summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/tests/test_libvirt_vif.py41
-rw-r--r--nova/virt/libvirt/vif.py165
2 files changed, 127 insertions, 79 deletions
diff --git a/nova/tests/test_libvirt_vif.py b/nova/tests/test_libvirt_vif.py
index 5c3d148b7..c6937bde3 100644
--- a/nova/tests/test_libvirt_vif.py
+++ b/nova/tests/test_libvirt_vif.py
@@ -335,6 +335,7 @@ class LibvirtVifTestCase(test.TestCase):
br_want)
def _check_ovs_ethernet_driver(self, d, net, mapping):
+ self.flags(firewall_driver="nova.virt.firewall.NoopFirewallDriver")
xml = self._get_instance_xml(d, net, mapping)
doc = etree.fromstring(xml)
@@ -371,6 +372,7 @@ class LibvirtVifTestCase(test.TestCase):
self.mapping_ovs)
def _check_ovs_virtualport_driver(self, d, net, mapping, want_iface_id):
+ self.flags(firewall_driver="nova.virt.firewall.NoopFirewallDriver")
xml = self._get_instance_xml(d, net, mapping)
doc = etree.fromstring(xml)
@@ -418,14 +420,9 @@ class LibvirtVifTestCase(test.TestCase):
self.mapping_ovs,
want_iface_id)
- def test_quantum_hybrid_driver(self):
- def get_connection():
- return fakelibvirt.Connection("qemu:///session",
- False)
- d = vif.LibvirtHybridOVSBridgeDriver(get_connection)
- xml = self._get_instance_xml(d,
- self.net_ovs,
- self.mapping_ovs)
+ def _check_quantum_hybrid_driver(self, d, net, mapping, br_want):
+ self.flags(firewall_driver="nova.virt.firewall.IptablesFirewallDriver")
+ xml = self._get_instance_xml(d, net, mapping)
doc = etree.fromstring(xml)
ret = doc.findall('./devices/interface')
@@ -433,6 +430,30 @@ class LibvirtVifTestCase(test.TestCase):
node = ret[0]
self.assertEqual(node.get("type"), "bridge")
br_name = node.find("source").get("bridge")
- self.assertEqual(br_name, self.net_ovs['bridge'])
+ self.assertEqual(br_name, br_want)
mac = node.find("mac").get("address")
- self.assertEqual(mac, self.mapping_ovs['mac'])
+ self.assertEqual(mac, mapping['mac'])
+
+ def test_quantum_hybrid_driver(self):
+ def get_connection():
+ return fakelibvirt.Connection("qemu:///session",
+ False)
+ br_want = "qbr" + self.mapping_ovs['vif_uuid']
+ br_want = br_want[:network_model.NIC_NAME_LEN]
+ d = vif.LibvirtHybridOVSBridgeDriver(get_connection)
+ self._check_quantum_hybrid_driver(d,
+ self.net_ovs,
+ self.mapping_ovs_legacy,
+ br_want)
+
+ def test_generic_hybrid_driver(self):
+ def get_connection():
+ return fakelibvirt.Connection("qemu:///session",
+ False)
+ d = vif.LibvirtGenericVIFDriver(get_connection)
+ br_want = "qbr" + self.mapping_ovs['vif_uuid']
+ br_want = br_want[:network_model.NIC_NAME_LEN]
+ self._check_quantum_hybrid_driver(d,
+ self.net_ovs,
+ self.mapping_ovs,
+ br_want)
diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py
index 1110d356e..4a56e3fb6 100644
--- a/nova/virt/libvirt/vif.py
+++ b/nova/virt/libvirt/vif.py
@@ -19,6 +19,8 @@
"""VIF drivers for libvirt."""
+import copy
+
from nova import exception
from nova.network import linux_net
from nova.network import model as network_model
@@ -105,6 +107,21 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
def get_ovs_interfaceid(self, mapping):
return mapping['ovs_interfaceid']
+ def get_br_name(self, iface_id):
+ return ("qbr" + iface_id)[:network_model.NIC_NAME_LEN]
+
+ def get_veth_pair_names(self, iface_id):
+ return (("qvb%s" % iface_id)[:network_model.NIC_NAME_LEN],
+ ("qvo%s" % iface_id)[:network_model.NIC_NAME_LEN])
+
+ def get_firewall_required(self):
+ # TODO(berrange): Extend this to use information from VIF model
+ # which can indicate whether the network provider (eg Quantum)
+ # has already applied firewall filtering itself.
+ if CONF.firewall_driver != "nova.virt.firewall.NoopFirewallDriver":
+ return True
+ return False
+
def get_config_bridge(self, instance, network, mapping):
"""Get VIF configurations for bridge type."""
conf = super(LibvirtGenericVIFDriver,
@@ -130,9 +147,10 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
if CONF.use_ipv6:
ipv6_cidr = network['cidr_v6']
- designer.set_vif_host_backend_filter_config(
- conf, name, primary_addr, dhcp_server,
- ra_server, ipv4_cidr, ipv6_cidr)
+ if self.get_firewall_required():
+ designer.set_vif_host_backend_filter_config(
+ conf, name, primary_addr, dhcp_server,
+ ra_server, ipv4_cidr, ipv6_cidr)
return conf
@@ -160,8 +178,18 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
return conf
+ def get_config_ovs_hybrid(self, instance, network, mapping):
+ newnet = copy.deepcopy(network)
+ newnet['bridge'] = self.get_br_name(mapping['vif_uuid'])
+ return self.get_config_bridge(instance,
+ newnet,
+ mapping)
+
def get_config_ovs(self, instance, network, mapping):
- if self.has_libvirt_version(LIBVIRT_OVS_VPORT_VERSION):
+ if self.get_firewall_required():
+ return self.get_config_ovs_hybrid(instance, network,
+ mapping)
+ elif self.has_libvirt_version(LIBVIRT_OVS_VPORT_VERSION):
return self.get_config_ovs_bridge(instance, network,
mapping)
else:
@@ -231,8 +259,37 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
super(LibvirtGenericVIFDriver,
self).plug(instance, vif)
+ def plug_ovs_hybrid(self, instance, vif):
+ """Plug using hybrid strategy
+
+ Create a per-VIF linux bridge, then link that bridge to the OVS
+ integration bridge via a veth device, setting up the other end
+ of the veth device just like a normal OVS port. Then boot the
+ VIF on the linux bridge using standard libvirt mechanisms.
+ """
+ super(LibvirtGenericVIFDriver,
+ self).plug(instance, vif)
+
+ network, mapping = vif
+ iface_id = self.get_ovs_interfaceid(mapping)
+ br_name = self.get_br_name(mapping['vif_uuid'])
+ v1_name, v2_name = self.get_veth_pair_names(mapping['vif_uuid'])
+
+ if not linux_net.device_exists(br_name):
+ utils.execute('brctl', 'addbr', br_name, run_as_root=True)
+
+ if not linux_net.device_exists(v2_name):
+ linux_net._create_veth_pair(v1_name, v2_name)
+ utils.execute('ip', 'link', 'set', br_name, 'up', run_as_root=True)
+ utils.execute('brctl', 'addif', br_name, v1_name, run_as_root=True)
+ linux_net.create_ovs_vif_port(self.get_bridge_name(network),
+ v2_name, iface_id, mapping['mac'],
+ instance['uuid'])
+
def plug_ovs(self, instance, vif):
- if self.has_libvirt_version(LIBVIRT_OVS_VPORT_VERSION):
+ if self.get_firewall_required():
+ self.plug_ovs_hybrid(instance, vif)
+ elif self.has_libvirt_version(LIBVIRT_OVS_VPORT_VERSION):
self.plug_ovs_bridge(instance, vif)
else:
self.plug_ovs_ethernet(instance, vif)
@@ -280,8 +337,34 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
super(LibvirtGenericVIFDriver,
self).unplug(instance, vif)
+ def unplug_ovs_hybrid(self, instance, vif):
+ """UnPlug using hybrid strategy
+
+ Unhook port from OVS, unhook port from bridge, delete
+ bridge, and delete both veth devices.
+ """
+ super(LibvirtGenericVIFDriver,
+ self).unplug(instance, vif)
+
+ try:
+ network, mapping = vif
+ br_name = self.get_br_name(mapping['vif_uuid'])
+ v1_name, v2_name = self.get_veth_pair_names(mapping['vif_uuid'])
+
+ utils.execute('brctl', 'delif', br_name, v1_name, run_as_root=True)
+ utils.execute('ip', 'link', 'set', br_name, 'down',
+ run_as_root=True)
+ utils.execute('brctl', 'delbr', br_name, run_as_root=True)
+
+ linux_net.delete_ovs_vif_port(self.get_bridge_name(network),
+ v2_name)
+ except exception.ProcessExecutionError:
+ LOG.exception(_("Failed while unplugging vif"), instance=instance)
+
def unplug_ovs(self, instance, vif):
- if self.has_libvirt_version(LIBVIRT_OVS_VPORT_VERSION):
+ if self.get_firewall_required():
+ self.unplug_ovs_hybrid(instance, vif)
+ elif self.has_libvirt_version(LIBVIRT_OVS_VPORT_VERSION):
self.unplug_ovs_bridge(instance, vif)
else:
self.unplug_ovs_ethernet(instance, vif)
@@ -344,21 +427,10 @@ class LibvirtOpenVswitchDriver(LibvirtGenericVIFDriver):
self.unplug_ovs_ethernet(instance, vif)
-class LibvirtHybridOVSBridgeDriver(LibvirtBridgeDriver):
- """VIF driver that uses OVS + Linux Bridge for iptables compatibility.
-
- Enables the use of OVS-based Quantum plugins while at the same
- time using iptables-based filtering, which requires that vifs be
- plugged into a linux bridge, not OVS. IPtables filtering is useful for
- in particular for Nova security groups.
- """
-
- def get_br_name(self, iface_id):
- return ("qbr" + iface_id)[:network_model.NIC_NAME_LEN]
-
- def get_veth_pair_names(self, iface_id):
- return (("qvb%s" % iface_id)[:network_model.NIC_NAME_LEN],
- ("qvo%s" % iface_id)[:network_model.NIC_NAME_LEN])
+class LibvirtHybridOVSBridgeDriver(LibvirtGenericVIFDriver):
+ """Retained in Grizzly for compatibility with Quantum
+ drivers which do not yet report 'vif_type' port binding.
+ Will be deprecated in Havana, and removed in Ixxxx."""
def get_bridge_name(self, network):
return network.get('bridge') or CONF.libvirt_ovs_bridge
@@ -367,58 +439,13 @@ class LibvirtHybridOVSBridgeDriver(LibvirtBridgeDriver):
return mapping.get('ovs_interfaceid') or mapping['vif_uuid']
def get_config(self, instance, network, mapping):
- br_name = self.get_br_name(mapping['vif_uuid'])
- network['bridge'] = br_name
- return super(LibvirtHybridOVSBridgeDriver,
- self).get_config(instance,
- network,
- mapping)
+ return self.get_config_ovs_hybrid(instance, network, mapping)
def plug(self, instance, vif):
- """Plug using hybrid strategy
-
- Create a per-VIF linux bridge, then link that bridge to the OVS
- integration bridge via a veth device, setting up the other end
- of the veth device just like a normal OVS port. Then boot the
- VIF on the linux bridge using standard libvirt mechanisms
- """
-
- network, mapping = vif
- iface_id = self.get_ovs_interfaceid(mapping)
- br_name = self.get_br_name(mapping['vif_uuid'])
- v1_name, v2_name = self.get_veth_pair_names(mapping['vif_uuid'])
-
- if not linux_net.device_exists(br_name):
- utils.execute('brctl', 'addbr', br_name, run_as_root=True)
-
- if not linux_net.device_exists(v2_name):
- linux_net._create_veth_pair(v1_name, v2_name)
- utils.execute('ip', 'link', 'set', br_name, 'up', run_as_root=True)
- utils.execute('brctl', 'addif', br_name, v1_name, run_as_root=True)
- linux_net.create_ovs_vif_port(self.get_bridge_name(network),
- v2_name, iface_id, mapping['mac'],
- instance['uuid'])
+ return self.plug_ovs_hybrid(instance, vif)
def unplug(self, instance, vif):
- """UnPlug using hybrid strategy
-
- Unhook port from OVS, unhook port from bridge, delete
- bridge, and delete both veth devices.
- """
- try:
- network, mapping = vif
- br_name = self.get_br_name(mapping['vif_uuid'])
- v1_name, v2_name = self.get_veth_pair_names(mapping['vif_uuid'])
-
- utils.execute('brctl', 'delif', br_name, v1_name, run_as_root=True)
- utils.execute('ip', 'link', 'set', br_name, 'down',
- run_as_root=True)
- utils.execute('brctl', 'delbr', br_name, run_as_root=True)
-
- linux_net.delete_ovs_vif_port(self.get_bridge_name(network),
- v2_name)
- except exception.ProcessExecutionError:
- LOG.exception(_("Failed while unplugging vif"), instance=instance)
+ return self.unplug_ovs_hybrid(instance, vif)
class LibvirtOpenVswitchVirtualPortDriver(LibvirtGenericVIFDriver):