Example #1
0
    def ensure_bridge(self, bridge_name, interface=None,
                      update_interface=True):
        """Create a bridge unless it already exists."""
        # ensure_device_is_ready instead of device_exists is used here
        # because there are cases where the bridge exists but it's not UP,
        # for example:
        # 1) A greenthread was executing this function and had not yet executed
        # "ip link set bridge_name up" before eventlet switched to this
        # thread running the same function
        # 2) The Nova VIF driver was running concurrently and had just created
        #    the bridge, but had not yet put it UP
        if not ip_lib.ensure_device_is_ready(bridge_name):
            LOG.debug("Starting bridge %(bridge_name)s for subinterface "
                      "%(interface)s",
                      {'bridge_name': bridge_name, 'interface': interface})
            bridge_device = bridge_lib.BridgeDevice.addbr(bridge_name)
            if bridge_device.setfd(0):
                return
            if bridge_device.disable_stp():
                return
            if bridge_device.link.set_up():
                return
            LOG.debug("Done starting bridge %(bridge_name)s for "
                      "subinterface %(interface)s",
                      {'bridge_name': bridge_name, 'interface': interface})
        else:
            bridge_device = bridge_lib.BridgeDevice(bridge_name)

        if not interface:
            return bridge_name

        # Update IP info if necessary
        if update_interface:
            self.update_interface_ip_details(bridge_name, interface)

        # Check if the interface is part of the bridge
        if not bridge_device.owns_interface(interface):
            try:
                # Check if the interface is not enslaved in another bridge
                bridge = bridge_lib.BridgeDevice.get_interface_bridge(
                    interface)
                if bridge:
                    bridge.delif(interface)

                bridge_device.addif(interface)
            except Exception as e:
                LOG.error("Unable to add %(interface)s to %(bridge_name)s"
                          "! Exception: %(e)s",
                          {'interface': interface, 'bridge_name': bridge_name,
                           'e': e})
                return
        return bridge_name
Example #2
0
    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.bridge_mappings.get(physical_network)
        if not bridge_name:
            bridge_name = self.get_bridge_name(network_id)

        if network_type == constants.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,
                                                mtu):
            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)
        # Avoid messing with plugging devices into a bridge that the agent
        # does not own
        if not device_owner.startswith(constants.DEVICE_OWNER_COMPUTE_PREFIX):
            # 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
        else:
            data = {'tap_device_name': tap_device_name,
                    'device_owner': device_owner,
                    'bridge_name': bridge_name}
            LOG.debug("Skip adding device %(tap_device_name)s to "
                      "%(bridge_name)s. It is owned by %(device_owner)s and "
                      "thus added elsewhere.", data)
        return True
Example #3
0
 def _delete_bridge(self, bridge_name):
     bridge_device = bridge_lib.BridgeDevice(bridge_name)
     if bridge_device.exists():
         try:
             LOG.debug("Deleting bridge %s", bridge_name)
             if bridge_device.link.set_down():
                 return
             if bridge_device.delbr():
                 return
             LOG.debug("Done deleting bridge %s", bridge_name)
             return
         except RuntimeError:
             pass
     LOG.debug("Cannot delete bridge %s; it does not exist", bridge_name)
Example #4
0
    def _add_tap_interface(self, network_id, network_type, physical_network,
                           segmentation_id, tap_device_name, device_owner):
        """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)
        else:
            phy_dev_name = self.ensure_physical_in_bridge(
                network_id, network_type, physical_network, segmentation_id)
            if not phy_dev_name:
                return False
            self.ensure_tap_mtu(tap_device_name, phy_dev_name)
        # Avoid messing with plugging devices into a bridge that the agent
        # does not own
        if device_owner.startswith(constants.DEVICE_OWNER_PREFIXES):
            # 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
        else:
            data = {
                'tap_device_name': tap_device_name,
                'device_owner': device_owner,
                'bridge_name': bridge_name
            }
            LOG.debug(
                "Skip adding device %(tap_device_name)s to "
                "%(bridge_name)s. It is owned by %(device_owner)s and "
                "thus added elsewhere.", data)
        return True
    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

        if physical_network:
            bridge_name = self.get_existing_bridge_name(physical_network)
        else:
            bridge_name = self.get_bridge_name(network_id)

        if network_type == p_const.TYPE_LOCAL:
            self.ensure_local_bridge(network_id, bridge_name)
        else:
            phy_dev_name = self.ensure_physical_in_bridge(
                network_id, network_type, physical_network, segmentation_id)
            if not phy_dev_name:
                return False
            self.ensure_tap_mtu(tap_device_name, phy_dev_name)

        # 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
            }
            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
        else:
            data = {
                'tap_device_name': tap_device_name,
                'bridge_name': bridge_name
            }
            LOG.debug(
                "%(tap_device_name)s already exists on bridge "
                "%(bridge_name)s", data)
        return True
Example #6
0
    def ensure_bridge(self, bridge_name, interface=None, ips=None,
                      gateway=None, physical=False):
        """Create a bridge unless it already exists."""
        # _bridge_exists_and_ensure_up instead of device_exists is used here
        # because there are cases where the bridge exists but it's not UP,
        # for example:
        # 1) A greenthread was executing this function and had not yet executed
        # "ip link set bridge_name up" before eventlet switched to this
        # thread running the same function
        # 2) The Nova VIF driver was running concurrently and had just created
        #    the bridge, but had not yet put it UP
        if not self._bridge_exists_and_ensure_up(bridge_name):
            LOG.debug("Starting bridge %(bridge_name)s for subinterface "
                      "%(interface)s",
                      {'bridge_name': bridge_name, 'interface': interface})
            bridge_device = bridge_lib.BridgeDevice.addbr(bridge_name)
            if bridge_device.setfd(0):
                return
            if bridge_device.disable_ipv6():
                return
            if bridge_device.link.set_up():
                return
            LOG.debug("Done starting bridge %(bridge_name)s for "
                      "subinterface %(interface)s",
                      {'bridge_name': bridge_name, 'interface': interface})
        else:
            bridge_device = bridge_lib.BridgeDevice(bridge_name)

        if bridge_name not in self.known_bridges:
            bridge_device.set_group_fwd_mask()
            bridge_device.set_ageing(cfg.CONF.network_bridge_ageing,
                                     cfg.CONF.network_physical_ageing,
                                     physical)
            bridge_device.set_multicast_snooping(cfg.CONF.network_bridge_multicast_snooping)
            bridge_device.disable_stp()
            self.known_bridges.add(bridge_name)
        if not interface:
            return bridge_name

        # Update IP info if necessary
        self.update_interface_ip_details(bridge_name, interface, ips, gateway)

        # Ensure interface is in bridge
        ip_lib.IPDevice(interface).link.set_master(bridge_name)
        return bridge_name
    def remove_interface(bridge_name, interface_name):
        bridge_device = bridge_lib.BridgeDevice(bridge_name)
        if bridge_device.exists():
            if not bridge_device.owns_interface(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 bridge_device.delif(interface_name):
                LOG.debug(
                    "Done removing device %(interface_name)s from "
                    "bridge %(bridge_name)s", {
                        'interface_name': interface_name,
                        'bridge_name': bridge_name
                    })
                return True
            else:
                if not bridge_device.owns_interface(interface_name):
                    LOG.debug(
                        "Cannot remove %(interface_name)s from "
                        "%(bridge_name)s. It is not on the bridge.", {
                            'interface_name': interface_name,
                            'bridge_name': bridge_name
                        })
                    return False
                msg = _("Error deleting %(interface_name)s from bridge "
                        "%(bridge_name)s") % {
                            'interface_name': interface_name,
                            'bridge_name': bridge_name
                        }
                raise RuntimeError(msg)
        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
Example #8
0
    def delete_bridge(self, bridge_name):
        bridge_device = bridge_lib.BridgeDevice(bridge_name)
        if bridge_device.exists():
            physical_interfaces = set(self.interface_mappings.values())
            interfaces_on_bridge = bridge_device.get_interfaces()
            for interface in interfaces_on_bridge:
                self.remove_interface(bridge_name, interface)

                if interface.startswith(VXLAN_INTERFACE_PREFIX):
                    self.delete_interface(interface)
                else:
                    # Match the vlan/flat interface in the bridge.
                    # If the bridge has an IP, it mean that this IP was moved
                    # from the current interface, which also mean that this
                    # interface was not created by the agent.
                    ips, gateway = self.get_interface_details(bridge_name)
                    if ips:
                        self.update_interface_ip_details(interface,
                                                         bridge_name,
                                                         ips, gateway)
                    elif interface not in physical_interfaces:
                        self.delete_interface(interface)

            try:
                LOG.debug("Deleting bridge %s", bridge_name)
                if bridge_device.link.set_down():
                    return
                if bridge_device.delbr():
                    return
                LOG.debug("Done deleting bridge %s", bridge_name)
            except RuntimeError:
                with excutils.save_and_reraise_exception() as ctxt:
                    if not bridge_device.exists():
                        # the exception was likely a side effect of the bridge
                        # being removed by nova during handling,
                        # so we just return
                        ctxt.reraise = False
                        LOG.debug("Cannot delete bridge %s; it does not exist",
                                  bridge_name)
                        return
        else:
            LOG.debug("Cannot delete bridge %s; it does not exist",
                      bridge_name)
Example #9
0
 def setup_isoflat_bridges(self):
     for physical_network in self.iso_bridge_mappings:
         phy_br_name = self.iso_bridge_mappings[physical_network]
         if physical_network not in self.ovs_bridge_mappings:
             self._bridge_mappings_changed = True
             if not bridge_lib.BridgeDevice(phy_br_name).exists():
                 LOG.error(
                     "Linux bridge %(bridge)s for physical network "
                     "%(physical_network)s does not exist. Isoflat agent "
                     "terminated!", {
                         'physical_network': physical_network,
                         'bridge': phy_br_name
                     })
                 sys.exit(1)
             iso_br_name = self._allocate_bridge_name()
             self.ovs_bridge_mappings[physical_network] = iso_br_name
         else:
             iso_br_name = self.ovs_bridge_mappings[physical_network]
         self._setup_isoflat_bridge(phy_br_name, iso_br_name)
Example #10
0
    def unbind_interface_on_host(self, uuid):
        if uuid not in self.interfaces:
            LOG.debug('unknown port %s unbinding request - ignored' % uuid)
        else:
            props = self.interfaces[uuid]
            iface_idx = props['iface_idx']

            LOG.debug('unbinding port %s, recorded as type %s' %
                      (uuid, props['bind_type']))

            # We no longer need this interface.  Specifically if it's
            # a vhostuser interface it's annoying to have it around
            # because the VM's memory (hugepages) will not be
            # released.  So, here, we destroy it.

            if props['bind_type'] == 'vhostuser':
                # remove port from bridge (sets to l3 mode) prior to deletion
                self.vpp.delete_from_bridge(iface_idx)
                self.vpp.delete_vhostuser(iface_idx)
            elif props['bind_type'] in ['maketap', 'plugtap']:
                # remove port from bridge (sets to l3 mode) prior to deletion
                self.vpp.delete_from_bridge(iface_idx)
                self.vpp.delete_tap(iface_idx)
                if props['bind_type'] == 'plugtap':
                    name = uuid[0:11]
                    bridge_name = 'br-' + name
                    bridge = bridge_lib.BridgeDevice(bridge_name)
                    if bridge.exists():
                        # These may fail, don't care much
                        try:
                            if bridge.owns_interface(props['int_tap_name']):
                                bridge.delif(props['int_tap_name'])
                            if bridge.owns_interface(props['ext_tap_name']):
                                bridge.delif(props['ext_tap_name'])
                            bridge.link.set_down()
                            bridge.delbr()
                        except Exception as exc:
                            LOG.debug(exc)
            else:
                LOG.error('Unknown port type %s during unbind' %
                          props['bind_type'])
 def remove_interface(self, bridge_name, interface_name):
     bridge_device = bridge_lib.BridgeDevice(bridge_name)
     if bridge_device.exists():
         if not bridge_device.owns_interface(interface_name):
             return True
         LOG.debug(
             "Removing device %(interface_name)s from bridge "
             "%(bridge_name)s", {
                 'interface_name': interface_name,
                 'bridge_name': bridge_name
             })
         try:
             bridge_device.delif(interface_name)
             LOG.debug(
                 "Done removing device %(interface_name)s from "
                 "bridge %(bridge_name)s", {
                     'interface_name': interface_name,
                     'bridge_name': bridge_name
                 })
             return True
         except RuntimeError:
             with excutils.save_and_reraise_exception() as ctxt:
                 if not bridge_device.owns_interface(interface_name):
                     # the exception was likely a side effect of the tap
                     # being deleted by some other agent during handling
                     ctxt.reraise = False
                     LOG.debug(
                         "Cannot remove %(interface_name)s from "
                         "%(bridge_name)s. It is not on the bridge.", {
                             'interface_name': interface_name,
                             'bridge_name': bridge_name
                         })
                     return False
     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
Example #12
0
 def remove_interface(self, bridge_name, interface_name):
     bridge_device = bridge_lib.BridgeDevice(bridge_name)
     if bridge_device.exists():
         if not bridge_lib.is_bridged_interface(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 bridge_device.delif(interface_name):
             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 _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
Example #14
0
 def ensure_bridge(self, bridge_name):
     """Create a bridge unless it already exists."""
     # _bridge_exists_and_ensure_up instead of device_exists is used here
     # because there are cases where the bridge exists but it's not UP,
     # for example:
     # 1) A greenthread was executing this function and had not yet executed
     # "ip link set bridge_name up" before eventlet switched to this
     # thread running the same function
     # 2) The Nova VIF driver was running concurrently and had just created
     #    the bridge, but had not yet put it UP
     if not self._bridge_exists_and_ensure_up(bridge_name):
         bridge_device = bridge_lib.BridgeDevice.addbr(bridge_name)
         if bridge_device.setfd(0):
             return
         if bridge_device.disable_stp():
             return
         if bridge_device.disable_ipv6():
             return
         if bridge_device.link.set_up():
             return
     else:
         bridge_device = bridge_lib.BridgeDevice(bridge_name)
     return bridge_device
Example #15
0
 def remove_interface(self, bridge_name, interface_name, down=False):
     return not ip_lib.IPDevice(interface).link.set_master(None, down=down)
     # Ignore the rest
     bridge_device = bridge_lib.BridgeDevice(bridge_name)
     if bridge_device.exists():
         if not bridge_lib.is_bridged_interface(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 bridge_device.delif(interface_name):
             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
Example #16
0
 def test_set_forward_delay(self):
     bridge = bridge_lib.BridgeDevice(self.bridge.name)
     for fd in (10, 200, 3000, 40000):
         bridge.setfd(fd)
         br_info = self._get_bridge_info()
         self.assertEqual(fd, br_info['forward_delay'])
 def get_tap_devices_count(self, bridge_name):
     if_list = bridge_lib.BridgeDevice(bridge_name).get_interfaces()
     return len([
         interface for interface in if_list
         if interface.startswith(constants.TAP_DEVICE_PREFIX)
     ])
Example #18
0
 def _if_bridge_exists(bridge_name):
     ovs = ovs_lib.BaseOVS()
     if bridge_name in ovs.get_bridges() or bridge_lib.BridgeDevice(
             bridge_name).exists():
         return True
     return False
Example #19
0
 def test_get_interfaces_no_bridge(self):
     bridge = bridge_lib.BridgeDevice('--fake--')
     self.assertEqual([], bridge.get_interfaces())
Example #20
0
 def test_owns_interface(self):
     br = bridge_lib.BridgeDevice('br-int')
     exists = lambda path: path == "/sys/class/net/br-int/brif/abc"
     with mock.patch('os.path.exists', side_effect=exists):
         self.assertTrue(br.owns_interface("abc"))
         self.assertFalse(br.owns_interface("def"))
Example #21
0
 def test_get_interfaces(self):
     br = bridge_lib.BridgeDevice('br-int')
     interfaces = ["tap1", "tap2"]
     with mock.patch('os.listdir', side_effect=[interfaces, OSError()]):
         self.assertEqual(interfaces, br.get_interfaces())
         self.assertEqual([], br.get_interfaces())
Example #22
0
 def test_is_bridged_interface_and_remove(self):
     bridge = bridge_lib.BridgeDevice(self.bridge.name)
     bridge_port = self.port_fixture.br_port.name
     self.assertTrue(bridge_lib.is_bridged_interface(bridge_port))
     bridge.delif(bridge_port)
     self.assertFalse(bridge_lib.is_bridged_interface(bridge_port))
Example #23
0
 def test_delete_bridge(self):
     bridge = bridge_lib.BridgeDevice(self.bridge.name)
     self.assertTrue(bridge.exists())
     bridge.delbr()
     self.assertFalse(bridge.exists())