diff --git a/neunton/agent/l3_agent.py b/neunton/agent/l3_agent.py index 79156cd..0037b80 100644 --- a/neunton/agent/l3_agent.py +++ b/neunton/agent/l3_agent.py @@ -23,6 +23,7 @@ import eventlet from eventlet import semaphore import netaddr from oslo.config import cfg +from quantum.agent.linux.interface import OVSInterfaceDriver from neunton.agent.common import config from neunton.agent.linux import external_process @@ -233,7 +234,8 @@ class L3NATAgent(manager.Manager): for c, r in self.metadata_nat_rules(): ri.iptables_manager.ipv4['nat'].add_rule(c, r) ri.iptables_manager.apply() - self._spawn_metadata_proxy(ri) + if self.conf.use_namespaces: + self._spawn_metadata_proxy(ri) def _router_removed(self, router_id): ri = self.router_info[router_id] @@ -246,7 +248,8 @@ class L3NATAgent(manager.Manager): for c, r in self.metadata_nat_rules(): ri.iptables_manager.ipv4['nat'].remove_rule(c, r) ri.iptables_manager.apply() - self._destroy_metadata_proxy(ri) + if self.conf.use_namespaces: + self._destroy_metadata_proxy(ri) del self.router_info[router_id] self._destroy_router_namespace(ri.ns_name()) @@ -370,7 +373,9 @@ class L3NATAgent(manager.Manager): ri.floating_ips.append(new_fip) def _get_ex_gw_port(self, ri): - return ri.router.get('gw_port') + rv = ri.router.get('gw_port') + LOG.debug("***SV::_get_ex_gw_port: {0}".format(rv)) + return rv def _send_gratuitous_arp_packet(self, ri, interface_name, ip_address): if self.conf.send_arp_for_ha > 0: @@ -390,49 +395,78 @@ class L3NATAgent(manager.Manager): LOG.error(_("Failed sending gratuitous ARP: %s"), str(e)) def get_internal_device_name(self, port_id): - return (INTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN] + devname = INTERNAL_DEV_PREFIX + port_id + LOG.debug("***SV::get_internal_device_name: {0}".format(devname)) + return devname[:self.driver.DEV_NAME_LEN] def get_external_device_name(self, port_id): - return (EXTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN] + devname = EXTERNAL_DEV_PREFIX + port_id + LOG.debug("***SV::get_external_device_name: {0}".format(devname)) + return devname[:self.driver.DEV_NAME_LEN] - def external_gateway_added(self, ri, ex_gw_port, internal_cidrs): + def get_effective_interface_name(self, ifname): + if not self.conf.use_namespaces: + return self.conf.external_network_bridge + else: + return ifname + def external_gateway_added(self, ri, ex_gw_port, internal_cidrs): + ### SV: patched !!! interface_name = self.get_external_device_name(ex_gw_port['id']) + effective_interface_name = self.get_effective_interface_name(interface_name) ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address'] - if not ip_lib.device_exists(interface_name, - root_helper=self.root_helper, - namespace=ri.ns_name()): + ip_address = ex_gw_port['ip_cidr'].split('/')[0] + if not ip_lib.device_exists(interface_name, root_helper=self.root_helper, namespace=ri.ns_name()): self.driver.plug(ex_gw_port['network_id'], ex_gw_port['id'], interface_name, ex_gw_port['mac_address'], bridge=self.conf.external_network_bridge, namespace=ri.ns_name(), - prefix=EXTERNAL_DEV_PREFIX) - self.driver.init_l3(interface_name, [ex_gw_port['ip_cidr']], - namespace=ri.ns_name()) - ip_address = ex_gw_port['ip_cidr'].split('/')[0] - self._send_gratuitous_arp_packet(ri, interface_name, ip_address) + prefix=EXTERNAL_DEV_PREFIX + ) + + if not self.conf.use_namespaces: + LOG.info("Warning! You are not using network namespaces! " + "IP {ip} will be assigned to interface {iface}, instead {eiface}." + .format( + ip=ex_gw_port['ip_cidr'], + iface=interface_name, + eiface=effective_interface_name + ) + ) + net = netaddr.IPNetwork(ex_gw_port['ip_cidr']) + device = ip_lib.IPDevice(effective_interface_name, self.root_helper, namespace=ri.ns_name()) + device.addr.add(net.version, ex_gw_port['ip_cidr'], str(net.broadcast)) + else: + self.driver.init_l3(interface_name, [ex_gw_port['ip_cidr']], namespace=ri.ns_name()) + + self._send_gratuitous_arp_packet(ri, effective_interface_name, ip_address) gw_ip = ex_gw_port['subnet']['gateway_ip'] - if ex_gw_port['subnet']['gateway_ip']: - cmd = ['route', 'add', 'default', 'gw', gw_ip] - if self.conf.use_namespaces: - ip_wrapper = ip_lib.IPWrapper(self.root_helper, - namespace=ri.ns_name()) - ip_wrapper.netns.execute(cmd, check_exit_code=False) - else: - utils.execute(cmd, check_exit_code=False, - root_helper=self.root_helper) + if interface_name == effective_interface_name: + # work in net.namespaces, or 1st assignation on this interface + if ex_gw_port['subnet']['gateway_ip']: + cmd = ['route', 'add', 'default', 'gw', gw_ip] + if self.conf.use_namespaces: + ip_wrapper = ip_lib.IPWrapper(self.root_helper, namespace=ri.ns_name()) + ip_wrapper.netns.execute(cmd, check_exit_code=False) + else: + utils.execute(cmd, check_exit_code=False, root_helper=self.root_helper) - for (c, r) in self.external_gateway_nat_rules(ex_gw_ip, - internal_cidrs, - interface_name): + for (c, r) in self.external_gateway_nat_rules(ex_gw_ip, internal_cidrs, effective_interface_name): ri.iptables_manager.ipv4['nat'].add_rule(c, r) ri.iptables_manager.apply() def external_gateway_removed(self, ri, ex_gw_port, internal_cidrs): - interface_name = self.get_external_device_name(ex_gw_port['id']) + effective_interface_name = self.get_effective_interface_name(interface_name) + ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address'] + + if not self.conf.use_namespaces: + net = netaddr.IPNetwork(ex_gw_ip) + device = ip_lib.IPDevice(effective_interface_name, self.root_helper, namespace=ri.ns_name()) + device.addr.delete(net.version, ex_gw_ip) + if ip_lib.device_exists(interface_name, root_helper=self.root_helper, namespace=ri.ns_name()): @@ -441,9 +475,7 @@ class L3NATAgent(manager.Manager): namespace=ri.ns_name(), prefix=EXTERNAL_DEV_PREFIX) - ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address'] - for c, r in self.external_gateway_nat_rules(ex_gw_ip, internal_cidrs, - interface_name): + for c, r in self.external_gateway_nat_rules(ex_gw_ip, internal_cidrs, effective_interface_name): ri.iptables_manager.ipv4['nat'].remove_rule(c, r) ri.iptables_manager.apply() @@ -463,6 +495,7 @@ class L3NATAgent(manager.Manager): def external_gateway_nat_rules(self, ex_gw_ip, internal_cidrs, interface_name): + ### SV: need-patch !!! rules = [('POSTROUTING', '! -i %(interface_name)s ' '! -o %(interface_name)s -m conntrack ! ' '--ctstate DNAT -j ACCEPT' % locals())] @@ -475,7 +508,7 @@ class L3NATAgent(manager.Manager): interface_name = self.get_internal_device_name(port_id) if not ip_lib.device_exists(interface_name, root_helper=self.root_helper, - namespace=ri.ns_name()): + namespace=ri.ns_name()): # check existing MAC address of qr_* self.driver.plug(network_id, port_id, interface_name, mac_address, namespace=ri.ns_name(), prefix=INTERNAL_DEV_PREFIX) @@ -513,27 +546,38 @@ class L3NATAgent(manager.Manager): return rules def floating_ip_added(self, ri, ex_gw_port, floating_ip, fixed_ip): + ### SV: patched !!! ip_cidr = str(floating_ip) + '/32' interface_name = self.get_external_device_name(ex_gw_port['id']) - device = ip_lib.IPDevice(interface_name, self.root_helper, - namespace=ri.ns_name()) + effective_interface_name = self.get_effective_interface_name(interface_name) + if not self.conf.use_namespaces: + LOG.info("Warning! You are not using network namespaces! " + "Floating IP {ip} will be assigned to interface {iface}, instead {eiface}." + .format( + ip=ip_cidr, + iface=interface_name, + eiface=effective_interface_name + ) + ) + device = ip_lib.IPDevice(effective_interface_name, self.root_helper, namespace=ri.ns_name()) if ip_cidr not in [addr['cidr'] for addr in device.addr.list()]: net = netaddr.IPNetwork(ip_cidr) device.addr.add(net.version, ip_cidr, str(net.broadcast)) - self._send_gratuitous_arp_packet(ri, interface_name, floating_ip) + self._send_gratuitous_arp_packet(ri, effective_interface_name, floating_ip) for chain, rule in self.floating_forward_rules(floating_ip, fixed_ip): ri.iptables_manager.ipv4['nat'].add_rule(chain, rule) ri.iptables_manager.apply() def floating_ip_removed(self, ri, ex_gw_port, floating_ip, fixed_ip): + ### SV: patched !!! ip_cidr = str(floating_ip) + '/32' net = netaddr.IPNetwork(ip_cidr) interface_name = self.get_external_device_name(ex_gw_port['id']) + effective_interface_name = self.get_effective_interface_name(interface_name) - device = ip_lib.IPDevice(interface_name, self.root_helper, - namespace=ri.ns_name()) + device = ip_lib.IPDevice(effective_interface_name, self.root_helper, namespace=ri.ns_name()) device.addr.delete(net.version, ip_cidr) for chain, rule in self.floating_forward_rules(floating_ip, fixed_ip): @@ -642,7 +686,16 @@ class L3NATAgent(manager.Manager): self.fullsync = True def after_start(self): - LOG.info(_("L3 agent started")) + LOG.info(_("L3 agent started (Mirantis-patched)")) + LOG.debug("*Ext.bridge name is '{0}'".format(self.conf.external_network_bridge)) + if not self.conf.use_namespaces: + LOG.info("Warning!!!") + LOG.info("You are not using network namespaces! " + "Floating IPs will be assigned to interface {iface}".format( + iface=self.conf.external_network_bridge + ) + ) + def _update_routing_table(self, ri, operation, route): cmd = ['ip', 'route', operation, 'to', route['destination'],