我们通常知道的答案是当删除子网的时候会会回调dhcp-agent的subnet_delete_end
函数。然后调用driver的restart
来重新加载dnsmasq进程,但今天我想说一点细节的东西。
##细节一:什么时候把一个网络分发到一个agent上去,
当第一个DHCP port创建后,会做2个件事情
- 为这个network schedule到一个agent上去
- 给所有个agent发送消息比如port_create_end
所以一个有意思的流程是,当一个subnet创建后,并不一定会通知dhcp_agent,因为要考虑这时候dhcp-port有没有创建,如果没有创建的话,说明连dhcp-agent也没有呢,自然不需要notify
那么什么时候创建dhcp-port呢?当一个subnet通过router-interface-add添加一个port的时候,就会触发dhcp-port的创建。然后schedule agent,
然后后续的subnet都会通知这些dhcp agents了
<% codeblock %>
def add_router_interface(self, context, router_id, interface_info):
add_by_port, add_by_sub = self._validate_interface_info(interface_info)
device_owner = self._get_device_owner(context, router_id)
if add_by_port:
port = self._add_interface_by_port(
context, router_id, interface_info['port_id'], device_owner)
elif add_by_sub:
port = self._add_interface_by_subnet(
context, router_id, interface_info['subnet_id'], device_owner)
super(L3_NAT_db_mixin, self).send_dhcp_notification(
context, {'port': port}, 'port.create.end')
<% endcodeblock %>
所以会发送一个创建port的指令,然后会schedule一个agent来负责这个network,然后agent会做如下操作:
- 拉subnet数据到agent
- 创建dhcp_port(实际上是从neutron server获得分配给本dhcp port的信息,比如ip mac啥的,实际还是在本地创建)
之后再创建subnet就会notify 这个agent了。
##细节二:DHCP Port上的IP什么时候删除的
当port/subnet有更新的时候,会走restart流程,然后
- 拉新的network数据
重建dhcp_port,一般调用update_dhcp_port,然后重新设置ip网关之类的
<% codeblock %>
def setup(self, network, reuse_existing=False):"""Create and initialize a device for network's DHCP on this host.""" port = self.setup_dhcp_port(network) interface_name = self.get_interface_name(network, port) if ip_lib.device_exists(interface_name, self.root_helper, network.namespace): if not reuse_existing: raise exceptions.PreexistingDeviceFailure( dev_name=interface_name) LOG.debug(_('Reusing existing device: %s.'), interface_name) else: self.driver.plug(network.id, port.id, interface_name, port.mac_address, namespace=network.namespace) ip_cidrs = [] for fixed_ip in port.fixed_ips: subnet = fixed_ip.subnet net = netaddr.IPNetwork(subnet.cidr) ip_cidr = '%s/%s' % (fixed_ip.ip_address, net.prefixlen) ip_cidrs.append(ip_cidr) if (self.conf.enable_isolated_metadata and self.conf.use_namespaces): ip_cidrs.append(METADATA_DEFAULT_CIDR) self.driver.init_l3(interface_name, ip_cidrs, namespace=network.namespace) # ensure that the dhcp interface is first in the list if network.namespace is None: device = ip_lib.IPDevice(interface_name, self.root_helper) device.route.pullup_route(interface_name) if self.conf.use_namespaces: self._set_default_route(network, port=port) return interface_name
<% endcodeblock %>
##细节二:在Neutron Server上,那个子网的IP什么时候删除的