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 <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2013-01-22 11:32:28 +00:00
parent 113880fe16
commit 78ebb445b3
3 changed files with 132 additions and 18 deletions

View File

@ -16,6 +16,8 @@
from lxml import etree from lxml import etree
from nova import exception
from nova.network import model as network_model
from nova.openstack.common import cfg from nova.openstack.common import cfg
from nova import test from nova import test
from nova import utils from nova import utils
@ -48,7 +50,8 @@ class LibvirtVifTestCase(test.TestCase):
'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' 'vif_devname': 'tap-xxx-yyy-zzz',
'vif_type': network_model.VIF_TYPE_BRIDGE,
} }
net_ovs = { net_ovs = {
@ -75,6 +78,15 @@ class LibvirtVifTestCase(test.TestCase):
'ovs_interfaceid': 'aaa-bbb-ccc', '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 = { instance = {
'name': 'instance-name', 'name': 'instance-name',
'uuid': 'instance-uuid' 'uuid': 'instance-uuid'
@ -149,7 +161,7 @@ class LibvirtVifTestCase(test.TestCase):
self.flags(libvirt_use_virtio_for_bridges=False, self.flags(libvirt_use_virtio_for_bridges=False,
libvirt_type='kvm') libvirt_type='kvm')
d = vif.LibvirtBridgeDriver() d = vif.LibvirtGenericVIFDriver()
xml = self._get_instance_xml(d, xml = self._get_instance_xml(d,
self.net_bridge, self.net_bridge,
self.mapping_bridge) self.mapping_bridge)
@ -168,7 +180,7 @@ class LibvirtVifTestCase(test.TestCase):
self.flags(libvirt_use_virtio_for_bridges=True, self.flags(libvirt_use_virtio_for_bridges=True,
libvirt_type='kvm') libvirt_type='kvm')
d = vif.LibvirtBridgeDriver() d = vif.LibvirtGenericVIFDriver()
xml = self._get_instance_xml(d, xml = self._get_instance_xml(d,
self.net_bridge, self.net_bridge,
self.mapping_bridge) self.mapping_bridge)
@ -187,7 +199,7 @@ class LibvirtVifTestCase(test.TestCase):
self.flags(libvirt_use_virtio_for_bridges=True, self.flags(libvirt_use_virtio_for_bridges=True,
libvirt_type='qemu') libvirt_type='qemu')
d = vif.LibvirtBridgeDriver() d = vif.LibvirtGenericVIFDriver()
xml = self._get_instance_xml(d, xml = self._get_instance_xml(d,
self.net_bridge, self.net_bridge,
self.mapping_bridge) self.mapping_bridge)
@ -206,7 +218,7 @@ class LibvirtVifTestCase(test.TestCase):
self.flags(libvirt_use_virtio_for_bridges=True, self.flags(libvirt_use_virtio_for_bridges=True,
libvirt_type='xen') libvirt_type='xen')
d = vif.LibvirtBridgeDriver() d = vif.LibvirtGenericVIFDriver()
xml = self._get_instance_xml(d, xml = self._get_instance_xml(d,
self.net_bridge, self.net_bridge,
self.mapping_bridge) self.mapping_bridge)
@ -221,8 +233,15 @@ class LibvirtVifTestCase(test.TestCase):
ret = node.findall("driver") ret = node.findall("driver")
self.assertEqual(len(ret), 0) self.assertEqual(len(ret), 0)
def test_bridge_driver(self): def test_generic_driver_none(self):
d = vif.LibvirtBridgeDriver() 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, xml = self._get_instance_xml(d,
self.net_bridge, self.net_bridge,
self.mapping_bridge) self.mapping_bridge)
@ -237,6 +256,14 @@ class LibvirtVifTestCase(test.TestCase):
mac = node.find("mac").get("address") mac = node.find("mac").get("address")
self.assertEqual(mac, self.mapping_bridge['mac']) 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): def test_ovs_ethernet_driver(self):
d = vif.LibvirtOpenVswitchDriver() d = vif.LibvirtOpenVswitchDriver()
xml = self._get_instance_xml(d, xml = self._get_instance_xml(d,

View File

@ -140,7 +140,7 @@ libvirt_opts = [
'raw, qcow2, vmdk, vdi). ' 'raw, qcow2, vmdk, vdi). '
'Defaults to same as source image'), 'Defaults to same as source image'),
cfg.StrOpt('libvirt_vif_driver', 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.'), help='The libvirt VIF driver to configure the VIFs.'),
cfg.ListOpt('libvirt_volume_drivers', cfg.ListOpt('libvirt_volume_drivers',
default=[ default=[

View File

@ -72,19 +72,22 @@ class LibvirtBaseVIFDriver(object):
return conf return conf
def plug(self, instance, vif):
pass
class LibvirtBridgeDriver(LibvirtBaseVIFDriver): def unplug(self, instance, vif):
"""VIF driver for Linux bridge.""" pass
class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
"""Generic VIF driver for libvirt networking."""
def get_bridge_name(self, network): def get_bridge_name(self, network):
return network['bridge'] return network['bridge']
def get_config(self, instance, network, mapping): def get_config_bridge(self, instance, network, mapping):
"""Get VIF configurations for bridge type.""" """Get VIF configurations for bridge type."""
conf = super(LibvirtGenericVIFDriver,
mac_id = mapping['mac'].replace(':', '')
conf = super(LibvirtBridgeDriver,
self).get_config(instance, self).get_config(instance,
network, network,
mapping) mapping)
@ -93,6 +96,7 @@ class LibvirtBridgeDriver(LibvirtBaseVIFDriver):
conf, self.get_bridge_name(network), conf, self.get_bridge_name(network),
self.get_vif_devname(mapping)) self.get_vif_devname(mapping))
mac_id = mapping['mac'].replace(':', '')
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']
dhcp_server = ra_server = ipv4_cidr = ipv6_cidr = None dhcp_server = ra_server = ipv4_cidr = ipv6_cidr = None
@ -112,8 +116,29 @@ class LibvirtBridgeDriver(LibvirtBaseVIFDriver):
return conf 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.""" """Ensure that the bridge exists, and add VIF to it."""
super(LibvirtGenericVIFDriver,
self).plug(instance, vif)
network, mapping = vif network, mapping = vif
if (not network.get('multi_host') and if (not network.get('multi_host') and
mapping.get('should_create_bridge')): mapping.get('should_create_bridge')):
@ -135,9 +160,71 @@ class LibvirtBridgeDriver(LibvirtBaseVIFDriver):
self.get_bridge_name(network), self.get_bridge_name(network),
iface) 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.""" """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): class LibvirtOpenVswitchDriver(LibvirtBaseVIFDriver):