1.neutron dhcp3个主要部件分别为什么?
2.dhcp模块包含哪些内容?
3.Dnsmasq配置文件是如何创建和更新的?
4.DHCP agent的信息存放在neutron数据库的哪个表中?

扩展: neutron-dhcp-agent在neutron的作用是什么?

一.概述

neutron dhcp为租户网络提供DHCP服务,即IP地址动态分配,另外还会提供metadata请求服务。
3个主要的部件:
DHCP agent scheduler:负责DHCP agent与network的调度
DHCP agent:为租户网络提供DHCP的功能,提供metadata request服务。
DHCP driver:即dnsmasq,用于管理DHCP server。

二.REST API

neutron dhcp提供2类REST API接口,这两类API都是extension API。
一种是 Agent Management Extension API:
<ignore_js_op> 
另一种是agent调度:
<ignore_js_op> 

三.总体架构

根据整个dhcp处理的流程,dhcp模块主要由Neutron api、core plugin(如linux bridge plugin,ovs plugin等)、dhcp agent scheduler、dhcp agent、dhcp driver(dnsmasq)构成。
架构图如下:
<ignore_js_op> 
对应架构图中数字,有以下几个接口:
1.network/subnet/port的操作
2.agent management/agent scheduler的操作
3.network/subnet/port操作会发送rpc请求到dhcp agent。
4.agentscheduler db发送rpc请求到dhcp agent。
5.dhcp agent通过DhcpPluginApi发送rpc请求到core plugin,操作相应的数据库。
6.dhcp agent调用dhcp driver进行dhcp相关操作。
四.代码分析
neutron-dhcp-agent的入口为neutron.agent.dhcp_agent:main,跟l3-agent的启动方式是类似的,都是以Service启动;Manager类为DhcpAgentWithStateReport,汇报DHCPAgent的状态。
  1. def main():
  2. register_options()
  3. common_config.init(sys.argv[1:])
  4. config.setup_logging(cfg.CONF)
  5. server = neutron_service.Service.create(
  6. binary='neutron-dhcp-agent',
  7. topic=topics.DHCP_AGENT,
  8. report_interval=cfg.CONF.AGENT.report_interval,
  9. manager='neutron.agent.dhcp_agent.DhcpAgentWithStateReport')
  10. service.launch(server).wait()

复制代码

DhcpAgentWithStateReport继承自DhcpAgent,用于汇报DHCPAgent的状态

  1. if report_interval:
  2. self.heartbeat = loopingcall.FixedIntervalLoopingCall(
  3. self._report_state)
  4. self.heartbeat.start(interval=report_interval)

复制代码

_report_state就是从self.cache中取出当前状态,然后构造一个report_state的message发到q-plugin topic的消息队列上。

下面看下DhcpAgent初始化过程:

  1. def __init__(self, host=None):
  2. super(DhcpAgent, self).__init__(host=host)
  3. self.needs_resync_reasons = []
  4. self.conf = cfg.CONF
  5. # Agent cache of the current network state
  6. self.cache = NetworkCache()
  7. self.root_helper = config.get_root_helper(self.conf)
  8. # dhcp_driver currently is neutron.agent.linux.dhcp.Dnsmasq
  9. self.dhcp_driver_cls = importutils.import_class(self.conf.dhcp_driver)
  10. ctx = context.get_admin_context_without_session()
  11. # init plugin rpc
  12. self.plugin_rpc = DhcpPluginApi(topics.PLUGIN,  # topic is q-plugin,提供DHCP相关的创建、查询、更新、删除接口
  13. ctx, self.conf.use_namespaces)
  14. # create dhcp dir to store dhcp info: /var/lib/neutron/dhcp/
  15. # these files are used for Dnsmasq
  16. dhcp_dir = os.path.dirname("/%s/dhcp/" % self.conf.state_path)
  17. if not os.path.isdir(dhcp_dir):
  18. os.makedirs(dhcp_dir, 0o755)
  19. self.dhcp_version = self.dhcp_driver_cls.check_version()
  20. # query existing_dhcp_networks from driver and then save them into self.cache
  21. self._populate_networks_cache()

复制代码

DhcpPluginApi创建了topic为q-plugin的处理方法,dhcp-agent外部可以通过DhcpAgentNotifyAPI来调用这些接口:

  1. class DhcpAgentNotifyAPI(n_rpc.RpcProxy):
  2. """API for plugin to notify DHCP agent."""
  3. BASE_RPC_API_VERSION = '1.0'
  4. # It seems dhcp agent does not support bulk operation
  5. VALID_RESOURCES = ['network', 'subnet', 'port']
  6. VALID_METHOD_NAMES = ['network.create.end',
  7. 'network.update.end',
  8. 'network.delete.end',
  9. 'subnet.create.end',
  10. 'subnet.update.end',
  11. 'subnet.delete.end',
  12. 'port.create.end',
  13. 'port.update.end',
  14. 'port.delete.end']

复制代码

neutron.agent.linux.dhcp.Dnsmasq

DhcpAgent通过self.dhcp_driver_cls = importutils.import_class(self.conf.dhcp_driver)注册了Dnsmasq这个Driver,并在需要的时候调用driver的相应接口:
  1. def call_driver(self, action, network, **action_kwargs):
  2. """Invoke an action on a DHCP driver instance."""
  3. LOG.debug(_('Calling driver for network: %(net)s action: %(action)s'),
  4. {'net': network.id, 'action': action})
  5. try:
  6. # the Driver expects something that is duck typed similar to
  7. # the base models.
  8. driver = self.dhcp_driver_cls(self.conf,
  9. network,
  10. self.root_helper,
  11. self.dhcp_version,
  12. self.plugin_rpc)
  13. getattr(driver, action)(**action_kwargs)
  14. return True

复制代码

Dnsmasq会通过/var/lib/neutron/dhcp/目录下的配置文件启动dnsmasq进程,在DHCP更新的时候,更新这些配置文件并reload配置。

  1. dnsmasq --no-hosts --no-resolv --strict-order
  2. --bind-interfaces --interface=tap746570b9-2b --except-interface=lo
  3. --pid-file=/var/lib/quantum/dhcp/3e16cd2f-c693-49b4-91a7-2a65912ec152/pid
  4. --dhcp-hostsfile=/var/lib/quantum/dhcp/3e16cd2f-c693-49b4-91a7-2a65912ec152/host
  5. --dhcp-optsfile=/var/lib/quantum/dhcp/3e16cd2f-c693-49b4-91a7-2a65912ec152/opts
  6. --dhcp-script=/usr/bin/quantum-dhcp-agent-dnsmasq-lease-update --leasefile-ro
  7. --dhcp-range=set:tag0,12.0.0.192,static,120s
  8. --conf-file= --domain=openstacklocal
  9. --bind-interfaces --interface=tap746570b9-2b
  10. 主要选项:
  11. --except-interface=lo 使多个dnsmasq实例可以同时运行在同一台主机上并监听不同的interface
  12. --dhcp-hostsfile=/var/lib/quantum/dhcp/3e16cd2f-c693-49b4-91a7-2a65912ec152/host 读取IP与虚拟机的静态映射关系,该文件改变后dnsmasq会自动重新加载,不需要重启
  13. --dhcp-optsfile=/var/lib/quantum/dhcp/3e16cd2f-c693-49b4-91a7-2a65912ec152/opts  指定DNS服务器地址等选项
  14. --dhcp-script=/usr/bin/quantum-dhcp-agent-dnsmasq-lease-update --leasefile-ro  lease信息更新与通知
  15. --dhcp-range=set:tag0,12.0.0.192,static,120s  重点在于static参数,该参数限制dnsmasq只能为dhcp-hostsfile包含的主机提供DHCP服务

复制代码

既然Dnsmasq是根据/var/lib/neutron/dhcp/目录下的配置文件启动的,那么这些配置文件是如何创建和更新的呢?
(1)创建过程
dhcp agent在收到network_create_end后,会启动一个dhcp(dnsmasq)进程服务这个新网络。
(2)更新过程

dhcp agent会调用dhcp_driver.reload_allocations来更新配置文件。reload_allocations会根据新网络配置重新生成配置文件。

dhcp agent会在收到如下4种消息时调用reload_allocations

  • port_update_end
  • port_delete_end
  • subnet_update_end
  • subnet_delete_end
上面这些通知消息在neturon rest API的前端实现中发出,具体代码在neutron.api.v2.base.py中
  1. #Controller
  2. notifier_method = self._resource + '.create.end'
  3. notifier_method = self._resource + '.delete.end'
  4. notifier_method = self._resource + '.update.end'

复制代码

可以看到针对每种resource(network, subnet, port),都会有相应的消息发出。dhcp agent根据这些消息来决定何时重新加载dnsmasp配置文件。

dhcp agent scheduler

通过dhcp agent scheduler,系统中可以部署多个dhcp agent:
1)增加可用性(HA, high availability),避免单点失败(SOF, single point of failure)
2)增加性能,多个dhcp agent可以安装在多台机器上,同时服务。

如何调度dhcp agent

调度算法通过network_scheduler_driver配置,默认是neutron.scheduler.dhcp_agent_scheduler.ChanceScheduler
class ChanceScheduler(object):
    """Allocate a DHCP agent for a network in a random way.
    More sophisticated scheduler (similar to filter scheduler in nova?)
    can be introduced later.
    """
可以看出,这个实现采用了随机分配算法。

如何调用dhcp agent scheduler

通过neutron.api.rpc.agentnotifiers.dhcp_rpc_agent_api.py中

def notify(self, context, data, method_name): 发送消息时,会调用
self._notify_agents,有代码
            schedule_required = method == 'port_create_end'
            if schedule_required:
                agents = self._schedule_network(admin_ctx, network, agents)

可以看到当系统中有新的port创建后,会调用dhcp agent scheduler分配dhcp agent。

dhcp服务的启动

  1. def after_start(self):
  2. self.run()
  3. LOG.info(_("DHCP agent started"))
  4. def run(self):
  5. """Activate the DHCP agent."""
  6. # 根据系统中的网络配置,启动dhcp服务器进程(dnsmasq)。
  7. # sync_state()在dhcp agent启动后运行一次。
  8. self.sync_state()
  9. # 周期性调用sync_state()
  10. # dhcp agent会缓存一些网路的信息,通过该任务和neutron同步网络信息,更新本地缓存。
  11. self.periodic_resync()

复制代码

neutron的各种插件实现(core plugin or service plugin)都继承于db包下的对象,这些object实现了对相应资源数据模型的操作。

五.类图

<ignore_js_op> 
六.数据库
DHCP agent的信息会存放在neutron数据库的agents表中:
  1. mysql> desc agents;
  2. +---------------------+---------------+------+-----+---------+-------+
  3. | Field               | Type          | Null | Key | Default | Extra |
  4. +---------------------+---------------+------+-----+---------+-------+
  5. | id                  | varchar(36)   | NO   | PRI | NULL    |       |
  6. | agent_type          | varchar(255)  | NO   |     | NULL    |       |
  7. | binary              | varchar(255)  | NO   |     | NULL    |       |
  8. | topic               | varchar(255)  | NO   |     | NULL    |       |
  9. | host                | varchar(255)  | NO   |     | NULL    |       |
  10. | admin_state_up      | tinyint(1)    | NO   |     | NULL    |       |
  11. | created_at          | datetime      | NO   |     | NULL    |       |
  12. | started_at          | datetime      | NO   |     | NULL    |       |
  13. | heartbeat_timestamp | datetime      | NO   |     | NULL    |       |
  14. | description         | varchar(255)  | YES  |     | NULL    |       |
  15. | configurations      | varchar(4095) | NO   |     | NULL    |       |
  16. +---------------------+---------------+------+-----+---------+-------+

复制代码

DHCP agent和network绑定关系存储在networkdhcpagentbindings中:

  1. mysql> desc networkdhcpagentbindings;
  2. +---------------+-------------+------+-----+---------+-------+
  3. | Field         | Type        | Null | Key | Default | Extra |
  4. +---------------+-------------+------+-----+---------+-------+
  5. | network_id    | varchar(36) | NO   | PRI | NULL    |       |
  6. | dhcp_agent_id | varchar(36) | NO   | PRI | NULL    |       |
  7. +---------------+-------------+------+-----+---------+-------+

复制代码

agents和networkdhcpagentbindings通过dhcp agent id建立引用关系。
网络,子网和端口信息分别存储在数据库的networks,subnets和ports表中。dhcp agent需要获取这些信息生成dnsmasq的配置信息,并将这些信息存储在/var/lib/neutron/dhcp/目录下。 当neutron-server有需要添加/修改/删除dhcp相关配置时,会将消息发送到队列dhcp_agent.hostname或dhcp_agent_fanout_id,dhcp agent收到消息后进行相应dhcp的配置。

相关文章

openstack Neutron分析(2)—— neutron-l3-agent

openstack Neutron分析(4)—— neutron-l3-agent中的iptables

openstack Neutron分析(5)-- neutron openvswitch agent

Openstack之neutron入门

Openstack之neutron入门二

Openstack之neutron入门三

http://www.aboutyun.com/thread-9533-1-1.html

openstack Neutron分析(3)—— neutron-dhcp-agent源码分析的更多相关文章

  1. $Django cbv源码分析 djangorestframework框架之APIView源码分析

    1 CBV的源码分析 #视图 class login (View): pass #路由 url(r'^books/$', views.login.as_view()) #阅读源码: #左侧工程栏--- ...

  2. 第十篇:Spark SQL 源码分析之 In-Memory Columnar Storage源码分析之 query

    /** Spark SQL源码分析系列文章*/ 前面讲到了Spark SQL In-Memory Columnar Storage的存储结构是基于列存储的. 那么基于以上存储结构,我们查询cache在 ...

  3. 第九篇:Spark SQL 源码分析之 In-Memory Columnar Storage源码分析之 cache table

    /** Spark SQL源码分析系列文章*/ Spark SQL 可以将数据缓存到内存中,我们可以见到的通过调用cache table tableName即可将一张表缓存到内存中,来极大的提高查询效 ...

  4. 深度 Mybatis 3 源码分析(一)SqlSessionFactoryBuilder源码分析

    MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java ...

  5. 源码分析系列1:HashMap源码分析(基于JDK1.8)

    1.HashMap的底层实现图示 如上图所示: HashMap底层是由  数组+(链表)+(红黑树) 组成,每个存储在HashMap中的键值对都存放在一个Node节点之中,其中包含了Key-Value ...

  6. [SPDK/NVMe存储技术分析]012 - 用户态ibv_post_send()源码分析

    OFA定义了一组标准的Verbs,并提供了一个标准库libibvers.在用户态实现NVMe over RDMA的Host(i.e. Initiator)和Target, 少不了要跟OFA定义的Ver ...

  7. 源码分析(一) HashMap 源码分析|JDK8

    HashMap是一个普遍应用于各大JAVA平台的最最最常用的数据结构.<K,V>的存储形式使HashMap备受广大java程序员的喜欢.JDK8中HashMap发生了很大的变化,例如:之前 ...

  8. Ambari Agent 源码分析

    一.ambari-agent 启动方式 Ambari-Agent的启动脚本为/etc/init.d/ambari-agent.该脚本主要实现了start,stop,status,restart,res ...

  9. openfalcon源码分析之agent

    本节内容 agent功能 1.1 agent上报数据 1.2 agent与HBS同步 1.3 agent Http服务 agent源码分析 2.1 初始化config配置 2.2 初始化根目录,本地I ...

随机推荐

  1. 巨蟒python全栈开发数据库前端9:bootstrap

    1.bootstrap的主网站: http://www.bootcss.com/ (1)bootstrap的CSS样式 (2)bootstrap组件 (3)JavaScript插件 (4)阿里图标库的 ...

  2. 巨蟒python全栈开发flask1

    1.整体把握 (1)路飞学城 - RestAPI 前后端分离开发 Django Vue.js - DRF DjangoRestFromwork - 线上商城的经验 (2)智能玩具 - RestAPI ...

  3. Sql注入基础一

    凡是带入数据库查询的都有可能是注入.     整个数据包 Sql注入原理? 网站数据传输中,接受变量传递的值未进行过滤,导致直接带入数据库查询执行的操作问题. Sql注入对于渗透的作用? 获取数据(网 ...

  4. crontab 问题分析 - CSDN博客 https://blog.csdn.net/tengdazhang770960436/article/details/50997297

    cd /mnt/tools/trunk/plugins/personas; python update_keywords.py crontab 问题分析  crontab 问题分析 - CSDN博客 ...

  5. Docker Metasploit Framework

    https://hub.docker.com/r/usertaken/metasploit-framework/ docker pull usertaken/metasploit-framework ...

  6. VS中没有为此解决方案配置选中要生成的项目

    菜单->生成->配置管理器->给要生成的项目打钩

  7. box-shadow阴影效果

    .shadowBox{ -moz-box-shadow:5px 5px 5px #A9A9A9; -webkit-box-shadow:5px 5px 5px #A9A9A9; box-shadow: ...

  8. Django报:builtin_function_or_method' object is not iterable

    def detail(request,hero_id): hero=models.HeroInfo.objects.get(id=hero_id) return render_to_response( ...

  9. Python3.6全栈开发实例[011]

    11.元素分类有如下值li= [11,22,33,44,55,66,77,88,99,90],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中.即: {'k ...

  10. servlet 3.0 的新特性之三对异步处理的支持

    一.异步处理 1. 什么是异步处理 原来,在服务器没有结束响应之前,浏览器是看不到响应内容的!只有响应结束时,浏览器才能显示结果! 现在异步处理的作用:在服务器开始响应后,浏览器就可以看到响应内容,不 ...