Add 'devname' to nova.network.model.VIF class
Add a 'devname' field to nova.network.model.VIF to allow network drivers to specify a desired TAP device name. Update the Quantum driver to set a device name, and update the libvirt VIF drivers to honour it. Blueprint: libvirt-vif-driver Change-Id: Ia8dd546af36e7f6c22efd7c696fb58b37aac0061 Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
		@@ -32,9 +32,10 @@ VIF_TYPE_802_QBG = '802.1qbg'
 | 
				
			|||||||
VIF_TYPE_802_QBH = '802.1qbh'
 | 
					VIF_TYPE_802_QBH = '802.1qbh'
 | 
				
			||||||
VIF_TYPE_OTHER = 'other'
 | 
					VIF_TYPE_OTHER = 'other'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Constant for max length of 'bridge' in Network class
 | 
					# Constant for max length of network interface names
 | 
				
			||||||
# Chosen to match max Linux NIC name length
 | 
					# eg 'bridge' in the Network class or 'devname' in
 | 
				
			||||||
BRIDGE_NAME_LEN = 14
 | 
					# the VIF class
 | 
				
			||||||
 | 
					NIC_NAME_LEN = 14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Model(dict):
 | 
					class Model(dict):
 | 
				
			||||||
@@ -206,13 +207,14 @@ class Network(Model):
 | 
				
			|||||||
class VIF(Model):
 | 
					class VIF(Model):
 | 
				
			||||||
    """Represents a Virtual Interface in Nova."""
 | 
					    """Represents a Virtual Interface in Nova."""
 | 
				
			||||||
    def __init__(self, id=None, address=None, network=None, type=None,
 | 
					    def __init__(self, id=None, address=None, network=None, type=None,
 | 
				
			||||||
                 **kwargs):
 | 
					                 devname=None, **kwargs):
 | 
				
			||||||
        super(VIF, self).__init__()
 | 
					        super(VIF, self).__init__()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self['id'] = id
 | 
					        self['id'] = id
 | 
				
			||||||
        self['address'] = address
 | 
					        self['address'] = address
 | 
				
			||||||
        self['network'] = network or None
 | 
					        self['network'] = network or None
 | 
				
			||||||
        self['type'] = type
 | 
					        self['type'] = type
 | 
				
			||||||
 | 
					        self['devname'] = devname
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._set_meta(kwargs)
 | 
					        self._set_meta(kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -377,6 +379,7 @@ class NetworkInfo(list):
 | 
				
			|||||||
                         'broadcast': str(subnet_v4.as_netaddr().broadcast),
 | 
					                         'broadcast': str(subnet_v4.as_netaddr().broadcast),
 | 
				
			||||||
                         'mac': vif['address'],
 | 
					                         'mac': vif['address'],
 | 
				
			||||||
                         'vif_type': vif['type'],
 | 
					                         'vif_type': vif['type'],
 | 
				
			||||||
 | 
					                         'vif_devname': vif.get('devname'),
 | 
				
			||||||
                         'vif_uuid': vif['id'],
 | 
					                         'vif_uuid': vif['id'],
 | 
				
			||||||
                         'rxtx_cap': vif.get_meta('rxtx_cap', 0),
 | 
					                         'rxtx_cap': vif.get_meta('rxtx_cap', 0),
 | 
				
			||||||
                         'dns': [get_ip(ip) for ip in subnet_v4['dns']],
 | 
					                         'dns': [get_ip(ip) for ip in subnet_v4['dns']],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -593,7 +593,10 @@ class API(base.Base):
 | 
				
			|||||||
                bridge = "brq" + port['network_id']
 | 
					                bridge = "brq" + port['network_id']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if bridge is not None:
 | 
					            if bridge is not None:
 | 
				
			||||||
                bridge = bridge[:network_model.BRIDGE_NAME_LEN]
 | 
					                bridge = bridge[:network_model.NIC_NAME_LEN]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            devname = "tap" + port['id']
 | 
				
			||||||
 | 
					            devname = devname[:network_model.NIC_NAME_LEN]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            network = network_model.Network(
 | 
					            network = network_model.Network(
 | 
				
			||||||
                id=port['network_id'],
 | 
					                id=port['network_id'],
 | 
				
			||||||
@@ -607,7 +610,8 @@ class API(base.Base):
 | 
				
			|||||||
                id=port['id'],
 | 
					                id=port['id'],
 | 
				
			||||||
                address=port['mac_address'],
 | 
					                address=port['mac_address'],
 | 
				
			||||||
                network=network,
 | 
					                network=network,
 | 
				
			||||||
                type=port.get('binding:vif_type')))
 | 
					                type=port.get('binding:vif_type'),
 | 
				
			||||||
 | 
					                devname=devname))
 | 
				
			||||||
        return nw_info
 | 
					        return nw_info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _get_subnets_from_port(self, context, port):
 | 
					    def _get_subnets_from_port(self, context, port):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -186,6 +186,7 @@ class FlatNetworkTestCase(test.TestCase):
 | 
				
			|||||||
                     'mac': 'DE:AD:BE:EF:00:%02x' % nid,
 | 
					                     'mac': 'DE:AD:BE:EF:00:%02x' % nid,
 | 
				
			||||||
                     'rxtx_cap': 30,
 | 
					                     'rxtx_cap': 30,
 | 
				
			||||||
                     'vif_type': net_model.VIF_TYPE_BRIDGE,
 | 
					                     'vif_type': net_model.VIF_TYPE_BRIDGE,
 | 
				
			||||||
 | 
					                     'vif_devname': None,
 | 
				
			||||||
                     'vif_uuid':
 | 
					                     'vif_uuid':
 | 
				
			||||||
                        '00000000-0000-0000-0000-00000000000000%02d' % nid,
 | 
					                        '00000000-0000-0000-0000-00000000000000%02d' % nid,
 | 
				
			||||||
                     'should_create_vlan': False,
 | 
					                     'should_create_vlan': False,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,7 +47,8 @@ class LibvirtVifTestCase(test.TestCase):
 | 
				
			|||||||
        'gateway_v6': net['gateway_v6'],
 | 
					        'gateway_v6': net['gateway_v6'],
 | 
				
			||||||
        'ips': [{'ip': '101.168.1.9'}],
 | 
					        'ips': [{'ip': '101.168.1.9'}],
 | 
				
			||||||
        'dhcp_server': '191.168.1.1',
 | 
					        'dhcp_server': '191.168.1.1',
 | 
				
			||||||
        'vif_uuid': 'vif-xxx-yyy-zzz'
 | 
					        'vif_uuid': 'vif-xxx-yyy-zzz',
 | 
				
			||||||
 | 
					        'vif_devname': 'tap-xxx-yyy-zzz'
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    instance = {
 | 
					    instance = {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@ import nova.context
 | 
				
			|||||||
import nova.db
 | 
					import nova.db
 | 
				
			||||||
from nova.image import glance
 | 
					from nova.image import glance
 | 
				
			||||||
from nova.network import minidns
 | 
					from nova.network import minidns
 | 
				
			||||||
 | 
					from nova.network import model as network_model
 | 
				
			||||||
from nova.openstack.common import cfg
 | 
					from nova.openstack.common import cfg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONF = cfg.CONF
 | 
					CONF = cfg.CONF
 | 
				
			||||||
@@ -91,6 +92,8 @@ def get_test_network_info(count=1):
 | 
				
			|||||||
               'bridge_interface': fake_bridge_interface,
 | 
					               'bridge_interface': fake_bridge_interface,
 | 
				
			||||||
               'injected': False}
 | 
					               'injected': False}
 | 
				
			||||||
    mapping = {'mac': fake,
 | 
					    mapping = {'mac': fake,
 | 
				
			||||||
 | 
					               'vif_type': network_model.VIF_TYPE_BRIDGE,
 | 
				
			||||||
 | 
					               'vif_uuid': 'vif-xxx-yyy-zzz',
 | 
				
			||||||
               'dhcp_server': fake,
 | 
					               'dhcp_server': fake,
 | 
				
			||||||
               'dns': ['fake1', 'fake2'],
 | 
					               'dns': ['fake1', 'fake2'],
 | 
				
			||||||
               'gateway': fake,
 | 
					               'gateway': fake,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from nova import exception
 | 
					from nova import exception
 | 
				
			||||||
from nova.network import linux_net
 | 
					from nova.network import linux_net
 | 
				
			||||||
 | 
					from nova.network import model as network_model
 | 
				
			||||||
from nova.openstack.common import cfg
 | 
					from nova.openstack.common import cfg
 | 
				
			||||||
from nova.openstack.common import log as logging
 | 
					from nova.openstack.common import log as logging
 | 
				
			||||||
from nova import utils
 | 
					from nova import utils
 | 
				
			||||||
@@ -41,11 +42,14 @@ CONF.register_opts(libvirt_vif_opts)
 | 
				
			|||||||
CONF.import_opt('libvirt_type', 'nova.virt.libvirt.driver')
 | 
					CONF.import_opt('libvirt_type', 'nova.virt.libvirt.driver')
 | 
				
			||||||
CONF.import_opt('use_ipv6', 'nova.netconf')
 | 
					CONF.import_opt('use_ipv6', 'nova.netconf')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LINUX_DEV_LEN = 14
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LibvirtBaseVIFDriver(object):
 | 
					class LibvirtBaseVIFDriver(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_vif_devname(self, mapping):
 | 
				
			||||||
 | 
					        if 'vif_devname' in mapping:
 | 
				
			||||||
 | 
					            return mapping['vif_devname']
 | 
				
			||||||
 | 
					        return ("nic" + mapping['vif_uuid'])[:network_model.NIC_NAME_LEN]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_config(self, instance, network, mapping):
 | 
					    def get_config(self, instance, network, mapping):
 | 
				
			||||||
        conf = vconfig.LibvirtConfigGuestInterface()
 | 
					        conf = vconfig.LibvirtConfigGuestInterface()
 | 
				
			||||||
        model = None
 | 
					        model = None
 | 
				
			||||||
@@ -78,7 +82,7 @@ class LibvirtBridgeDriver(LibvirtBaseVIFDriver):
 | 
				
			|||||||
                                      mapping)
 | 
					                                      mapping)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        designer.set_vif_host_backend_bridge_config(
 | 
					        designer.set_vif_host_backend_bridge_config(
 | 
				
			||||||
            conf, network['bridge'], None)
 | 
					            conf, network['bridge'], self.get_vif_devname(mapping))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        name = "nova-instance-" + instance['name'] + "-" + mac_id
 | 
					        name = "nova-instance-" + instance['name'] + "-" + mac_id
 | 
				
			||||||
        primary_addr = mapping['ips'][0]['ip']
 | 
					        primary_addr = mapping['ips'][0]['ip']
 | 
				
			||||||
@@ -134,11 +138,8 @@ class LibvirtOpenVswitchDriver(LibvirtBaseVIFDriver):
 | 
				
			|||||||
    OVS virtual port XML (0.9.10 or earlier).
 | 
					    OVS virtual port XML (0.9.10 or earlier).
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_dev_name(self, iface_id):
 | 
					 | 
				
			||||||
        return ("tap" + iface_id)[:LINUX_DEV_LEN]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_config(self, instance, network, mapping):
 | 
					    def get_config(self, instance, network, mapping):
 | 
				
			||||||
        dev = self.get_dev_name(mapping['vif_uuid'])
 | 
					        dev = self.get_vif_devname(mapping)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        conf = super(LibvirtOpenVswitchDriver,
 | 
					        conf = super(LibvirtOpenVswitchDriver,
 | 
				
			||||||
                     self).get_config(instance,
 | 
					                     self).get_config(instance,
 | 
				
			||||||
@@ -167,7 +168,7 @@ class LibvirtOpenVswitchDriver(LibvirtBaseVIFDriver):
 | 
				
			|||||||
    def plug(self, instance, vif):
 | 
					    def plug(self, instance, vif):
 | 
				
			||||||
        network, mapping = vif
 | 
					        network, mapping = vif
 | 
				
			||||||
        iface_id = mapping['vif_uuid']
 | 
					        iface_id = mapping['vif_uuid']
 | 
				
			||||||
        dev = self.get_dev_name(iface_id)
 | 
					        dev = self.get_vif_devname(mapping)
 | 
				
			||||||
        if not linux_net.device_exists(dev):
 | 
					        if not linux_net.device_exists(dev):
 | 
				
			||||||
            # Older version of the command 'ip' from the iproute2 package
 | 
					            # Older version of the command 'ip' from the iproute2 package
 | 
				
			||||||
            # don't have support for the tuntap option (lp:882568).  If it
 | 
					            # don't have support for the tuntap option (lp:882568).  If it
 | 
				
			||||||
@@ -191,7 +192,7 @@ class LibvirtOpenVswitchDriver(LibvirtBaseVIFDriver):
 | 
				
			|||||||
        try:
 | 
					        try:
 | 
				
			||||||
            network, mapping = vif
 | 
					            network, mapping = vif
 | 
				
			||||||
            self.delete_ovs_vif_port(network['bridge'],
 | 
					            self.delete_ovs_vif_port(network['bridge'],
 | 
				
			||||||
                                     self.get_dev_name(mapping['vif_uuid']))
 | 
					                                     self.get_vif_devname(mapping))
 | 
				
			||||||
        except exception.ProcessExecutionError:
 | 
					        except exception.ProcessExecutionError:
 | 
				
			||||||
            LOG.exception(_("Failed while unplugging vif"), instance=instance)
 | 
					            LOG.exception(_("Failed while unplugging vif"), instance=instance)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -207,11 +208,11 @@ class LibvirtHybridOVSBridgeDriver(LibvirtBridgeDriver,
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_br_name(self, iface_id):
 | 
					    def get_br_name(self, iface_id):
 | 
				
			||||||
        return ("qbr" + iface_id)[:LINUX_DEV_LEN]
 | 
					        return ("qbr" + iface_id)[:network_model.NIC_NAME_LEN]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_veth_pair_names(self, iface_id):
 | 
					    def get_veth_pair_names(self, iface_id):
 | 
				
			||||||
        return (("qvb%s" % iface_id)[:LINUX_DEV_LEN],
 | 
					        return (("qvb%s" % iface_id)[:network_model.NIC_NAME_LEN],
 | 
				
			||||||
                ("qvo%s" % iface_id)[:LINUX_DEV_LEN])
 | 
					                ("qvo%s" % iface_id)[:network_model.NIC_NAME_LEN])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_config(self, instance, network, mapping):
 | 
					    def get_config(self, instance, network, mapping):
 | 
				
			||||||
        br_name = self.get_br_name(mapping['vif_uuid'])
 | 
					        br_name = self.get_br_name(mapping['vif_uuid'])
 | 
				
			||||||
@@ -280,7 +281,8 @@ class LibvirtOpenVswitchVirtualPortDriver(LibvirtBaseVIFDriver):
 | 
				
			|||||||
                                      mapping)
 | 
					                                      mapping)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        designer.set_vif_host_backend_ovs_config(
 | 
					        designer.set_vif_host_backend_ovs_config(
 | 
				
			||||||
            conf, network['bridge'], mapping['vif_uuid'])
 | 
					            conf, network['bridge'], mapping['vif_uuid'],
 | 
				
			||||||
 | 
					            self.get_vif_devname(mapping))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return conf
 | 
					        return conf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -295,15 +297,9 @@ class LibvirtOpenVswitchVirtualPortDriver(LibvirtBaseVIFDriver):
 | 
				
			|||||||
class QuantumLinuxBridgeVIFDriver(LibvirtBaseVIFDriver):
 | 
					class QuantumLinuxBridgeVIFDriver(LibvirtBaseVIFDriver):
 | 
				
			||||||
    """VIF driver for Linux Bridge when running Quantum."""
 | 
					    """VIF driver for Linux Bridge when running Quantum."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_dev_name(self, iface_id):
 | 
					 | 
				
			||||||
        return ("tap" + iface_id)[:LINUX_DEV_LEN]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_config(self, instance, network, mapping):
 | 
					    def get_config(self, instance, network, mapping):
 | 
				
			||||||
        iface_id = mapping['vif_uuid']
 | 
					        linux_net.LinuxBridgeInterfaceDriver.ensure_bridge(network['bridge'],
 | 
				
			||||||
        dev = self.get_dev_name(iface_id)
 | 
					                                                           None,
 | 
				
			||||||
 | 
					 | 
				
			||||||
        bridge = network['bridge']
 | 
					 | 
				
			||||||
        linux_net.LinuxBridgeInterfaceDriver.ensure_bridge(bridge, None,
 | 
					 | 
				
			||||||
                                                           filtering=False)
 | 
					                                                           filtering=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        conf = super(QuantumLinuxBridgeVIFDriver,
 | 
					        conf = super(QuantumLinuxBridgeVIFDriver,
 | 
				
			||||||
@@ -312,7 +308,7 @@ class QuantumLinuxBridgeVIFDriver(LibvirtBaseVIFDriver):
 | 
				
			|||||||
                                      mapping)
 | 
					                                      mapping)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        designer.set_vif_host_backend_bridge_config(
 | 
					        designer.set_vif_host_backend_bridge_config(
 | 
				
			||||||
            conf, bridge, dev)
 | 
					            conf, network['bridge'], self.get_vif_devname(mapping))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return conf
 | 
					        return conf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user