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. 《挑战程序设计竞赛》2.1 穷竭搜索 POJ2718 POJ3187 POJ3050 AOJ0525

    POJ2718 Smallest Difference Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6509   Acce ...

  2. hadoop报错java.io.IOException: Bad connect ack with firstBadLink as 192.168.1.218:50010

    [root@linuxmain hadoop]# bin/hadoop jar hdfs3.jar com.dragon.test.CopyToHDFS Java HotSpot(TM) Client ...

  3. 使用 Docker 部署 MongoDB 复制集

    启用三个 mongod 建立复制集. MongoDB 版本选择目前最新的稳定版 3.6.2-jessie. docker run --name mongo0 -d mongo:3.6.2-jessie ...

  4. (转)免费天气预报接口API以及全国所有地区代码!!

    国家气象局提供的天气预报接口 接口地址: http://www.weather.com.cn/data/sk/101010100.html http://www.weather.com.cn/data ...

  5. 【DevExpress】 SearchLookUpEdit

    一.属性的基本介绍: 绑定数据源: lookUpEdit.Properties.ValueMember = 实际要用的字段;   //相当于Editvalue lookUpEdit.Propertie ...

  6. 使用GUID作为数据表主键的好处(转)

    http://blog.itpub.net/3875/viewspace-789520/ 分类: 数据库开发技术 使用GUID作为数据表主键的好处 [@more@] 使用GUID作为数据表主键的好处 ...

  7. lodash的使用

    Lodash是一个一致性.模块化.高性能的 JavaScript 实用工具库,内部封装了很多字符串.数组.对象等常见数据类型的处理函数. 为什么选择 Lodash ? Lodash 通过降低 arra ...

  8. Linux用户相关文件之组文件

    组信息文件: 1.文件地址: /etc/group -rw-r--r--. 1 root root 492 10月 6 21:56 /etc/group 2.文件内容: xiaol:x:500: 3. ...

  9. vue+django前后端分析解决csrf token问题

    vue-resource post数据 参考:https://www.cnblogs.com/linxizhifeng/p/8995077.html 阅读django CsrfViewMiddlewa ...

  10. python并发编程之多线程2---(死锁与递归锁,信号量等)

    一.死锁现象与递归锁 进程也是有死锁的 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用, 它们都将无法推进下去.此时称系统处于死锁状态或系统 ...