From 78ebb445b349e9407c60c3fe2d21552977a3c299 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 22 Jan 2013 11:32:28 +0000 Subject: [PATCH] Merge LibvirtBridgeDriver class into LibvirtGenericVIFDriver This introduces the LibvirtGenericVIFDriver class which uses the 'vif_type' mapping field to determine what type of host network configuration is required. The LibvirtBridgeDriver class functionality is merged into LibvirtGenericVIFDriver. For backwards compatibility with the Folsom release, the existing LibvirtBridgeDriver class is made to inherit from LibvirtGenericVIFDriver and directly call the bridge specific setup APIs. This eases migration to the new VIF impl during the Grizzly deployment lifecycle, with an expectation that the LibvirtBridgeDriver stub will be deleted in the Hxxxxx release. DocImpact Blueprint: libvirt-vif-driver Change-Id: I948158b5ee0a97f666bb4d21020b552d3475b6d3 Signed-off-by: Daniel P. Berrange --- nova/tests/test_libvirt_vif.py | 41 ++++++++++--- nova/virt/libvirt/driver.py | 2 +- nova/virt/libvirt/vif.py | 107 ++++++++++++++++++++++++++++++--- 3 files changed, 132 insertions(+), 18 deletions(-) diff --git a/nova/tests/test_libvirt_vif.py b/nova/tests/test_libvirt_vif.py index 3861d7dfa8ee..7ce81cc09925 100644 --- a/nova/tests/test_libvirt_vif.py +++ b/nova/tests/test_libvirt_vif.py @@ -16,6 +16,8 @@ from lxml import etree +from nova import exception +from nova.network import model as network_model from nova.openstack.common import cfg from nova import test from nova import utils @@ -48,7 +50,8 @@ class LibvirtVifTestCase(test.TestCase): 'ips': [{'ip': '101.168.1.9'}], 'dhcp_server': '191.168.1.1', 'vif_uuid': 'vif-xxx-yyy-zzz', - 'vif_devname': 'tap-xxx-yyy-zzz' + 'vif_devname': 'tap-xxx-yyy-zzz', + 'vif_type': network_model.VIF_TYPE_BRIDGE, } net_ovs = { @@ -75,6 +78,15 @@ class LibvirtVifTestCase(test.TestCase): 'ovs_interfaceid': 'aaa-bbb-ccc', } + mapping_none = { + 'mac': 'ca:fe:de:ad:be:ef', + 'gateway_v6': net_bridge['gateway_v6'], + 'ips': [{'ip': '101.168.1.9'}], + 'dhcp_server': '191.168.1.1', + 'vif_uuid': 'vif-xxx-yyy-zzz', + 'vif_devname': 'tap-xxx-yyy-zzz', + } + instance = { 'name': 'instance-name', 'uuid': 'instance-uuid' @@ -149,7 +161,7 @@ class LibvirtVifTestCase(test.TestCase): self.flags(libvirt_use_virtio_for_bridges=False, libvirt_type='kvm') - d = vif.LibvirtBridgeDriver() + d = vif.LibvirtGenericVIFDriver() xml = self._get_instance_xml(d, self.net_bridge, self.mapping_bridge) @@ -168,7 +180,7 @@ class LibvirtVifTestCase(test.TestCase): self.flags(libvirt_use_virtio_for_bridges=True, libvirt_type='kvm') - d = vif.LibvirtBridgeDriver() + d = vif.LibvirtGenericVIFDriver() xml = self._get_instance_xml(d, self.net_bridge, self.mapping_bridge) @@ -187,7 +199,7 @@ class LibvirtVifTestCase(test.TestCase): self.flags(libvirt_use_virtio_for_bridges=True, libvirt_type='qemu') - d = vif.LibvirtBridgeDriver() + d = vif.LibvirtGenericVIFDriver() xml = self._get_instance_xml(d, self.net_bridge, self.mapping_bridge) @@ -206,7 +218,7 @@ class LibvirtVifTestCase(test.TestCase): self.flags(libvirt_use_virtio_for_bridges=True, libvirt_type='xen') - d = vif.LibvirtBridgeDriver() + d = vif.LibvirtGenericVIFDriver() xml = self._get_instance_xml(d, self.net_bridge, self.mapping_bridge) @@ -221,8 +233,15 @@ class LibvirtVifTestCase(test.TestCase): ret = node.findall("driver") self.assertEqual(len(ret), 0) - def test_bridge_driver(self): - d = vif.LibvirtBridgeDriver() + def test_generic_driver_none(self): + d = vif.LibvirtGenericVIFDriver() + self.assertRaises(exception.NovaException, + self._get_instance_xml, + d, + self.net_bridge, + self.mapping_none) + + def _check_bridge_driver(self, d): xml = self._get_instance_xml(d, self.net_bridge, self.mapping_bridge) @@ -237,6 +256,14 @@ class LibvirtVifTestCase(test.TestCase): mac = node.find("mac").get("address") self.assertEqual(mac, self.mapping_bridge['mac']) + def test_bridge_driver(self): + d = vif.LibvirtBridgeDriver() + self._check_bridge_driver(d) + + def test_generic_driver_bridge(self): + d = vif.LibvirtGenericVIFDriver() + self._check_bridge_driver(d) + def test_ovs_ethernet_driver(self): d = vif.LibvirtOpenVswitchDriver() xml = self._get_instance_xml(d, diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 7439ad40ad6c..9e6d7350d85e 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -140,7 +140,7 @@ libvirt_opts = [ 'raw, qcow2, vmdk, vdi). ' 'Defaults to same as source image'), cfg.StrOpt('libvirt_vif_driver', - default='nova.virt.libvirt.vif.LibvirtBridgeDriver', + default='nova.virt.libvirt.vif.LibvirtGenericVIFDriver', help='The libvirt VIF driver to configure the VIFs.'), cfg.ListOpt('libvirt_volume_drivers', default=[ diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index d90a5e2952e5..f185e8efd320 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -72,19 +72,22 @@ class LibvirtBaseVIFDriver(object): return conf + def plug(self, instance, vif): + pass -class LibvirtBridgeDriver(LibvirtBaseVIFDriver): - """VIF driver for Linux bridge.""" + def unplug(self, instance, vif): + pass + + +class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + """Generic VIF driver for libvirt networking.""" def get_bridge_name(self, network): return network['bridge'] - def get_config(self, instance, network, mapping): + def get_config_bridge(self, instance, network, mapping): """Get VIF configurations for bridge type.""" - - mac_id = mapping['mac'].replace(':', '') - - conf = super(LibvirtBridgeDriver, + conf = super(LibvirtGenericVIFDriver, self).get_config(instance, network, mapping) @@ -93,6 +96,7 @@ class LibvirtBridgeDriver(LibvirtBaseVIFDriver): conf, self.get_bridge_name(network), self.get_vif_devname(mapping)) + mac_id = mapping['mac'].replace(':', '') name = "nova-instance-" + instance['name'] + "-" + mac_id primary_addr = mapping['ips'][0]['ip'] dhcp_server = ra_server = ipv4_cidr = ipv6_cidr = None @@ -112,8 +116,29 @@ class LibvirtBridgeDriver(LibvirtBaseVIFDriver): return conf - def plug(self, instance, vif): + def get_config(self, instance, network, mapping): + vif_type = mapping.get('vif_type') + + LOG.debug(_("vif_type=%(vif_type)s instance=%(instance)s " + "network=%(network)s mapping=%(mapping)s") + % locals()) + + if vif_type is None: + raise exception.NovaException( + _("vif_type parameter must be present " + "for this vif_driver implementation")) + + if vif_type == network_model.VIF_TYPE_BRIDGE: + return self.get_config_bridge(instance, network, mapping) + else: + raise exception.NovaException( + _("Unexpected vif_type=%s") % vif_type) + + def plug_bridge(self, instance, vif): """Ensure that the bridge exists, and add VIF to it.""" + super(LibvirtGenericVIFDriver, + self).plug(instance, vif) + network, mapping = vif if (not network.get('multi_host') and mapping.get('should_create_bridge')): @@ -135,9 +160,71 @@ class LibvirtBridgeDriver(LibvirtBaseVIFDriver): self.get_bridge_name(network), iface) - def unplug(self, instance, vif): + def plug(self, instance, vif): + network, mapping = vif + vif_type = mapping.get('vif_type') + + LOG.debug(_("vif_type=%(vif_type)s instance=%(instance)s " + "network=%(network)s mapping=%(mapping)s") + % locals()) + + if vif_type is None: + raise exception.NovaException( + _("vif_type parameter must be present " + "for this vif_driver implementation")) + + if vif_type == network_model.VIF_TYPE_BRIDGE: + self.plug_bridge(instance, vif) + else: + raise exception.NovaException( + _("Unexpected vif_type=%s") % vif_type) + + def unplug_bridge(self, instance, vif): """No manual unplugging required.""" - pass + super(LibvirtGenericVIFDriver, + self).unplug(instance, vif) + + def unplug(self, instance, vif): + network, mapping = vif + vif_type = mapping.get('vif_type') + + LOG.debug(_("vif_type=%(vif_type)s instance=%(instance)s " + "network=%(network)s mapping=%(mapping)s") + % locals()) + + if vif_type is None: + raise exception.NovaException( + _("vif_type parameter must be present " + "for this vif_driver implementation")) + + if vif_type == network_model.VIF_TYPE_BRIDGE: + self.unplug_bridge(instance, vif) + else: + raise exception.NovaException( + _("Unexpected vif_type=%s") % vif_type) + + +class LibvirtBridgeDriver(LibvirtGenericVIFDriver): + """Deprecated in favour of LibvirtGenericVIFDriver. + Retained in Grizzly for compatibility with Quantum + drivers which do not yet report 'vif_type' port binding. + To be removed in Hxxxx.""" + + def __init__(self): + LOG.deprecated( + _("LibvirtBridgeDriver is deprecated and " + "will be removed in the Hxxxx release. Please " + "update the 'libvirt_vif_driver' config parameter " + "to use the LibvirtGenericVIFDriver class instead")) + + def get_config(self, instance, network, mapping): + return self.get_config_bridge(instance, network, mapping) + + def plug(self, instance, vif): + self.plug_bridge(instance, vif) + + def unplug(self, instance, vif): + self.unplug_bridge(instance, vif) class LibvirtOpenVswitchDriver(LibvirtBaseVIFDriver):