From fa96bbf489fac8d16104d51c393d3d7777e0c65c Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 4 Jan 2013 12:44:00 +0000 Subject: [PATCH] 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 --- nova/network/model.py | 11 +++++--- nova/network/quantumv2/api.py | 8 ++++-- nova/tests/network/test_manager.py | 1 + nova/tests/test_libvirt_vif.py | 3 ++- nova/tests/utils.py | 3 +++ nova/virt/libvirt/vif.py | 40 ++++++++++++++---------------- 6 files changed, 37 insertions(+), 29 deletions(-) diff --git a/nova/network/model.py b/nova/network/model.py index f0a5d9d89e4d..e4fe0d54cf3c 100644 --- a/nova/network/model.py +++ b/nova/network/model.py @@ -32,9 +32,10 @@ VIF_TYPE_802_QBG = '802.1qbg' VIF_TYPE_802_QBH = '802.1qbh' VIF_TYPE_OTHER = 'other' -# Constant for max length of 'bridge' in Network class -# Chosen to match max Linux NIC name length -BRIDGE_NAME_LEN = 14 +# Constant for max length of network interface names +# eg 'bridge' in the Network class or 'devname' in +# the VIF class +NIC_NAME_LEN = 14 class Model(dict): @@ -206,13 +207,14 @@ class Network(Model): class VIF(Model): """Represents a Virtual Interface in Nova.""" def __init__(self, id=None, address=None, network=None, type=None, - **kwargs): + devname=None, **kwargs): super(VIF, self).__init__() self['id'] = id self['address'] = address self['network'] = network or None self['type'] = type + self['devname'] = devname self._set_meta(kwargs) @@ -377,6 +379,7 @@ class NetworkInfo(list): 'broadcast': str(subnet_v4.as_netaddr().broadcast), 'mac': vif['address'], 'vif_type': vif['type'], + 'vif_devname': vif.get('devname'), 'vif_uuid': vif['id'], 'rxtx_cap': vif.get_meta('rxtx_cap', 0), 'dns': [get_ip(ip) for ip in subnet_v4['dns']], diff --git a/nova/network/quantumv2/api.py b/nova/network/quantumv2/api.py index 780952bab991..8347ee94d458 100644 --- a/nova/network/quantumv2/api.py +++ b/nova/network/quantumv2/api.py @@ -593,7 +593,10 @@ class API(base.Base): bridge = "brq" + port['network_id'] 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( id=port['network_id'], @@ -607,7 +610,8 @@ class API(base.Base): id=port['id'], address=port['mac_address'], network=network, - type=port.get('binding:vif_type'))) + type=port.get('binding:vif_type'), + devname=devname)) return nw_info def _get_subnets_from_port(self, context, port): diff --git a/nova/tests/network/test_manager.py b/nova/tests/network/test_manager.py index 385aea1eecd8..1552630fb938 100644 --- a/nova/tests/network/test_manager.py +++ b/nova/tests/network/test_manager.py @@ -186,6 +186,7 @@ class FlatNetworkTestCase(test.TestCase): 'mac': 'DE:AD:BE:EF:00:%02x' % nid, 'rxtx_cap': 30, 'vif_type': net_model.VIF_TYPE_BRIDGE, + 'vif_devname': None, 'vif_uuid': '00000000-0000-0000-0000-00000000000000%02d' % nid, 'should_create_vlan': False, diff --git a/nova/tests/test_libvirt_vif.py b/nova/tests/test_libvirt_vif.py index 9271afb13554..11ffa020f59e 100644 --- a/nova/tests/test_libvirt_vif.py +++ b/nova/tests/test_libvirt_vif.py @@ -47,7 +47,8 @@ class LibvirtVifTestCase(test.TestCase): 'gateway_v6': net['gateway_v6'], 'ips': [{'ip': '101.168.1.9'}], '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 = { diff --git a/nova/tests/utils.py b/nova/tests/utils.py index 00b70ceb3296..6437f9537037 100644 --- a/nova/tests/utils.py +++ b/nova/tests/utils.py @@ -20,6 +20,7 @@ import nova.context import nova.db from nova.image import glance from nova.network import minidns +from nova.network import model as network_model from nova.openstack.common import cfg CONF = cfg.CONF @@ -91,6 +92,8 @@ def get_test_network_info(count=1): 'bridge_interface': fake_bridge_interface, 'injected': False} mapping = {'mac': fake, + 'vif_type': network_model.VIF_TYPE_BRIDGE, + 'vif_uuid': 'vif-xxx-yyy-zzz', 'dhcp_server': fake, 'dns': ['fake1', 'fake2'], 'gateway': fake, diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index 29bf2d09d15d..54de9da2d8b1 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -21,6 +21,7 @@ from nova import exception 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 log as logging 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('use_ipv6', 'nova.netconf') -LINUX_DEV_LEN = 14 - 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): conf = vconfig.LibvirtConfigGuestInterface() model = None @@ -78,7 +82,7 @@ class LibvirtBridgeDriver(LibvirtBaseVIFDriver): mapping) 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 primary_addr = mapping['ips'][0]['ip'] @@ -134,11 +138,8 @@ class LibvirtOpenVswitchDriver(LibvirtBaseVIFDriver): 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): - dev = self.get_dev_name(mapping['vif_uuid']) + dev = self.get_vif_devname(mapping) conf = super(LibvirtOpenVswitchDriver, self).get_config(instance, @@ -167,7 +168,7 @@ class LibvirtOpenVswitchDriver(LibvirtBaseVIFDriver): def plug(self, instance, vif): network, mapping = vif 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): # Older version of the command 'ip' from the iproute2 package # don't have support for the tuntap option (lp:882568). If it @@ -191,7 +192,7 @@ class LibvirtOpenVswitchDriver(LibvirtBaseVIFDriver): try: network, mapping = vif self.delete_ovs_vif_port(network['bridge'], - self.get_dev_name(mapping['vif_uuid'])) + self.get_vif_devname(mapping)) except exception.ProcessExecutionError: LOG.exception(_("Failed while unplugging vif"), instance=instance) @@ -207,11 +208,11 @@ class LibvirtHybridOVSBridgeDriver(LibvirtBridgeDriver, """ 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): - return (("qvb%s" % iface_id)[:LINUX_DEV_LEN], - ("qvo%s" % iface_id)[:LINUX_DEV_LEN]) + return (("qvb%s" % iface_id)[:network_model.NIC_NAME_LEN], + ("qvo%s" % iface_id)[:network_model.NIC_NAME_LEN]) def get_config(self, instance, network, mapping): br_name = self.get_br_name(mapping['vif_uuid']) @@ -280,7 +281,8 @@ class LibvirtOpenVswitchVirtualPortDriver(LibvirtBaseVIFDriver): mapping) 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 @@ -295,15 +297,9 @@ class LibvirtOpenVswitchVirtualPortDriver(LibvirtBaseVIFDriver): class QuantumLinuxBridgeVIFDriver(LibvirtBaseVIFDriver): """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): - iface_id = mapping['vif_uuid'] - dev = self.get_dev_name(iface_id) - - bridge = network['bridge'] - linux_net.LinuxBridgeInterfaceDriver.ensure_bridge(bridge, None, + linux_net.LinuxBridgeInterfaceDriver.ensure_bridge(network['bridge'], + None, filtering=False) conf = super(QuantumLinuxBridgeVIFDriver, @@ -312,7 +308,7 @@ class QuantumLinuxBridgeVIFDriver(LibvirtBaseVIFDriver): mapping) designer.set_vif_host_backend_bridge_config( - conf, bridge, dev) + conf, network['bridge'], self.get_vif_devname(mapping)) return conf