赞
踩
NEUTRONDHCP为租户网络提供DHCP服务,即IP地址动态分配,另外还会提供metadata请求服务(元数据是描述数据属性的信息,也就是数据的数据)。根据整个DHCP处理的流程,DHCP模块主要由DHCP agent scheduler、DHCP agent、DHCP driver构成:
DHCP agent scheduler:负责DHCP agent与network的调度
DHCP agent:为租户网络提供DHCP的功能,提供metadatarequest服务
DHCP driver:用于管理DHCPserver,目前环境中是采用的dnsmasq。
对应架构图中数字,有以下几个操作:
当dashboard(openstack的web界面)上执行network/subnet/port的操作时,会调用neutron-api通知CorePlugin(如linux bridge plugin,ovs plugin等),创建相应虚拟network/subnet/port。
agentmanagement/agent scheduler里面会通过调度算法调度DHCP agent
network/subnet/port操作会发送rpc请求到DHCP agent。
agentschedulerdb发送rpc请求到DHCP agent。
DHCP agent通过DhcpPluginApi发送rpc请求到coreplugin,操作相应的数据库。
DHCP agent调用dhcpdriver实现DHCP server的管理。
通过DHCP agent scheduler,系统中可以部署多个dhcp agent,增加可用性(HA, highavailability),避免单点失败(SOF,single point of failure);多个dhcp agent可以安装在多台机器上,同时服务。
DHCP agent的调度算法可以在/etc/neutron/neutron.conf文件中设置,默认设置是neutron.scheduler.dhcp_agent_scheduler.ChanceScheduler,这个实现是采用了随机分配算法。另外还有一种调度算法是根据agent的权重,进行负载均衡。
network_scheduler_driver = neutron.scheduler.dhcp_agent_scheduler.WeightScheduler
调度算法通过network_scheduler_driver的实现在neutron/scheduler/dhcp_agent_scheduler.py。
系统默认使用的是随机分配算法,下面是DHCP agent的随机调度算法部分代码:
#neutron/scheduler/base_scheduler.py
class BaseChanceScheduler(BaseScheduler):
"""Choose agents randomly."""
def __init__(self, resource_filter):
self.resource_filter = resource_filter
def select(self, plugin, context, resource_hostable_agents,
resource_hosted_agents, num_agents_needed):
chosen_agents = random.sample(resource_hostable_agents,
num_agents_needed)
return chosen_agents
根据agent的权重调度的方法,是比较常用的方法,有利于负载均衡。所以本节以WeightScheduler为例,分析一个网络使用一个DHCP agent的情况,是如何调度的。目前环境中在controller上和computer分别安装一个DHCP agent,并把DHCP agent调度算法设置成按权重调度。
network_scheduler_driver = neutron.scheduler.dhcp_agent_scheduler.WeightScheduler
调度算法的代码如下:在neutron/scheduler/dhcp_agent_scheduler.py:
class BaseWeightScheduler(BaseScheduler):
"""Choose agents randomly."""
def __init__(self, resource_filter):
self.resource_filter = resource_filter
def select(self, plugin, context, resource_hostable_agents,
resource_hosted_agents, num_agents_needed):
chosen_agents = sorted(resource_hostable_agents,
key=attrgetter('load'))[0:num_agents_needed]
return chosen_agents
调度算法的代码如下:在neutron/scheduler/dhcp_agent_scheduler.py:BaseWeightScheduler:select处设置pdb断点查看
调用栈如下:
根据调用栈看下首先schedule函数的调度过程,代码如下。首先从所有的DHCP agents里面通过self.resource_filter.filter_agent函数选出可供使用的DHCP agent,下面分别介绍该函数和self.select函数。
#neutron/scheduler/base_scheduler.py def schedule(self, plugin, context, resource): """Select and bind agents to a given resource.""" if not self.resource_filter: return # filter the agents that can host the resource filtered_agents_dict = self.resource_filter.filter_agents( plugin, context, resource) num_agents = filtered_agents_dict['n_agents'] hostable_agents = filtered_agents_dict['hostable_agents'] hosted_agents = filtered_agents_dict['hosted_agents'] chosen_agents = self.select(plugin, context, hostable_agents, hosted_agents, num_agents) # bind the resource to the agents self.resource_filter.bind(context, chosen_agents, resource['id']) return chosen_agents
self.resource_filter.filter_agent的返回值是一个字典,字典有3个key值。代码如下:
#neutron/scheduler/dhcp_agent_scheduler.py def filter_agents(self, plugin, context, network): """Return the agents that can host the network. This function returns a dictionary which has 3 keys. n_agents: The number of agents should be scheduled. If n_agents=0, all networks are already scheduled or no more agent can host the network. hostable_agents: A list of agents which can host the network. hosted_agents: A list of agents which already hosts the network. """ agents_dict = self._get_network_hostable_dhcp_agents( plugin, context, network) if not agents_dict['hostable_agents'] or agents_dict['n_agents'] <= 0: return {'n_agents': 0, 'hostable_agents': [], 'hosted_agents': agents_dict['hosted_agents']} return agents_dict
第一个KEY 'n_agents’代表需要调度几个dhcpagents,默认是一个。这个可以修改配置文件进行修改:
dhcp_agents_per_network = 1
第二个KEY’hostable_agents’代表可以使用的DHCP agent,这里面记录着每个agent的详细信息,如下:
<neutron.db.agents_db.Agent[objectat 56fd5d0] {id=u’21ea8426-5e68-4f83-abd6-3451e426511e’, agent_type=u’DHCP agent’,binary=u’neutron-dhcp-agent’, topic=u’dhcp_agent’, host=u’computer35’,availability_zone=u’nova’, admin_state_up=True,created_at=datetime.datetime(2016, 10, 19, 7, 33, 14),started_at=datetime.datetime(2016, 10, 19, 7, 33, 14), heartbeat_timestamp=datetime.datetime(2016,10, 19, 8, 58, 32), description=None, configurations=u’{“subnets”: 2,“dhcp_lease_duration”: 86400, “dhcp_driver”:“neutron.agent.linux.dhcp.Dnsmasq”, “networks”: 2,“log_agent_heartbeats”: false, “ports”: 2}’,resource_versions=None, load=2}>
记录着 id,宿主机,创建时间,该DHCP agent上创建了几个DHCP server的服务等等。
第三个KEY’hosted_agents’代表的意思是,已经为该网络创建DHCP服务的agent,我们的环境是每个网络使用一个DHCP agent服务,所以该值为空的列表。
那么这么多agents,是如何选举出最优的agent的呢?看下面的选举代码:
#neutron/scheduler/base_scheduler.py
def select(self, plugin, context, resource_hostable_agents,
resource_hosted_agents, num_agents_needed):
chosen_agents = sorted(resource_hostable_agents,
key=attrgetter('load'))[0:num_agents_needed]
return chosen_agents
上面得到了所有DHCP agent的详细信息,其中’load’参数记录着DHCP agent服务的网络个数。根据这个参数进行排序,把’load’值最小的agent选举出来。
首先通过查看setup.cfg文件,查找dhcp服务的启动路径。
[entry_points]
console_scripts =
neutron-db-manage = neutron.db.migration.cli:main
neutron-debug = neutron.debug.shell:main
neutron-dhcp-agent = neutron.cmd.eventlet.agents.dhcp:main
进入neutron/cmd/eventlet/agents/dhcp.py,可以查看的main函数的启动代码。与l2agent l3agent一样都是创建一个rpc-service对象。rpc-service的manager类为neutron.agent.dhcp.agent.DhcpAgentWithStateReport对象。
#/neutron/agent/dhcp_agent.py: main def register_options(conf): config.register_interface_driver_opts_helper(conf) config.register_agent_state_opts_helper(conf) config.register_availability_zone_opts_helper(conf) conf.register_opts(dhcp_config.DHCP_AGENT_OPTS) conf.register_opts(dhcp_config.DHCP_OPTS) conf.register_opts(dhcp_config.DNSMASQ_OPTS) conf.register_opts(metadata_config.DRIVER_OPTS) conf.register_opts(metadata_config.SHARED_OPTS) conf.register_opts(interface.OPTS) def main(): register_options(cfg.CONF) common_config.init(sys.argv[1:]) config.setup_logging() server = neutron_service.Service.create( binary='neutron-dhcp-agent', topic=topics.DHCP_AGENT, report_interval=cfg.CONF.AGENT.report_interval, manager='neutron.agent.dhcp.agent.DhcpAgentWithStateReport') service.launch(cfg.CONF, server).wait()
manager类的具体实现代码目录在neutron/agent/dhcp/agent.py,文件中DhcpAgentWithStateReport继承自DhcpAgent,用于汇报DHCPAgent的状态。在分析start函数之前,先分析首先neutron.agent.dhcp.agent.DhcpAgentWithStateReport对象的创建过程。
DhcpAgentWithStateReport类继承DhcpAgent类,DhcpAgentWithStateReport类的作用主要是创建一个协程定时向neutron-server启动时开启的rpc-server上报neutron-dhcp-agent的服务或network状态,然后通过neutron-server的core plugin将状态更新到数据库中。
DhcpAgent类才是为neutron-dhcp-agent服务做主要工作的。初始化代码如下:
#/neutron/agent/dhcp/agent.py: DhcpAgentWithStateReport class DhcpAgent(manager.Manager): """DHCP agent service manager. Note that the public methods of this class are exposed as the server side of an rpc interface. The neutron server uses neutron.api.rpc.agentnotifiers.dhcp_rpc_agent_api.DhcpAgentNotifyApi as the client side to execute the methods here. For more information about changing rpc interfaces, see doc/source/devref/rpc_api.rst. """ target = oslo_messaging.Target(version='1.0') def __init__(self, host=None, conf=None): super(DhcpAgent, self).__init__(host=host) self.needs_resync_reasons = collections.defaultdict(list) self.conf = conf or cfg.CONF self.cache = NetworkCache() self.dhcp_driver_cls = importutils.import_class(self.conf.dhcp_driver) ctx = context.get_admin_context_without_session() self.plugin_rpc = DhcpPluginApi(topics.PLUGIN, ctx, self.conf.host) # create dhcp dir to store dhcp info dhcp_dir = os.path.dirname("/%s/dhcp/" % self.conf.state_path) utils.ensure_dir(dhcp_dir) self.dhcp_version = self.dhcp_driver_cls.check_version() self._populate_networks_cache() # keep track of mappings between networks and routers for # metadata processing self._metadata_routers = {} # {network_id: router_id} self._process_monitor = external_process.ProcessMonitor( config=self.conf, resource_type='dhcp')
其中self.cache = NetworkCache()主要保存底层的active的dhcp networks信息,这些信息会通过DhcpAgentWithStateReport类的_report_state方法上报到数据库中。
dhcp_dir=os.path.dirname("/%s/dhcp/" % self.conf.state_path)创建了一个目录,其中self.conf.state_path的配置(在/etc/neutron/dhcp_agent.ini配置文件中)为:
state_path=/var/lib/neutron
在该目录下将会保存创建的dhcp networks的相关信息。
self.dhcp_driver_cls=importutils.import_class(self.conf.dhcp_driver)中的dhcp_driver也为/etc/neutron/dhcp_agent.ini配置文件中参数。
dhcp_driver = neutron.agent.Linux.dhcp.Dnsmasq
self.dhcp_driver_cls是Dnsmasq的类实例。
首先看下rpc-service的start代码,代码路径在neutron/service.py
#/neutron/service.py:Service def start(self): self.manager.init_host() super(Service, self).start() if self.report_interval: pulse = loopingcall.FixedIntervalLoopingCall(self.report_state) pulse.start(interval=self.report_interval, initial_delay=self.report_interval) self.timers.append(pulse) if self.periodic_interval: if self.periodic_fuzzy_delay: initial_delay = random.randint(0, self.periodic_fuzzy_delay) else: initial_delay = None periodic = loopingcall.FixedIntervalLoopingCall( self.periodic_tasks) periodic.start(interval=self.periodic_interval, initial_delay=initial_delay) self.timers.append(periodic) self.manager.after_start()
rpc-service start的时候会调用agent的init_host函数。下面分析self.manager.init_host()
#/neutron/agent/dhcp/agent.py:DhcpAgent def init_host(self): self.sync_state() #/neutron/agent/dhcp/agent.py:DhcpAgent @utils.synchronized('dhcp-agent') def sync_state(self, networks=None): """Sync the local DHCP state with Neutron. If no networks are passed, or 'None' is one of the networks, sync all of the networks. """ only_nets = set([] if (not networks or None in networks) else networks) LOG.info(_LI('Synchronizing state')) pool = eventlet.GreenPool(self.conf.num_sync_threads) known_network_ids = set(self.cache.get_network_ids()) try: active_networks = self.plugin_rpc.get_active_networks_info() LOG.info(_LI('All active networks have been fetched through RPC.')) active_network_ids = set(network.id for network in active_networks) for deleted_id in known_network_ids - active_network_ids: try: self.disable_dhcp_helper(deleted_id) except Exception as e: self.schedule_resync(e, deleted_id) LOG.exception(_LE('Unable to sync network state on ' 'deleted network %s'), deleted_id) for network in active_networks: if (not only_nets or # specifically resync all network.id not in known_network_ids or # missing net network.id in only_nets): # specific network to sync pool.spawn(self.safe_configure_dhcp_for_network, network) pool.waitall() LOG.info(_LI('Synchronizing state complete')) except Exception as e: if only_nets: for network_id in only_nets: self.schedule_resync(e, network_id) else: self.schedule_resync(e) LOG.exception(_LE('Unable to sync network state.'))
sync_state函数主要功能是根据数据库同步底层的networks信息,即将self.cache(底层保存的dhcpnetworks信息)与通过active_networks=self.plugin_rpc.get_active_networks_info()函数获取的数据库中的networks信息作比较,将未在数据库中的底层networks从self.cache中进行移除。其中self.cache中的networks信息在创建DhcpAgent类的__init__函数的self._populate_networks_cache()代码进行实现.
在将未在数据库中的底层的dhcpnetworks从self.cache中进行移除后,将更新active的dhcp networks信息。
#/neutron/agent/dhcp/agent.py:DhcpAgent @utils.exception_logger() def safe_configure_dhcp_for_network(self, network): try: network_id = network.get('id') LOG.info(_LI('Starting network %s dhcp configuration'), network_id) self.configure_dhcp_for_network(network) LOG.info(_LI('Finished network %s dhcp configuration'), network_id) except (exceptions.NetworkNotFound, RuntimeError): LOG.warning(_LW('Network %s may have been deleted and ' 'its resources may have already been disposed.'), network.id) #/neutron/agent/dhcp/agent.py:DhcpAgent def configure_dhcp_for_network(self, network): if not network.admin_state_up: return enable_metadata = self.dhcp_driver_cls.should_enable_metadata( self.conf, network) dhcp_network_enabled = False for subnet in network.subnets: if subnet.enable_dhcp: if self.call_driver('enable', network): dhcp_network_enabled = True self.cache.put(network) break if enable_metadata and dhcp_network_enabled: for subnet in network.subnets: if subnet.ip_version == 4 and subnet.enable_dhcp: self.enable_isolated_metadata_proxy(network) break elif (not self.conf.force_metadata and not self.conf.enable_isolated_metadata): # In the case that the dhcp agent ran with metadata enabled, # and dhcp agent now starts with metadata disabled, check and # delete any metadata_proxy. self.disable_isolated_metadata_proxy(network)
从代码层面也可以看出:
一个network下可以创建多个subnet。
self.cache中存放的是至少有一个subnetenable dhcp的network。
如果network中的subnets全部都未enabledhcp,则self.cache将不会存放该network。
在有subnetenabledhcp的network下将执行self.call_driver(‘enable’,network)代码。将在下一章介绍。
这里就完成了neutron-agent的start的过程。
DHCP agent对外的提供的API接口在neutron/api/agentnotifiers/dhcp_rpc_agent_api.py里面,当网络变化时,比如网络创建和删除,会通过API调用DHCP driver。
#neutron/api/agentnotifiers/dhcp_rpc_agent_api.py
class DhcpAgentNotifyAPI(object):
"""API for plugin to notify DHCP agent.
VALID_RESOURCES = ['network', 'subnet', 'port']
VALID_METHOD_NAMES = ['network.create.end',
'network.update.end',
'network.delete.end',
'subnet.create.end',
'subnet.update.end',
'subnet.delete.end',
'port.create.end',
'port.update.end',
'port.delete.end']
可以看network/subnet/port的创建、删除和更新都会通知到DHCP agent, DHCPagent里面有对应的回调函数。
#/neutron/agent/dhcp/agent.py:DhcpAgent @utils.synchronized('dhcp-agent') def network_create_end(self, context, payload): """Handle the network.create.end notification event.""" network_id = payload['network']['id'] self.enable_dhcp_helper(network_id) #/neutron/agent/dhcp/agent.py:DhcpAgent @utils.synchronized('dhcp-agent') def network_update_end(self, context, payload): """Handle the network.update.end notification event.""" #/neutron/agent/dhcp/agent.py:DhcpAgent @utils.synchronized('dhcp-agent') def network_delete_end(self, context, payload): """Handle the network.delete.end notification event.""" #/neutron/agent/dhcp/agent.py:DhcpAgent @utils.synchronized('dhcp-agent') def subnet_update_end(self, context, payload): """Handle the subnet.update.end notification event.""" #/neutron/agent/dhcp/agent.py:DhcpAgent @utils.synchronized('dhcp-agent') def subnet_delete_end(self, context, payload): """Handle the subnet.delete.end notification event.""" #/neutron/agent/dhcp/agent.py:DhcpAgent @utils.synchronized('dhcp-agent') def port_update_end(self, context, payload): """Handle the port.update.end notification event.""" #/neutron/agent/dhcp/agent.py:DhcpAgent @utils.synchronized('dhcp-agent') def port_delete_end(self, context, payload): """Handle the port.delete.end notification event."""
我们以network创建为例,分析HDCP agent如何调用DHCP driver 启动DHCP server服务的。
#/neutron/agent/dhcp/agent.py:DhcpAgent @utils.synchronized('dhcp-agent') def network_create_end(self, context, payload): """Handle the network.create.end notification event.""" network_id = payload['network']['id'] self.enable_dhcp_helper(network_id) #/neutron/agent/dhcp/agent.py:DhcpAgent def enable_dhcp_helper(self, network_id): """Enable DHCP for a network that meets enabling criteria.""" network = self.safe_get_network_info(network_id) if network: self.configure_dhcp_for_network(network) #/neutron/agent/dhcp/agent.py:DhcpAgent def configure_dhcp_for_network(self, network): if not network.admin_state_up: return enable_metadata = self.dhcp_driver_cls.should_enable_metadata( self.conf, network) dhcp_network_enabled = False for subnet in network.subnets: if subnet.enable_dhcp: if self.call_driver('enable', network): dhcp_network_enabled = True self.cache.put(network) break if enable_metadata and dhcp_network_enabled: for subnet in network.subnets: if subnet.ip_version == 4 and subnet.enable_dhcp: self.enable_isolated_metadata_proxy(network) break elif (not self.conf.force_metadata and not self.conf.enable_isolated_metadata): # In the case that the dhcp agent ran with metadata enabled, # and dhcp agent now starts with metadata disabled, check and # delete any metadata_proxy. self.disable_isolated_metadata_proxy(network)
DhcpAgent通过self.dhcp_driver_cls = importutils.import_class(self.conf.dhcp_driver)注册了Dnsmasq这个Driver,并在需要的时候调用driver的相应接口。
当创建网络的时候,发现子网里面需要开启DHCP server,则调用self.call_driver(‘enable’, network)。会创建一个DHCP服务,这个通过命令可以看到。
当删除网络时候,发现已经开启了DHCP server,那么就要删除掉DHCP server,则调用接口self.call_driver(‘disable’, network)。
当子网和port添加和删除的时候,与网络有所不同,是调用的self.call_driver(‘reload_allocations’, network),进行更新配置操作数据。这块代码最终会调用DHCP driver部分。
下面看下DHCP dirver 是怎么通过Dnsmasq管理DHCP server服务的。
Dnsmasq是根据/var/lib/neutron/dhcp/目录下的配置文件启动的,根据第3节内容总结,可以知道这些配置文件是如何创建和更新的:
(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中
#neutron/api/v2/base.py
notifier_method = self._resource + '.create.end'
notifier_method = self._resource + '.delete.end'
notifier_method = self._resource + '.update.end'
可以看到针对每种resource(network, subnet, port),都会有相应的消息发出。dhcp agent根据这些消息来决定何时重新加载dnsmasp配置文件。
self.call_driver根据网络和端口的变化,会调用/neutron/linux/dhcp.py代码。这里是self.call_driver(‘enable’,network)等不同的操作的具体实现。
当创建一个网络,并且在子网上开启DHCP服务时,会调用如下的代码:
#/neutron/linux/dhcp.py
def enable(self):
"""Enables DHCP for this network by spawning a local process."""
if self.active:
self.restart()
elif self._enable_dhcp():
common_utils.ensure_dir(self.network_conf_dir)
interface_name = self.device_manager.setup(self.network)
self.interface_name = interface_name
self.spawn_process()
Neutron为每个 network启动一个 Dnsmasq进程,比如:
oot@network:/home/s1# ps -ef | grep dnsmasq
nobody 1198 1 0 18:51 ? 00:00:00 dnsmasq --no-hosts --no-resolv --strict-order --bind-interfaces --interface=tap8dfd0bd8-45 --except-interface=lo --pid-file=/var/lib/neutron/dhcp/d04a0a06-7206-4d05-9432-3443843bc199/pid --dhcp-hostsfile=/var/lib/neutron/dhcp/d04a0a06-7206-4d05-9432-3443843bc199/host --addn-hosts=/var/lib/neutron/dhcp/d04a0a06-7206-4d05-9432-3443843bc199/addn_hosts --dhcp-optsfile=/var/lib/neutron/dhcp/d04a0a06-7206-4d05-9432-3443843bc199/opts --leasefile-ro --dhcp-range=set:tag0,10.0.11.0,static,86400s --dhcp-lease-max=256 --conf-file=/etc/neutron/dnsmasq.conf --domain=openstacklocal
nobody 1201 1 0 18:51 ? 00:00:00 dnsmasq --no-hosts --no-resolv --strict-order --bind-interfaces --interface=tap6356d532-32 --except-interface=lo --pid-file=/var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/pid --dhcp-hostsfile=/var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/host --addn-hosts=/var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/addn_hosts --dhcp-optsfile=/var/lib/neutron/dhcp/0a4cd030-d951-401a-8202-937b788bea43/opts --leasefile-ro --dhcp-range=set:tag0,10.0.0.0,static,86400s --dhcp-lease-max=256 --conf-file=/etc/neutron/dnsmasq.conf --domain=openstacklocal
用到的几个参数的意义如下:
–no-hosts: Don’t read the hostnames in /etc/hosts.
–bind-interfaces: Setting this option also enables multiple instances ofdnsmasq which provide DHCP service to run in the same machine.
–interface: Listen only on the specified interface(s). 在指定的 interface上监听 DHCP请求。
–dhcp-hostsfile: Read DHCP host information from the specified file. Theadvantage of storing DHCP host information in this file is that it can bechanged without re-starting dnsmasq: the file will be re-read when dnsmasqreceives SIGHUP. DHCP host 文件,dnsmasq收到 SIGHUP后会重新读入。没看到 Neutron code发出该信息,而似乎每次都重启dnsmasq进程。
–addn-hosts:Additional hosts file. The file will be re-read when dnsmasq receives SIGHUP.
–dhcp-optsfile:Read DHCP option information from the specified file when dnsmasq receivingSIGHUP.
–dhcp-range:Enable the DHCP server. This option may be repeated, with differentaddresses, to enable DHCP service to more than one network. dnsmasq默认关闭DHCP功能,该选项开启该功能。每个开启了 DHCP的 subnet 拥有一个该项。
–dhcp-lease-max: Limits dnsmasq to the specified maximum number of DHCP leasesto prevent DoS attacks from hosts.
–domain: Specifies DNS domains for the DHCP server.
这些数据皆由数据库中数据计算得出。
dnsmasq默认地将日志写到 /var/log/syslog中。可以在 Neutron节点上做如下配置,使得它使用别的log文件以便调试:
(1)创建文件 /etc/neutron/dnsmasq.conf,在其中添加
log-facility = /var/log/neutron/dnsmasq.log
log-dhcp
(2)添加下面行到 /etc/neutron/dhcp_agent.ini:
dnsmasq_config_file = /etc/neutron/dnsmasq.conf
(3)运行下面命令重启 Neutron DHCP agent:
sudo service neutron-dhcp-agent restart
经过以上步骤,Dnsmasq 准备好相应虚机的IP 申请请求了,它:准备好了 host 文件,里面有每个虚机的 MAC 地址和 IP 对照表;绑定了 interface,可以收到请求;启动好了进程,可以为指定的 subnet服务。
获取 IP 的过程如下:
(1)虚机 VM_1开机,发出 DHCPDISCOVER广播,该广播消息在整个 network中都可以被收到。
(2)广播到达 tap6356d532-32,Dnsmasq在它上面监听。它检查其 host文件,发现有对应项,它以 DHCPOFFER消息将 IP和 gateway IP发回到 VM_1。如果有其他DHCP Server的话,它们也可能会发回IP地址。
(3)VM_1发回 DHCPREQUEST消息确认只接受第二步发的 DHCPOFFER,别的 DHCP Server给的 IP可以自行收回了。
(4)Dnsmasq发回确认消息 DHCPACK,整个过程结束。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。