def setup_physical_bridges(self, bridge_mappings): """Setup the physical network bridges. Creates physical network bridges and links them to the integration bridge using veths. :param bridge_mappings: map physical network names to bridge names. """ self.phys_brs = {} self.int_ofports = {} self.phys_ofports = {} ip_wrapper = ip_lib.IPWrapper(self.root_helper) for physical_network, bridge in bridge_mappings.iteritems(): LOG.info( _("Mapping physical network %(physical_network)s to " "bridge %(bridge)s"), {"physical_network": physical_network, "bridge": bridge}, ) # setup physical bridge if not ip_lib.device_exists(bridge, self.root_helper): LOG.error( _( "Bridge %(bridge)s for physical network " "%(physical_network)s does not exist. Agent " "terminated!" ), {"physical_network": physical_network, "bridge": bridge}, ) sys.exit(1) br = ovs_lib.OVSBridge(bridge, self.root_helper) br.remove_all_flows() br.add_flow(priority=1, actions="normal") self.phys_brs[physical_network] = br # create veth to patch physical bridge with integration bridge int_veth_name = constants.VETH_INTEGRATION_PREFIX + bridge self.int_br.delete_port(int_veth_name) phys_veth_name = constants.VETH_PHYSICAL_PREFIX + bridge br.delete_port(phys_veth_name) if ip_lib.device_exists(int_veth_name, self.root_helper): ip_lib.IPDevice(int_veth_name, self.root_helper).link.delete() # Give udev a chance to process its rules here, to avoid # race conditions between commands launched by udev rules # and the subsequent call to ip_wrapper.add_veth utils.execute(["/sbin/udevadm", "settle", "--timeout=10"]) int_veth, phys_veth = ip_wrapper.add_veth(int_veth_name, phys_veth_name) self.int_ofports[physical_network] = self.int_br.add_port(int_veth) self.phys_ofports[physical_network] = br.add_port(phys_veth) # block all untranslated traffic over veth between bridges self.int_br.add_flow(priority=2, in_port=self.int_ofports[physical_network], actions="drop") br.add_flow(priority=2, in_port=self.phys_ofports[physical_network], actions="drop") # enable veth to pass traffic int_veth.link.set_up() phys_veth.link.set_up() if self.veth_mtu: # set up mtu size for veth interfaces int_veth.link.set_mtu(self.veth_mtu) phys_veth.link.set_mtu(self.veth_mtu)
def _assert_dvr_floating_ips(self, router): # in the fip namespace: # Check that the fg-<port-id> (floatingip_agent_gateway) # is created with the ip address of the external gateway port floating_ips = router.router[l3_constants.FLOATINGIP_KEY] self.assertTrue(floating_ips) external_port = self.agent._get_ex_gw_port(router) fip_ns = self.agent.get_fip_ns(floating_ips[0]['floating_network_id']) fip_ns_name = fip_ns.get_name() fg_port_created_succesfully = ip_lib.device_exists_with_ip_mac( fip_ns.get_ext_device_name(external_port['id']), external_port['ip_cidr'], external_port['mac_address'], fip_ns_name, self.root_helper) self.assertTrue(fg_port_created_succesfully) # Check fpr-router device has been created device_name = fip_ns.get_int_device_name(router.router_id) fpr_router_device_created_succesfully = ip_lib.device_exists( device_name, self.root_helper, fip_ns_name) self.assertTrue(fpr_router_device_created_succesfully) # In the router namespace # Check rfp-<router-id> is created correctly for fip in floating_ips: device_name = fip_ns.get_rtr_ext_device_name(router.router_id) self.assertTrue(ip_lib.device_exists( device_name, self.root_helper, router.ns_name))
def internal_network_removed(self, ri, port): port_id = port['id'] interface_name = self.get_internal_device_name(port_id) if ri.router['distributed'] and ri.ex_gw_port: # DVR handling code for SNAT self._snat_redirect_remove(ri, port, interface_name) if (self.conf.agent_mode == l3_constants.L3_AGENT_MODE_DVR_SNAT and ri.ex_gw_port['binding:host_id'] == self.host): snat_port = self._map_internal_interfaces(ri, port, ri.snat_ports) if snat_port: snat_interface = ( self.get_snat_int_device_name(snat_port['id']) ) ns_name = self.get_snat_ns_name(ri.router['id']) prefix = dvr.SNAT_INT_DEV_PREFIX if ip_lib.device_exists(snat_interface, namespace=ns_name): self.driver.unplug(snat_interface, namespace=ns_name, prefix=prefix) if ip_lib.device_exists(interface_name, namespace=ri.ns_name): if ri.is_ha: ri._clear_vips(interface_name) self.driver.unplug(interface_name, namespace=ri.ns_name, prefix=INTERNAL_DEV_PREFIX)
def _assert_dvr_floating_ips(self, router): # in the fip namespace: # Check that the fg-<port-id> (floatingip_agent_gateway) # is created with the ip address of the external gateway port floating_ips = router.router[l3_constants.FLOATINGIP_KEY] self.assertTrue(floating_ips) # We need to fetch the floatingip agent gateway port info # from the router_info floating_agent_gw_port = ( router.router[l3_constants.FLOATINGIP_AGENT_INTF_KEY]) self.assertTrue(floating_agent_gw_port) external_gw_port = floating_agent_gw_port[0] fip_ns = self.agent.get_fip_ns(floating_ips[0]['floating_network_id']) fip_ns_name = fip_ns.get_name() fg_port_created_successfully = ip_lib.device_exists_with_ips_and_mac( fip_ns.get_ext_device_name(external_gw_port['id']), [self._port_first_ip_cidr(external_gw_port)], external_gw_port['mac_address'], namespace=fip_ns_name) self.assertTrue(fg_port_created_successfully) # Check fpr-router device has been created device_name = fip_ns.get_int_device_name(router.router_id) fpr_router_device_created_successfully = ip_lib.device_exists( device_name, namespace=fip_ns_name) self.assertTrue(fpr_router_device_created_successfully) # In the router namespace # Check rfp-<router-id> is created correctly for fip in floating_ips: device_name = fip_ns.get_rtr_ext_device_name(router.router_id) self.assertTrue(ip_lib.device_exists( device_name, namespace=router.ns_name))
def _get_dvr_snat_namespace_device_status(self, router, internal_dev_name=None): """Function returns the internal and external device status.""" snat_ns = dvr_snat_ns.SnatNamespace.get_snat_ns_name(router.router_id) external_port = router.get_ex_gw_port() external_device_name = router.get_external_device_name(external_port["id"]) qg_device_created_successfully = ip_lib.device_exists(external_device_name, namespace=snat_ns) sg_device_created_successfully = ip_lib.device_exists(internal_dev_name, namespace=snat_ns) return qg_device_created_successfully, sg_device_created_successfully
def setup_physical_bridges(self, bridge_mappings): '''Setup the physical network bridges. Creates physical network bridges and links them to the integration bridge using veths. :param bridge_mappings: map physical network names to bridge names. ''' self.phys_brs = {} self.int_ofports = {} self.phys_ofports = {} ip_wrapper = ip_lib.IPWrapper(self.root_helper) for physical_network, bridge in bridge_mappings.iteritems(): LOG.info(_("Mapping physical network %(physical_network)s to " "bridge %(bridge)s"), {'physical_network': physical_network, 'bridge': bridge}) # setup physical bridge if not ip_lib.device_exists(bridge, self.root_helper): LOG.error(_("Bridge %(bridge)s for physical network " "%(physical_network)s does not exist. Agent " "terminated!"), {'physical_network': physical_network, 'bridge': bridge}) sys.exit(1) br = ovs_lib.OVSBridge(bridge, self.root_helper) br.remove_all_flows() br.add_flow(priority=1, actions="normal") self.phys_brs[physical_network] = br # create veth to patch physical bridge with integration bridge int_veth_name = constants.VETH_INTEGRATION_PREFIX + bridge self.int_br.delete_port(int_veth_name) phys_veth_name = constants.VETH_PHYSICAL_PREFIX + bridge br.delete_port(phys_veth_name) if ip_lib.device_exists(int_veth_name, self.root_helper): ip_lib.IPDevice(int_veth_name, self.root_helper).link.delete() int_veth, phys_veth = ip_wrapper.add_veth(int_veth_name, phys_veth_name) self.int_ofports[physical_network] = self.int_br.add_port(int_veth) self.phys_ofports[physical_network] = br.add_port(phys_veth) # block all untranslated traffic over veth between bridges self.int_br.add_flow(priority=2, in_port=self.int_ofports[physical_network], actions="drop") br.add_flow(priority=2, in_port=self.phys_ofports[physical_network], actions="drop") # enable veth to pass traffic int_veth.link.set_up() phys_veth.link.set_up() if self.veth_mtu: # set up mtu size for veth interfaces int_veth.link.set_mtu(self.veth_mtu) phys_veth.link.set_mtu(self.veth_mtu)
def test_device_exists(self): attr = self.generate_device_details() self.assertFalse(ip_lib.device_exists(attr.name, namespace=attr.namespace)) device = self.manage_device(attr) self.assertTrue(ip_lib.device_exists(device.name, namespace=attr.namespace)) device.link.delete() self.assertFalse(ip_lib.device_exists(attr.name, namespace=attr.namespace))
def _get_router_info_list_for_tenant(self, router_ids, tenant_id): """Returns the list of router info objects on which to apply the fw.""" root_ip = ip_lib.IPWrapper(self.root_helper) local_ns_list = root_ip.get_namespaces( self.root_helper) if self.conf.use_namespaces else [] router_info_list = [] # Pick up namespaces for Tenant Routers for rid in router_ids: # for routers without an interface - get_routers returns # the router - but this is not yet populated in router_info if rid not in self.router_info: continue self.router_info[rid].fip_exist = False rtr_2_fip_name = self.get_rtr_int_device_name(rid) if ip_lib.device_exists(rtr_2_fip_name, self.root_helper, namespace=self.router_info[rid].ns_name): self.router_info[rid].fip_exist = True if self.router_info[rid].use_namespaces: router_ns = self.router_info[rid].ns_name if router_ns in local_ns_list: router_info_list.append(self.router_info[rid]) else: router_info_list.append(self.router_info[rid]) return router_info_list
def validate_bridge_mappings(self): for physnet, bridge in self.bridge_mappings.items(): if not ip_lib.device_exists(bridge): LOG.error(_LE("Bridge %(brq)s for physical network %(net)s" " does not exist. Agent terminated!"), {'brq': bridge, 'net': physnet}) sys.exit(1)
def create_rtr_2_fip_link(self, ri): """Create interface between router and Floating IP namespace.""" rtr_2_fip_name = self.get_rtr_ext_device_name(ri.router_id) fip_2_rtr_name = self.get_int_device_name(ri.router_id) fip_ns_name = self.get_name() # add link local IP to interface if ri.rtr_fip_subnet is None: ri.rtr_fip_subnet = self.local_subnets.allocate(ri.router_id) rtr_2_fip, fip_2_rtr = ri.rtr_fip_subnet.get_pair() ip_wrapper = ip_lib.IPWrapper(namespace=ri.ns_name) device_exists = ip_lib.device_exists(rtr_2_fip_name, namespace=ri.ns_name) if not device_exists: int_dev = ip_wrapper.add_veth(rtr_2_fip_name, fip_2_rtr_name, fip_ns_name) self._internal_ns_interface_added(str(rtr_2_fip), rtr_2_fip_name, ri.ns_name) self._internal_ns_interface_added(str(fip_2_rtr), fip_2_rtr_name, fip_ns_name) if self.agent_conf.network_device_mtu: int_dev[0].link.set_mtu(self.agent_conf.network_device_mtu) int_dev[1].link.set_mtu(self.agent_conf.network_device_mtu) int_dev[0].link.set_up() int_dev[1].link.set_up() # add default route for the link local interface device = ip_lib.IPDevice(rtr_2_fip_name, namespace=ri.ns_name) device.route.add_gateway(str(fip_2_rtr.ip), table=FIP_RT_TBL) #setup the NAT rules and chains ri._handle_fip_nat_rules(rtr_2_fip_name, 'add_rules')
def external_gateway_added(self, ri, ex_gw_port, interface_name, internal_cidrs): 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) 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)
def internal_network_removed(self, ri, port_id, internal_cidr): interface_name = self.get_internal_device_name(port_id) if ip_lib.device_exists(interface_name, root_helper=self.root_helper, namespace=ri.ns_name()): self.driver.unplug(interface_name, namespace=ri.ns_name(), prefix=INTERNAL_DEV_PREFIX)
def plug(self, network_id, port_id, device_name, mac_address, bridge=None, namespace=None, prefix=None): """This method is called by the Dhcp agent or by the L3 agent when a new network is created """ if not ip_lib.device_exists(device_name, self.root_helper, namespace=namespace): ip = ip_lib.IPWrapper(self.root_helper) tap_name = device_name.replace(prefix or n_const.TAP_DEVICE_PREFIX, n_const.TAP_DEVICE_PREFIX) # Create ns_dev in a namespace if one is configured. root_dev, ns_dev = ip.add_veth(tap_name, device_name, namespace2=namespace) ns_dev.link.set_address(mac_address) # Add an interface created by ovs to the namespace. namespace_obj = ip.ensure_namespace(namespace) namespace_obj.add_device_to_namespace(ns_dev) ns_dev.link.set_up() root_dev.link.set_up() cmd = ['mm-ctl', '--bind-port', port_id, device_name] utils.execute(cmd, self.root_helper) else: LOG.info(_LI("Device %s already exists"), device_name)
def plug(self, network_id, port_id, device_name, mac_address, bridge=None, namespace=None, prefix=None): """Plugin the interface.""" if not ip_lib.device_exists(device_name, self.root_helper, namespace=namespace): ip = ip_lib.IPWrapper(self.root_helper) # Enable agent to define the prefix tap_name = device_name.replace(prefix or self.DEV_NAME_PREFIX, n_const.TAP_DEVICE_PREFIX) # Create ns_veth in a namespace if one is configured. root_veth, ns_veth = ip.add_veth(tap_name, device_name, namespace2=namespace) ns_veth.link.set_address(mac_address) if self.conf.network_device_mtu: root_veth.link.set_mtu(self.conf.network_device_mtu) ns_veth.link.set_mtu(self.conf.network_device_mtu) root_veth.link.set_up() ns_veth.link.set_up() else: LOG.info(_LI("Device %s already exists"), device_name)
def delete_vlan_bridge(self, bridge_name): if ip_lib.device_exists(bridge_name): interfaces_on_bridge = self.get_interfaces_on_bridge(bridge_name) for interface in interfaces_on_bridge: self.remove_interface(bridge_name, interface) if interface.startswith(VXLAN_INTERFACE_PREFIX): self.delete_vxlan(interface) continue for physical_interface in self.interface_mappings.values(): if (interface.startswith(physical_interface)): ips, gateway = self.get_interface_details(bridge_name) if ips: # This is a flat network or a VLAN interface that # was setup outside of neutron => return IP's from # bridge to interface self.update_interface_ip_details(interface, bridge_name, ips, gateway) elif physical_interface != interface: self.delete_vlan(interface) LOG.debug("Deleting bridge %s", bridge_name) if utils.execute(['ip', 'link', 'set', bridge_name, 'down'], run_as_root=True): return if utils.execute(['brctl', 'delbr', bridge_name], run_as_root=True): return LOG.debug("Done deleting bridge %s", bridge_name) else: LOG.error(_LE("Cannot delete bridge %s, does not exist"), bridge_name)
def vxlan_ucast_supported(self): if not cfg.CONF.VXLAN.l2_population: return False if not ip_lib.iproute_arg_supported( ['bridge', 'fdb'], 'append'): LOG.warning(_LW('Option "%(option)s" must be supported by command ' '"%(command)s" to enable %(mode)s mode'), {'option': 'append', 'command': 'bridge fdb', 'mode': 'VXLAN UCAST'}) return False test_iface = None for seg_id in moves.range(1, p_const.MAX_VXLAN_VNI + 1): if not ip_lib.device_exists( self.get_vxlan_device_name(seg_id)): test_iface = self.ensure_vxlan(seg_id) break else: LOG.error(_LE('No valid Segmentation ID to perform UCAST test.')) return False try: utils.execute( cmd=['bridge', 'fdb', 'append', constants.FLOODING_ENTRY[0], 'dev', test_iface, 'dst', '1.1.1.1'], run_as_root=True, log_fail_as_error=False) return True except RuntimeError: return False finally: self.delete_vxlan(test_iface)
def internal_network_removed(self, port): interface_name = self.get_internal_device_name(port['id']) LOG.debug("removing internal network: port(%s) interface(%s)", port['id'], interface_name) if ip_lib.device_exists(interface_name, namespace=self.ns_name): self.driver.unplug(interface_name, namespace=self.ns_name, prefix=INTERNAL_DEV_PREFIX)
def _dvr_internal_network_removed(self, port): if not self.ex_gw_port: return sn_port = self._map_internal_interfaces(port, self.snat_ports) if not sn_port: return # DVR handling code for SNAT interface_name = self.get_internal_device_name(port['id']) self._snat_redirect_remove(sn_port, port, interface_name) mode = self.agent_conf.agent_mode is_this_snat_host = (mode == l3_constants.L3_AGENT_MODE_DVR_SNAT and self.ex_gw_port['binding:host_id'] == self.host) if not is_this_snat_host: return snat_interface = ( self.get_snat_int_device_name(sn_port['id'])) ns_name = self.snat_namespace.name prefix = dvr_snat_ns.SNAT_INT_DEV_PREFIX if ip_lib.device_exists(snat_interface, namespace=ns_name): self.driver.unplug(snat_interface, namespace=ns_name, prefix=prefix)
def ensure_vxlan(self, segmentation_id): """Create a vxlan unless it already exists.""" interface = self.get_vxlan_device_name(segmentation_id) if not ip_lib.device_exists(interface): LOG.debug("Creating vxlan interface %(interface)s for " "VNI %(segmentation_id)s", {'interface': interface, 'segmentation_id': segmentation_id}) args = {'dev': self.local_int} if self.vxlan_mode == lconst.VXLAN_MCAST: args['group'] = self.get_vxlan_group(segmentation_id) if cfg.CONF.VXLAN.ttl: args['ttl'] = cfg.CONF.VXLAN.ttl if cfg.CONF.VXLAN.tos: args['tos'] = cfg.CONF.VXLAN.tos if cfg.CONF.VXLAN.l2_population: args['proxy'] = True try: int_vxlan = self.ip.add_vxlan(interface, segmentation_id, **args) except RuntimeError: with excutils.save_and_reraise_exception() as ctxt: # perform this check after an attempt rather than before # to avoid excessive lookups and a possible race condition. if ip_lib.vxlan_in_use(segmentation_id): ctxt.reraise = False LOG.error(_LE("Unable to create VXLAN interface for " "VNI %s because it is in use by another " "interface."), segmentation_id) return None int_vxlan.link.set_up() LOG.debug("Done creating vxlan interface %s", interface) return interface
def get_interfaces_on_bridge(self, bridge_name): if ip_lib.device_exists(bridge_name): bridge_interface_path = BRIDGE_INTERFACES_FS.replace( BRIDGE_NAME_PLACEHOLDER, bridge_name) return os.listdir(bridge_interface_path) else: return []
def plug(self, network_id, port_id, device_name, mac_address, bridge=None, namespace=None, prefix=None): """Plug in the interface.""" if not ip_lib.device_exists(device_name, self.root_helper, namespace=namespace): ip = ip_lib.IPWrapper(self.root_helper) tap_name = self._get_tap_name(device_name, prefix) root_dev, ns_dev = ip.add_veth(tap_name, device_name) self._ivs_add_port(tap_name, port_id, mac_address) ns_dev = ip.device(device_name) ns_dev.link.set_address(mac_address) if self.conf.network_device_mtu: ns_dev.link.set_mtu(self.conf.network_device_mtu) root_dev.link.set_mtu(self.conf.network_device_mtu) if namespace: namespace_obj = ip.ensure_namespace(namespace) namespace_obj.add_device_to_namespace(ns_dev) ns_dev.link.set_up() root_dev.link.set_up() else: LOG.info(_LI("Device %s already exists"), device_name)
def validate_interface_mappings(self): for physnet, interface in self.interface_mappings.items(): if not ip_lib.device_exists(interface): LOG.error(_LE("Interface %(intf)s for physical network %(net)s" " does not exist. Agent terminated!"), {'intf': interface, 'net': physnet}) sys.exit(1)
def delete_vxlan(self, interface): if ip_lib.device_exists(interface): LOG.debug("Deleting vxlan interface %s for vlan", interface) int_vxlan = self.ip.device(interface) int_vxlan.link.set_down() int_vxlan.link.delete() LOG.debug("Done deleting vxlan interface %s", interface)
def vxlan_ucast_supported(self): if not cfg.CONF.VXLAN.l2_population: return False if not ip_lib.iproute_arg_supported( ['bridge', 'fdb'], 'append'): LOG.warning('Option "%(option)s" must be supported by command ' '"%(command)s" to enable %(mode)s mode', {'option': 'append', 'command': 'bridge fdb', 'mode': 'VXLAN UCAST'}) return False test_iface = None for seg_id in moves.range(1, constants.MAX_VXLAN_VNI + 1): if (ip_lib.device_exists(self.get_vxlan_device_name(seg_id)) or ip_lib.vxlan_in_use(seg_id)): continue test_iface = self.ensure_vxlan(seg_id) break else: LOG.error('No valid Segmentation ID to perform UCAST test.') return False try: bridge_lib.FdbInterface.append(constants.FLOODING_ENTRY[0], test_iface, '1.1.1.1', log_fail_as_error=False) return True except RuntimeError: return False finally: self.delete_interface(test_iface)
def _check_rtr_2_fip_connect(self): """Checks if the rtr to fip connect exists, if not sets to false.""" fip_ns_name = self.fip_ns.get_name() if ip_lib.network_namespace_exists(fip_ns_name): fip_2_rtr_name = self.fip_ns.get_int_device_name(self.router_id) if not ip_lib.device_exists(fip_2_rtr_name, namespace=fip_ns_name): self.rtr_fip_connect = False
def test_plug_with_namespace_sets_mtu_higher_than_bridge(self): device_mtu = 1450 # Create a new OVS bridge ovs_bridge = self.useFixture(net_helpers.OVSBridgeFixture()).bridge self.assertFalse(ovs_bridge.get_port_name_list()) # Add a new linuxbridge port with reduced MTU to OVS bridge lb_bridge = self.useFixture( net_helpers.LinuxBridgeFixture()).bridge lb_bridge_port = self.useFixture( net_helpers.LinuxBridgePortFixture(lb_bridge)) lb_bridge_port.port.link.set_mtu(device_mtu - 1) ovs_bridge.add_port(lb_bridge_port.port.name) # Now plug a device with intended MTU that is higher than for the port # above and validate that its MTU is not reduced to the least MTU on # the bridge device_name = utils.get_rand_name() mac_address = utils.get_random_mac('fa:16:3e:00:00:00'.split(':')) namespace = self.useFixture(net_helpers.NamespaceFixture()).name self.interface.plug(network_id=uuidutils.generate_uuid(), port_id=uuidutils.generate_uuid(), device_name=device_name, mac_address=mac_address, bridge=ovs_bridge.br_name, namespace=namespace, mtu=device_mtu) self.assertIn(device_name, ovs_bridge.get_port_name_list()) self.assertTrue(ip_lib.device_exists(device_name, namespace)) self.assertEqual( device_mtu, ip_lib.IPDevice(device_name, namespace=namespace).link.mtu )
def ensure_vxlan(self, segmentation_id, mtu=None): """Create a vxlan unless it already exists.""" interface = self.get_vxlan_device_name(segmentation_id) if not ip_lib.device_exists(interface): LOG.debug("Creating vxlan interface %(interface)s for " "VNI %(segmentation_id)s", {'interface': interface, 'segmentation_id': segmentation_id}) args = {'dev': self.local_int, 'srcport': (cfg.CONF.VXLAN.udp_srcport_min, cfg.CONF.VXLAN.udp_srcport_max), 'dstport': cfg.CONF.VXLAN.udp_dstport, 'ttl': cfg.CONF.VXLAN.ttl} if cfg.CONF.VXLAN.tos: args['tos'] = cfg.CONF.VXLAN.tos if cfg.CONF.AGENT.dscp or cfg.CONF.AGENT.dscp_inherit: LOG.warning('The deprecated tos option in group VXLAN ' 'is set and takes precedence over dscp and ' 'dscp_inherit in group AGENT.') elif cfg.CONF.AGENT.dscp_inherit: args['tos'] = 'inherit' elif cfg.CONF.AGENT.dscp: args['tos'] = int(cfg.CONF.AGENT.dscp) << 2 if self.vxlan_mode == lconst.VXLAN_MCAST: args['group'] = self.get_vxlan_group(segmentation_id) if cfg.CONF.VXLAN.l2_population: args['proxy'] = cfg.CONF.VXLAN.arp_responder try: int_vxlan = self.ip.add_vxlan(interface, segmentation_id, **args) except RuntimeError: with excutils.save_and_reraise_exception() as ctxt: # perform this check after an attempt rather than before # to avoid excessive lookups and a possible race condition. if ip_lib.vxlan_in_use(segmentation_id): ctxt.reraise = False LOG.error("Unable to create VXLAN interface for " "VNI %s because it is in use by another " "interface.", segmentation_id) return None if mtu: try: int_vxlan.link.set_mtu(mtu) except ip_lib.InvalidArgument: phys_dev_mtu = ip_lib.get_device_mtu(self.local_int) LOG.error("Provided MTU value %(mtu)s for VNI " "%(segmentation_id)s is too high according " "to physical device %(dev)s MTU=%(phys_mtu)s.", {'mtu': mtu, 'segmentation_id': segmentation_id, 'dev': self.local_int, 'phys_mtu': phys_dev_mtu}) int_vxlan.link.delete() return None int_vxlan.disable_ipv6() int_vxlan.link.set_up() LOG.debug("Done creating vxlan interface %s", interface) return interface
def delete_vlan_bridge(self, bridge_name): if ip_lib.device_exists(bridge_name): interfaces_on_bridge = self.get_interfaces_on_bridge(bridge_name) for interface in interfaces_on_bridge: #self.remove_interface(bridge_name, interface) if interface.startswith(VXLAN_INTERFACE_PREFIX): self.delete_vxlan(interface) continue for physical_interface in self.interface_mappings.itervalues(): if (interface.startswith(physical_interface)): ips, gateway = self.get_interface_details(bridge_name) if ips: # This is a flat network or a VLAN interface that # was setup outside of neutron => return IP's from # bridge to interface self.update_interface_ip_details(interface, bridge_name, ips, gateway) elif physical_interface != interface: self.delete_vlan(interface) LOG.debug("Deleting bridge %s", bridge_name) bridge = self.ip.device(bridge_name) bridge.link.delete() LOG.debug("Done deleting bridge %s", bridge_name) else: LOG.debug("Cannot delete bridge %s; it does not exist", bridge_name)
def create_probe(self, network_id, device_owner='network'): network = self._get_network(network_id) bridge = None if network.external: bridge = self.conf.external_network_bridge port = self._create_port(network, device_owner) interface_name = self.driver.get_device_name(port) namespace = None if self.conf.use_namespaces: namespace = self._get_namespace(port) if ip_lib.device_exists(interface_name, self.root_helper, namespace): LOG.debug(_('Reusing existing device: %s.'), interface_name) else: self.driver.plug(network.id, port.id, interface_name, port.mac_address, bridge=bridge, namespace=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) self.driver.init_l3(interface_name, ip_cidrs, namespace=namespace) return port
def _process_router_if_compatible(self, router): if (self.conf.external_network_bridge and not ip_lib.device_exists(self.conf.external_network_bridge)): LOG.error(_LE("The external network bridge '%s' does not exist"), self.conf.external_network_bridge) return # Either ex_net_id or handle_internal_only_routers must be set ex_net_id = (router['external_gateway_info'] or {}).get('network_id') if not ex_net_id and not self.conf.handle_internal_only_routers: raise n_exc.RouterNotCompatibleWithAgent(router_id=router['id']) # If target_ex_net_id and ex_net_id are set they must be equal target_ex_net_id = self._fetch_external_net_id() if (target_ex_net_id and ex_net_id and ex_net_id != target_ex_net_id): # Double check that our single external_net_id has not changed # by forcing a check by RPC. if ex_net_id != self._fetch_external_net_id(force=True): raise n_exc.RouterNotCompatibleWithAgent( router_id=router['id']) if router['id'] not in self.router_info: self._process_added_router(router) else: self._process_updated_router(router)
def ensure_vlan(self, physical_interface, vlan_id): """Create a vlan unless it already exists.""" interface = self.get_subinterface_name(physical_interface, vlan_id) if not ip_lib.device_exists(interface): LOG.debug("Creating subinterface %(interface)s for " "VLAN %(vlan_id)s on interface " "%(physical_interface)s", {'interface': interface, 'vlan_id': vlan_id, 'physical_interface': physical_interface}) if utils.execute(['ip', 'link', 'add', 'link', physical_interface, 'name', interface, 'type', 'vlan', 'id', vlan_id], run_as_root=True): return if utils.execute(['ip', 'link', 'set', interface, 'up'], run_as_root=True): return LOG.debug("Done creating subinterface %s", interface) return interface
def _dvr_internal_network_removed(self, port): super(DvrEdgeRouter, self)._dvr_internal_network_removed(port) if not self.ex_gw_port: return sn_port = self.get_snat_port_for_internal_port(port, self.snat_ports) if not sn_port: return if not self._is_this_snat_host(): return snat_interface = self._get_snat_int_device_name(sn_port['id']) ns_name = self.snat_namespace.name prefix = lib_constants.SNAT_INT_DEV_PREFIX if ip_lib.device_exists(snat_interface, namespace=ns_name): self.driver.unplug(snat_interface, namespace=ns_name, prefix=prefix)
def init_host(self): LOG.info(_LI("APIC host agent: agent starting on %s"), self.host) self.state = { 'binary': BINARY_APIC_HOST_AGENT, 'host': self.host, 'topic': self.topic, 'configurations': {}, 'start_flag': True, 'agent_type': TYPE_APIC_HOST_AGENT, } self.uplink_ports = [] for inf in self.conf.apic_host_uplink_ports: if ip_lib.device_exists(inf): self.uplink_ports.append(inf) else: # ignore unknown interfaces LOG.error(_LE("No such interface (ignored): %s"), inf) self.lldpcmd = ['lldpctl', '-f', 'keyvalue'] + self.uplink_ports
def add_tap_interface(self, network_id, network_type, physical_network, segmentation_id, tap_device_name): """Add tap interface. If a VIF has been plugged into a network, this function will add the corresponding tap device to the relevant bridge. """ if not ip_lib.device_exists(tap_device_name, root_helper=self.root_helper): LOG.debug( _("Tap device: %s does not exist on " "this host, skipped"), tap_device_name) return False bridge_name = self.get_bridge_name(network_id) if network_type == p_const.TYPE_LOCAL: self.ensure_local_bridge(network_id) elif not self.ensure_physical_in_bridge( network_id, network_type, physical_network, segmentation_id): return False # Check if device needs to be added to bridge tap_device_in_bridge = self.get_bridge_for_tap_device(tap_device_name) if not tap_device_in_bridge: data = { 'tap_device_name': tap_device_name, 'bridge_name': bridge_name } msg = _("Adding device %(tap_device_name)s to bridge " "%(bridge_name)s") % data LOG.debug(msg) if utils.execute(['brctl', 'addif', bridge_name, tap_device_name], root_helper=self.root_helper): return False else: data = { 'tap_device_name': tap_device_name, 'bridge_name': bridge_name } msg = _("%(tap_device_name)s already exists on bridge " "%(bridge_name)s") % data LOG.debug(msg) return True
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 self.conf.use_namespaces: namespace = NS_PREFIX + network.id else: namespace = None if ip_lib.device_exists(interface_name, self.root_helper, 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=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_IP) self.driver.init_l3(interface_name, ip_cidrs, namespace=namespace) # ensure that the dhcp interface is first in the list if 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) return interface_name
def scan_fip_ports(self, ri): # don't scan if not dvr or count is not None if not ri.router.get('distributed') or ri.dist_fip_count is not None: return # scan system for any existing fip ports ri.dist_fip_count = 0 rtr_2_fip_interface = self.get_rtr_int_device_name(ri.router_id) if ip_lib.device_exists(rtr_2_fip_interface, root_helper=self.root_helper, namespace=ri.ns_name): device = ip_lib.IPDevice(rtr_2_fip_interface, self.root_helper, namespace=ri.ns_name) existing_cidrs = [addr['cidr'] for addr in device.addr.list()] fip_cidrs = [ c for c in existing_cidrs if common_utils.is_cidr_host(c) ] ri.dist_fip_count = len(fip_cidrs)
def plug(self, network_id, port_id, device_name, mac_address, bridge=None, namespace=None, prefix=None): """Plug in the interface.""" if not bridge: bridge = self.conf.ovs_integration_bridge if not ip_lib.device_exists(device_name, namespace=namespace): self.check_bridge_exists(bridge) ip = ip_lib.IPWrapper() tap_name = self._get_tap_name(device_name, prefix) if self.conf.ovs_use_veth: # Create ns_dev in a namespace if one is configured. root_dev, ns_dev = ip.add_veth(tap_name, device_name, namespace2=namespace) else: ns_dev = ip.device(device_name) internal = not self.conf.ovs_use_veth self._ovs_add_port(bridge, tap_name, port_id, mac_address, internal=internal) ns_dev.link.set_address(mac_address) if self.conf.network_device_mtu: ns_dev.link.set_mtu(self.conf.network_device_mtu) if self.conf.ovs_use_veth: root_dev.link.set_mtu(self.conf.network_device_mtu) # Add an interface created by ovs to the namespace. if not self.conf.ovs_use_veth and namespace: namespace_obj = ip.ensure_namespace(namespace) namespace_obj.add_device_to_namespace(ns_dev) ns_dev.link.set_up() if self.conf.ovs_use_veth: root_dev.link.set_up() else: LOG.info(_LI("Device %s already exists"), device_name)
def ensure_vxlan(self, segmentation_id): """Create a vxlan unless it already exists.""" interface = self.get_vxlan_device_name(segmentation_id) if not ip_lib.device_exists(interface): LOG.debug(_("Creating vxlan interface %(interface)s for " "VNI %(segmentation_id)s"), {'interface': interface, 'segmentation_id': segmentation_id}) args = {'dev': self.local_int} if self.vxlan_mode == lconst.VXLAN_MCAST: args['group'] = cfg.CONF.VXLAN.vxlan_group if cfg.CONF.VXLAN.ttl: args['ttl'] = cfg.CONF.VXLAN.ttl if cfg.CONF.VXLAN.tos: args['tos'] = cfg.CONF.VXLAN.tos if cfg.CONF.VXLAN.l2_population: args['proxy'] = True int_vxlan = self.ip.add_vxlan(interface, segmentation_id, **args) int_vxlan.link.set_up() LOG.debug(_("Done creating vxlan interface %s"), interface) return interface
def _test_mtu_set_after_action(self, device_name, br_name, namespace, action=None): mac_address = net.get_random_mac('fa:16:3e:00:00:00'.split(':')) plug = functools.partial( self.interface.plug, network_id=uuidutils.generate_uuid(), port_id=uuidutils.generate_uuid(), device_name=device_name, mac_address=mac_address, bridge=self.bridge_name, namespace=namespace) plug(mtu=1500) self.assertTrue(ip_lib.device_exists(device_name, namespace)) action = action or plug for mtu in (1450, 1500, 9000, 9000, 1450): action(mtu=mtu) self.assertEqual( mtu, ip_lib.IPDevice(device_name, namespace=namespace).link.mtu)
def _dvr_internal_network_removed(self, port): super(DvrEdgeRouter, self)._dvr_internal_network_removed(port) if not self.ex_gw_port: return sn_port = self.get_snat_port_for_internal_port(port) if not sn_port: return is_this_snat_host = ('binding:host_id' in self.ex_gw_port) and ( self.ex_gw_port['binding:host_id'] == self.host) if not is_this_snat_host: return snat_interface = self._get_snat_int_device_name(sn_port['id']) ns_name = self.snat_namespace.name prefix = dvr_snat_ns.SNAT_INT_DEV_PREFIX if ip_lib.device_exists(snat_interface, namespace=ns_name): self.driver.unplug(snat_interface, namespace=ns_name, prefix=prefix)
def _test_linuxbridge_cleanup(self, bridge_exists, callback): br_fixture = self.useFixture( tools.SafeCleanupFixture( net_helpers.LinuxBridgeFixture( prefix=lb_agent.BRIDGE_NAME_PREFIX))).fixture config = callback(br_fixture) temp_dir = self.useFixture(fixtures.TempDir()).path conf = self.useFixture( config_fixtures.ConfigFileFixture(base_filename='neutron.conf', config=config, temp_dir=temp_dir)) cmd = 'neutron-linuxbridge-cleanup', '--config-file', conf.filename ip_wrapper = ip_lib.IPWrapper(br_fixture.namespace) ip_wrapper.netns.execute(cmd) self.assertEqual( bridge_exists, ip_lib.device_exists(br_fixture.bridge.name, br_fixture.namespace))
def setup_physical_interfaces(self, interface_mappings): '''Sets up the physical network interfaces. Link physical interfaces to the integration bridge. :param interface_mappings: map physical net names to interface names. ''' for physical_network, interface in interface_mappings.iteritems(): LOG.info(_("Mapping physical network %(physical_network)s to " "interface %(interface)s"), {'physical_network': physical_network, 'interface': interface}) # Connect the physical interface to the bridge if not ip_lib.device_exists(interface, self.root_helper): LOG.error(_("Interface %(interface)s for physical network " "%(physical_network)s does not exist. Agent " "terminated!"), {'physical_network': physical_network, 'interface': interface}) raise SystemExit(1) self.int_br.add_port(interface)
def _external_gateway_added(self, ri, ex_gw_port, interface_name, ns_name, preserve_ips): if not ip_lib.device_exists(interface_name, namespace=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=ns_name, prefix=EXTERNAL_DEV_PREFIX) if not ri.is_ha: self.driver.init_l3(interface_name, [ex_gw_port['ip_cidr']], namespace=ns_name, gateway=ex_gw_port['subnet'].get('gateway_ip'), extra_subnets=ex_gw_port.get( 'extra_subnets', []), preserve_ips=preserve_ips) ip_address = ex_gw_port['ip_cidr'].split('/')[0] ip_lib.send_gratuitous_arp(ns_name, interface_name, ip_address, self.conf.send_arp_for_ha)
def plug(self, network_id, port_id, device_name, mac_address, bridge=None, namespace=None, prefix=None, mtu=None): if not ip_lib.device_exists(device_name, namespace=namespace): self.plug_new(network_id, port_id, device_name, mac_address, bridge, namespace, prefix, mtu) else: LOG.info("Device %s already exists", device_name) if mtu: self.set_mtu(device_name, mtu, namespace=namespace, prefix=prefix) else: LOG.warning("No MTU configured for port %s", port_id)
def external_gateway_added(self, ri, ex_gw_port, interface_name, internal_cidrs): 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) # Compute a list of addresses this router is supposed to have. # This avoids unnecessarily removing those addresses and # causing a momentarily network outage. floating_ips = ri.router.get(l3_constants.FLOATINGIP_KEY, []) preserve_ips = [ ip['floating_ip_address'] + FLOATING_IP_CIDR_SUFFIX for ip in floating_ips ] self.driver.init_l3(interface_name, [ex_gw_port['ip_cidr']], namespace=ri.ns_name(), preserve_ips=preserve_ips) ip_address = ex_gw_port['ip_cidr'].split('/')[0] self._send_gratuitous_arp_packet(ri, 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)
def _test_linuxbridge_cleanup(self, bridge_exists, callback): br_fixture = self.useFixture( tools.SafeCleanupFixture( net_helpers.LinuxBridgeFixture( prefix=lb_agent.BRIDGE_NAME_PREFIX))).fixture config = callback(br_fixture) # NOTE(slaweq): use of oslo.privsep inside neutron-linuxbridge-cleanup # script requires rootwrap helper to be configured in this script's # config privsep_helper = os.path.join(os.getenv('VIRTUAL_ENV'), 'bin', 'privsep-helper') config.update({ 'AGENT': { 'root_helper': tests_base.get_rootwrap_cmd(), 'root_helper_daemon': tests_base.get_rootwrap_daemon_cmd() }, 'privsep': { 'helper_command': ' '.join(['sudo', '-E', privsep_helper]), }, 'privsep_link': { 'helper_command': ' '.join(['sudo', '-E', privsep_helper]), }, }) config.update({'VXLAN': {'enable_vxlan': 'False'}}) temp_dir = self.useFixture(fixtures.TempDir()).path conf = self.useFixture( config_fixtures.ConfigFileFixture(base_filename='neutron.conf', config=config, temp_dir=temp_dir)) cmd = 'neutron-linuxbridge-cleanup', '--config-file', conf.filename ip_wrapper = ip_lib.IPWrapper(br_fixture.namespace) ip_wrapper.netns.execute(cmd, privsep_exec=True) self.assertEqual( bridge_exists, ip_lib.device_exists(br_fixture.bridge.name, br_fixture.namespace))
def set_qos_for_port(self, port_name, port_id, rate_limit): #set qlen for interface if qlen equal zero if ip_lib.device_exists(port_name): device = ip_lib.IPDevice(port_name, self.root_helper) device.link.set_qlen(50000) else: LOG.error(_("Can not find device (%s)."), port_name) args = [ 'set', 'port', port_name, 'qos=@newqos', '--', '--id=@newqos', 'create', 'qos', 'type=linux-htb', 'other-config:max-rate=%s' % rate_limit, 'external_ids:port-id=%s' % port_id, 'queues=0=@q0', '--', '--id=@q0', 'create', 'queue', 'other-config:min-rate=%s' % rate_limit, 'other-config:max-rate=%s' % rate_limit ] result = self.run_vsctl(args) if not result: LOG.error(_("Unable to set qos for %s(%s)."), (port_name, port_id)) return result.split()
def _add_tap_interface(self, network_id, network_type, physical_network, segmentation_id, tap_device_name, device_owner, mtu): """Add tap interface. If a VIF has been plugged into a network, this function will add the corresponding tap device to the relevant bridge. """ if not ip_lib.device_exists(tap_device_name): LOG.debug("Tap device: %s does not exist on " "this host, skipped", tap_device_name) return False bridge_name = self.get_existing_bridge_name(physical_network) if not bridge_name: bridge_name = self.get_bridge_name(network_id) if network_type == p_const.TYPE_LOCAL: self.ensure_local_bridge(network_id, bridge_name) elif not self.ensure_physical_in_bridge(network_id, network_type, physical_network, segmentation_id): return False if mtu: # <-None with device_details from older neutron servers. # we ensure the MTU here because libvirt does not set the # MTU of a bridge it creates and the tap device it creates will # inherit from the bridge its plugged into, which will be 1500 # at the time. See bug/1684326 for details. self._set_tap_mtu(tap_device_name, mtu) # Check if device needs to be added to bridge if not bridge_lib.BridgeDevice.get_interface_bridge( tap_device_name): data = {'tap_device_name': tap_device_name, 'bridge_name': bridge_name} LOG.debug("Adding device %(tap_device_name)s to bridge " "%(bridge_name)s", data) if bridge_lib.BridgeDevice(bridge_name).addif(tap_device_name): return False return True
def remove_interface(self, bridge_name, interface_name): if ip_lib.device_exists(bridge_name): if not self.is_device_on_bridge(interface_name): return True LOG.debug(_("Removing device %(interface_name)s from bridge " "%(bridge_name)s"), {'interface_name': interface_name, 'bridge_name': bridge_name}) if utils.execute(['brctl', 'delif', bridge_name, interface_name], root_helper=self.root_helper): return False LOG.debug(_("Done removing device %(interface_name)s from bridge " "%(bridge_name)s"), {'interface_name': interface_name, 'bridge_name': bridge_name}) return True else: LOG.debug(_("Cannot remove device %(interface_name)s bridge " "%(bridge_name)s does not exist"), {'interface_name': interface_name, 'bridge_name': bridge_name}) return False
def plug(self, network_id, port_id, device_name, mac_address, bridge=None, namespace=None, prefix=None, mtu=None): if not ip_lib.device_exists(device_name, namespace=namespace): try: self.plug_new(network_id, port_id, device_name, mac_address, bridge, namespace, prefix, mtu) except TypeError: versionutils.report_deprecated_feature( LOG, _LW('Interface driver does not support MTU parameter. ' 'This may not work in future releases.')) self.plug_new(network_id, port_id, device_name, mac_address, bridge, namespace, prefix) else: LOG.info(_LI("Device %s already exists"), device_name)
def ensure_vxlan(self, segmentation_id): """Create a vxlan unless it already exists.""" interface = self.get_vxlan_device_name(segmentation_id) if not ip_lib.device_exists(interface): LOG.debug( "Creating vxlan interface %(interface)s for " "VNI %(segmentation_id)s", { 'interface': interface, 'segmentation_id': segmentation_id }) args = {'dev': self.local_int} if self.vxlan_mode == lconst.VXLAN_MCAST: args['group'] = self.get_vxlan_group(segmentation_id) if cfg.CONF.VXLAN.ttl: args['ttl'] = cfg.CONF.VXLAN.ttl if cfg.CONF.VXLAN.tos: args['tos'] = cfg.CONF.VXLAN.tos if cfg.CONF.network_device_mtu: args['mtu'] = cfg.CONF.network_device_mtu if cfg.CONF.VXLAN.l2_population: args['proxy'] = cfg.CONF.VXLAN.arp_responder try: int_vxlan = self.ip.add_vxlan(interface, segmentation_id, **args) except RuntimeError: with excutils.save_and_reraise_exception() as ctxt: # perform this check after an attempt rather than before # to avoid excessive lookups and a possible race condition. if ip_lib.vxlan_in_use(segmentation_id): ctxt.reraise = False LOG.error( _LE("Unable to create VXLAN interface for " "VNI %s because it is in use by another " "interface."), segmentation_id) return None int_vxlan.disable_ipv6() int_vxlan.link.set_up() LOG.debug("Done creating vxlan interface %s", interface) return interface
def create_probe(self, network_id, device_owner='network'): network = self._get_network(network_id) port = self._create_port(network, device_owner) interface_name = self.driver.get_device_name(port) namespace = self._get_namespace(port) if ip_lib.device_exists(interface_name, namespace=namespace): LOG.debug('Reusing existing device: %s.', interface_name) else: self.driver.plug(network.id, port.id, interface_name, port.mac_address, namespace=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) self.driver.init_l3(interface_name, ip_cidrs, namespace=namespace) return port
def plug(self, network_id, port_id, device_name, mac_address, bridge=None, namespace=None, prefix=None): """Plugin the interface.""" if not ip_lib.device_exists(device_name, namespace=namespace): ip = ip_lib.IPWrapper() # Enable agent to define the prefix tap_name = device_name.replace(prefix or self.DEV_NAME_PREFIX, n_const.TAP_DEVICE_PREFIX) # Create ns_veth in a namespace if one is configured. root_veth, ns_veth = ip.add_veth(tap_name, device_name, namespace2=namespace) ns_veth.link.set_address(mac_address) if self.conf.network_device_mtu: root_veth.link.set_mtu(self.conf.network_device_mtu) ns_veth.link.set_mtu(self.conf.network_device_mtu) root_veth.link.set_up() ns_veth.link.set_up() else: LOG.info(_LI("Device %s already exists"), device_name)
def _internal_network_added(self, ns_name, network_id, port_id, internal_cidr, mac_address, interface_name, prefix, is_ha=False): if not ip_lib.device_exists(interface_name, namespace=ns_name): self.driver.plug(network_id, port_id, interface_name, mac_address, namespace=ns_name, prefix=prefix) if not is_ha: self.driver.init_l3(interface_name, [internal_cidr], namespace=ns_name) ip_address = internal_cidr.split('/')[0] ip_lib.send_gratuitous_arp(ns_name, interface_name, ip_address, self.conf.send_arp_for_ha)
def add_tap_interface(self, network_id, network_type, physical_network, segmentation_id, tap_device_name): """Add tap interface. If a VIF has been plugged into a network, this function will add the corresponding tap device to the relevant bridge. """ if not ip_lib.device_exists(tap_device_name): LOG.debug("Tap device: %s does not exist on " "this host, skipped", tap_device_name) return False bridge_name = self.get_bridge_name(network_id) if network_type == p_const.TYPE_LOCAL: self.ensure_local_bridge(network_id) else: phy_dev_name = self.ensure_physical_in_bridge( network_id, network_type, physical_network, segmentation_id) if not phy_dev_name: return False # (mirlos) we are setting MTU to the configured value below #self.ensure_tap_mtu(tap_device_name, phy_dev_name) # fix-neutron-agent-for-mtu-config hack # also set the bridge in one go LOG.debug("Set MTU and master of %s", tap_device_name) try: utils.execute([ 'ip', 'link', 'set', tap_device_name, 'mtu', cfg.CONF.network_device_mtu, 'master', bridge_name, 'up' ], run_as_root=True) except RuntimeError: LOG.error('Failed to process interface %s for bridge %s', tap_device_name, bridge_name) return False return True
def environment_setup(): bridge = cfg.CONF.df.integration_bridge interface = cfg.CONF.df_metadata.metadata_interface port = cfg.CONF.df_metadata.port if ip_lib.device_exists(interface): LOG.info("Device %s already exists", interface) # Destroy the environment when the device exists. # We can re-initialize the environment correctly. environment_destroy() cmd = [ "ovs-vsctl", "add-port", bridge, interface, "--", "set", "Interface", interface, "type=internal" ] utils.execute(cmd, run_as_root=True) ip = cfg.CONF.df_metadata.ip cmd = ["ip", "addr", "add", "dev", interface, "{}/0".format(ip)] utils.execute(cmd, run_as_root=True) cmd = ["ip", "link", "set", "dev", interface, "up"] utils.execute(cmd, run_as_root=True) cmd = [ "ip", "route", "add", "0.0.0.0/0", "dev", interface, "table", METADATA_ROUTE_TABLE_ID ] utils.execute(cmd, run_as_root=True) cmd = ["ip", "rule", "add", "from", ip, "table", METADATA_ROUTE_TABLE_ID] utils.execute(cmd, run_as_root=True) cmd = [ "iptables", '-I', 'INPUT', '-i', interface, '-p', 'tcp', '--dport', str(port), '-j', 'ACCEPT' ] utils.execute(cmd, run_as_root=True)
def teardown_datapath(self, net_name): """Unprovision this datapath to stop serving metadata. This function will shutdown metadata proxy if it's running and delete the VETH pair, the OVS port and the namespace. """ namespace = self._get_namespace_name(net_name) ip = ip_lib.IPWrapper(namespace) # If the namespace doesn't exist, return if not ip.netns.exists(namespace): return LOG.info("Cleaning up %s namespace which is not needed anymore", namespace) metadata_driver.MetadataDriver.destroy_monitored_metadata_proxy( self._process_monitor, net_name, self.conf, namespace) veth_name = self._get_veth_name(net_name) self.ovs_idl.del_port(veth_name[0]).execute() if ip_lib.device_exists(veth_name[0]): ip_lib.IPWrapper().del_veth(veth_name[0]) ip.garbage_collect_namespace()
def vxlan_ucast_supported(self): if not cfg.CONF.VXLAN.l2_population: return False if not ip_lib.iproute_arg_supported(['bridge', 'fdb'], 'append'): LOG.warning( _LW('Option "%(option)s" must be supported by command ' '"%(command)s" to enable %(mode)s mode'), { 'option': 'append', 'command': 'bridge fdb', 'mode': 'VXLAN UCAST' }) return False test_iface = None for seg_id in moves.range(1, p_const.MAX_VXLAN_VNI + 1): if (ip_lib.device_exists(self.get_vxlan_device_name(seg_id)) or ip_lib.vxlan_in_use(seg_id)): continue test_iface = self.ensure_vxlan(seg_id) break else: LOG.error(_LE('No valid Segmentation ID to perform UCAST test.')) return False try: utils.execute(cmd=[ 'bridge', 'fdb', 'append', constants.FLOODING_ENTRY[0], 'dev', test_iface, 'dst', '1.1.1.1' ], run_as_root=True, log_fail_as_error=False) return True except RuntimeError: return False finally: self.delete_interface(test_iface)
def plug(self, network_id, port_id, device_name, mac_address, bridge=None, namespace=None, prefix=None): """This method is called by the Dhcp agent or by the L3 agent when a new network is created """ if not ip_lib.device_exists( device_name, self.root_helper, namespace=namespace): ip = ip_lib.IPWrapper(self.root_helper) tap_name = device_name.replace(prefix or n_const.TAP_DEVICE_PREFIX, n_const.TAP_DEVICE_PREFIX) # Create ns_dev in a namespace if one is configured. root_dev, ns_dev = ip.add_veth(tap_name, device_name, namespace2=namespace) ns_dev.link.set_address(mac_address) # Add an interface created by ovs to the namespace. namespace_obj = ip.ensure_namespace(namespace) namespace_obj.add_device_to_namespace(ns_dev) ns_dev.link.set_up() root_dev.link.set_up() cmd = ['mm-ctl', '--bind-port', port_id, device_name] utils.execute(cmd, self.root_helper) else: LOG.info(_LI("Device %s already exists"), device_name)
def ensure_vlan(self, physical_interface, vlan_id): """Create a vlan unless it already exists.""" interface = self.get_subinterface_name(physical_interface, vlan_id) if not ip_lib.device_exists(interface): LOG.debug("Creating subinterface %(interface)s for " "VLAN %(vlan_id)s on interface " "%(physical_interface)s", {'interface': interface, 'vlan_id': vlan_id, 'physical_interface': physical_interface}) try: int_vlan = self.ip.add_vlan(interface, physical_interface, vlan_id) except RuntimeError: with excutils.save_and_reraise_exception() as ctxt: if ip_lib.vlan_in_use(vlan_id): ctxt.reraise = False LOG.error(_LE("Unable to create VLAN interface for " "VLAN ID %s because it is in use by " "another interface."), vlan_id) return int_vlan.disable_ipv6() int_vlan.link.set_up() LOG.debug("Done creating subinterface %s", interface) return interface