diff --git a/nova/tests/unit/virt/libvirt/test_designer.py b/nova/tests/unit/virt/libvirt/test_designer.py
index 0b222fb28812..b5cb9946014d 100644
--- a/nova/tests/unit/virt/libvirt/test_designer.py
+++ b/nova/tests/unit/virt/libvirt/test_designer.py
@@ -60,15 +60,6 @@ class DesignerTestCase(test.NoDBTestCase):
self.assertEqual('fake-tap', conf.target_dev)
self.assertEqual('', conf.script)
- def test_set_vif_host_backend_ovs_config(self):
- conf = config.LibvirtConfigGuestInterface()
- designer.set_vif_host_backend_ovs_config(conf, 'fake-bridge',
- 'fake-interface', 'fake-tap')
- self.assertEqual('bridge', conf.net_type)
- self.assertEqual('fake-bridge', conf.source_dev)
- self.assertEqual('openvswitch', conf.vporttype)
- self.assertEqual('fake-tap', conf.target_dev)
-
def test_set_vif_host_backend_802qbg_config(self):
conf = config.LibvirtConfigGuestInterface()
designer.set_vif_host_backend_802qbg_config(conf, 'fake-devname',
diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py
index 0b143f45f4d0..2e8d61c072b7 100644
--- a/nova/tests/unit/virt/libvirt/test_driver.py
+++ b/nova/tests/unit/virt/libvirt/test_driver.py
@@ -6854,7 +6854,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
filterref = './devices/interface/filterref'
vif = network_info[0]
- nic_id = vif['address'].replace(':', '')
+ nic_id = vif['address'].lower().replace(':', '')
fw = firewall.NWFilterFirewall(drvr)
instance_filter_name = fw._instance_filter_name(instance_ref,
nic_id)
diff --git a/nova/tests/unit/virt/libvirt/test_vif.py b/nova/tests/unit/virt/libvirt/test_vif.py
index 7aa20fe3def5..5cd0439ec22d 100644
--- a/nova/tests/unit/virt/libvirt/test_vif.py
+++ b/nova/tests/unit/virt/libvirt/test_vif.py
@@ -17,6 +17,9 @@ import os
import fixtures
from lxml import etree
import mock
+import os_vif
+from os_vif import exception as osv_exception
+from os_vif import objects as osv_objects
from oslo_concurrency import processutils
from oslo_config import cfg
import six
@@ -27,6 +30,7 @@ from nova.network import model as network_model
from nova import objects
from nova.pci import utils as pci_utils
from nova import test
+from nova.tests.unit import matchers
from nova.tests.unit.virt import fakelibosinfo
from nova import utils
from nova.virt.libvirt import config as vconfig
@@ -384,6 +388,49 @@ class LibvirtVifTestCase(test.NoDBTestCase):
'quota:vif_outbound_burst': '30'
}
+ os_vif_network = osv_objects.network.Network(
+ id="b82c1929-051e-481d-8110-4669916c7915",
+ label="Demo Net",
+ subnets=osv_objects.subnet.SubnetList(
+ objects=[]))
+
+ os_vif_bridge = osv_objects.vif.VIFBridge(
+ id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
+ address="22:52:25:62:e2:aa",
+ plugin="linux_bridge",
+ vif_name="nicdc065497-3c",
+ bridge_name="br100",
+ has_traffic_filtering=False,
+ network=os_vif_network)
+
+ os_vif_ovs_prof = osv_objects.vif.VIFPortProfileOpenVSwitch(
+ interface_id="07bd6cea-fb37-4594-b769-90fc51854ee9",
+ profile_id="fishfood")
+
+ os_vif_ovs = osv_objects.vif.VIFOpenVSwitch(
+ id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
+ address="22:52:25:62:e2:aa",
+ unplugin="linux_bridge",
+ vif_name="nicdc065497-3c",
+ bridge_name="br0",
+ port_profile=os_vif_ovs_prof,
+ network=os_vif_network)
+
+ os_vif_ovs_hybrid = osv_objects.vif.VIFBridge(
+ id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
+ address="22:52:25:62:e2:aa",
+ unplugin="linux_bridge",
+ vif_name="nicdc065497-3c",
+ bridge_name="br0",
+ port_profile=os_vif_ovs_prof,
+ has_traffic_filtering=False,
+ network=os_vif_network)
+
+ os_vif_inst_info = osv_objects.instance_info.InstanceInfo(
+ uuid="d5b1090c-9e00-4fa4-9504-4b1494857970",
+ name="instance-000004da",
+ project_id="2f37d7f6-e51a-4a1f-8b6e-b0917ffc8390")
+
def setUp(self):
super(LibvirtVifTestCase, self).setUp()
self.flags(allow_same_net_traffic=True)
@@ -455,6 +502,9 @@ class LibvirtVifTestCase(test.NoDBTestCase):
pci_slot_want = vif['profile']['pci_slot']
self.assertEqual(pci_slot, pci_slot_want)
+ def _assertXmlEqual(self, expectedXmlstr, actualXmlstr):
+ self.assertThat(actualXmlstr, matchers.XMLMatches(expectedXmlstr))
+
def _get_conf(self):
conf = vconfig.LibvirtConfigGuest()
conf.virt_type = "qemu"
@@ -616,7 +666,7 @@ class LibvirtVifTestCase(test.NoDBTestCase):
d = vif.LibvirtGenericVIFDriver()
image_meta = {'properties': {'os_name': 'fedora22'}}
image_meta = objects.ImageMeta.from_dict(image_meta)
- d.get_base_config(None, self.vif_bridge, image_meta,
+ d.get_base_config(None, 'ca:fe:de:ad:be:ef', image_meta,
None, 'kvm')
mock_set.assert_called_once_with(mock.ANY, 'ca:fe:de:ad:be:ef',
'virtio', None, None)
@@ -719,85 +769,6 @@ class LibvirtVifTestCase(test.NoDBTestCase):
delete.side_effect = processutils.ProcessExecutionError
d.unplug(self.instance, self.vif_ivs)
- def _test_plug_ovs_hybrid(self, ipv6_exists):
- calls = {
- 'device_exists': [mock.call('qbrvif-xxx-yyy'),
- mock.call('qvovif-xxx-yyy')],
- '_create_veth_pair': [mock.call('qvbvif-xxx-yyy',
- 'qvovif-xxx-yyy', 1000)],
- 'execute': [mock.call('brctl', 'addbr', 'qbrvif-xxx-yyy',
- run_as_root=True),
- mock.call('brctl', 'setfd', 'qbrvif-xxx-yyy', 0,
- run_as_root=True),
- mock.call('brctl', 'stp', 'qbrvif-xxx-yyy', 'off',
- run_as_root=True),
- mock.call('tee', ('/sys/class/net/qbrvif-xxx-yyy'
- '/bridge/multicast_snooping'),
- process_input='0', run_as_root=True,
- check_exit_code=[0, 1])],
- 'create_ovs_vif_port': [mock.call(
- 'br0', 'qvovif-xxx-yyy', 'aaa-bbb-ccc',
- 'ca:fe:de:ad:be:ef',
- 'f0000000-0000-0000-0000-000000000001',
- 1000)]
- }
- # The disable_ipv6 call needs to be added in the middle, if required
- if ipv6_exists:
- calls['execute'].extend([
- mock.call('tee', ('/proc/sys/net/ipv6/conf'
- '/qbrvif-xxx-yyy/disable_ipv6'),
- process_input='1', run_as_root=True,
- check_exit_code=[0, 1])])
- calls['execute'].extend([
- mock.call('ip', 'link', 'set', 'qbrvif-xxx-yyy', 'up',
- run_as_root=True),
- mock.call('brctl', 'addif', 'qbrvif-xxx-yyy',
- 'qvbvif-xxx-yyy', run_as_root=True)])
- with test.nested(
- mock.patch.object(linux_net, 'device_exists',
- return_value=False),
- mock.patch.object(utils, 'execute'),
- mock.patch.object(linux_net, '_create_veth_pair'),
- mock.patch.object(linux_net, 'create_ovs_vif_port'),
- mock.patch.object(os.path, 'exists', return_value=ipv6_exists)
- ) as (device_exists, execute, _create_veth_pair, create_ovs_vif_port,
- path_exists):
- d = vif.LibvirtGenericVIFDriver()
- d.plug(self.instance, self.vif_ovs)
- device_exists.assert_has_calls(calls['device_exists'])
- _create_veth_pair.assert_has_calls(calls['_create_veth_pair'])
- execute.assert_has_calls(calls['execute'])
- create_ovs_vif_port.assert_has_calls(calls['create_ovs_vif_port'])
-
- def test_plug_ovs_hybrid_ipv6(self):
- self._test_plug_ovs_hybrid(ipv6_exists=True)
-
- def test_plug_ovs_hybrid_no_ipv6(self):
- self._test_plug_ovs_hybrid(ipv6_exists=False)
-
- def test_unplug_ovs_hybrid(self):
- calls = {
- 'device_exists': [mock.call('qbrvif-xxx-yyy')],
- 'execute': [mock.call('brctl', 'delif', 'qbrvif-xxx-yyy',
- 'qvbvif-xxx-yyy', run_as_root=True),
- mock.call('ip', 'link', 'set',
- 'qbrvif-xxx-yyy', 'down', run_as_root=True),
- mock.call('brctl', 'delbr',
- 'qbrvif-xxx-yyy', run_as_root=True)],
- 'delete_ovs_vif_port': [mock.call('br0', 'qvovif-xxx-yyy')]
- }
- with test.nested(
- mock.patch.object(linux_net, 'device_exists',
- return_value=True),
- mock.patch.object(utils, 'execute'),
- mock.patch.object(linux_net, 'delete_ovs_vif_port')
- ) as (device_exists, execute, delete_ovs_vif_port):
- d = vif.LibvirtGenericVIFDriver()
- d.unplug(self.instance, self.vif_ovs)
- device_exists.assert_has_calls(calls['device_exists'])
- execute.assert_has_calls(calls['execute'])
- delete_ovs_vif_port.assert_has_calls(calls['delete_ovs_vif_port'])
-
@mock.patch.object(utils, 'execute')
@mock.patch.object(pci_utils, 'get_ifname_by_pci_address')
@mock.patch.object(pci_utils, 'get_vf_num_by_pci_address', return_value=1)
@@ -839,21 +810,6 @@ class LibvirtVifTestCase(test.NoDBTestCase):
d = vif.LibvirtGenericVIFDriver()
self._test_hw_veb_op(d.unplug, 0)
- def test_unplug_ovs_hybrid_bridge_does_not_exist(self):
- calls = {
- 'device_exists': [mock.call('qbrvif-xxx-yyy')],
- 'delete_ovs_vif_port': [mock.call('br0', 'qvovif-xxx-yyy')]
- }
- with test.nested(
- mock.patch.object(linux_net, 'device_exists',
- return_value=False),
- mock.patch.object(linux_net, 'delete_ovs_vif_port')
- ) as (device_exists, delete_ovs_vif_port):
- d = vif.LibvirtGenericVIFDriver()
- d.unplug(self.instance, self.vif_ovs)
- device_exists.assert_has_calls(calls['device_exists'])
- delete_ovs_vif_port.assert_has_calls(calls['delete_ovs_vif_port'])
-
def test_plug_ivs_hybrid(self):
calls = {
'device_exists': [mock.call('qbrvif-xxx-yyy'),
@@ -1482,3 +1438,163 @@ class LibvirtVifTestCase(test.NoDBTestCase):
execute.assert_has_calls(calls['execute'])
delete_ovs_vif_port.assert_has_calls(calls['delete_ovs_vif_port'])
delete_fp_dev.assert_has_calls(calls['delete_fp_dev'])
+
+ @mock.patch("nova.network.os_vif_util.nova_to_osvif_instance")
+ @mock.patch("nova.network.os_vif_util.nova_to_osvif_vif")
+ @mock.patch.object(os_vif, "plug")
+ def _test_osvif_plug(self, fail, mock_plug,
+ mock_convert_vif, mock_convert_inst):
+ mock_convert_vif.return_value = self.os_vif_bridge
+ mock_convert_inst.return_value = self.os_vif_inst_info
+
+ d = vif.LibvirtGenericVIFDriver()
+ if fail:
+ mock_plug.side_effect = osv_exception.ExceptionBase("Wibble")
+ self.assertRaises(exception.NovaException,
+ d.plug,
+ self.instance, self.vif_bridge)
+ else:
+ d.plug(self.instance, self.vif_bridge)
+
+ mock_plug.assert_called_once_with(self.os_vif_bridge,
+ self.os_vif_inst_info)
+
+ def test_osvif_plug_normal(self):
+ self._test_osvif_plug(False)
+
+ def test_osvif_plug_fail(self):
+ self._test_osvif_plug(True)
+
+ @mock.patch("nova.network.os_vif_util.nova_to_osvif_instance")
+ @mock.patch("nova.network.os_vif_util.nova_to_osvif_vif")
+ @mock.patch.object(os_vif, "unplug")
+ def _test_osvif_unplug(self, fail, mock_unplug,
+ mock_convert_vif, mock_convert_inst):
+ mock_convert_vif.return_value = self.os_vif_bridge
+ mock_convert_inst.return_value = self.os_vif_inst_info
+
+ d = vif.LibvirtGenericVIFDriver()
+ if fail:
+ mock_unplug.side_effect = osv_exception.ExceptionBase("Wibble")
+ self.assertRaises(exception.NovaException,
+ d.unplug,
+ self.instance, self.vif_bridge)
+ else:
+ d.unplug(self.instance, self.vif_bridge)
+
+ mock_unplug.assert_called_once_with(self.os_vif_bridge,
+ self.os_vif_inst_info)
+
+ def test_osvif_unplug_normal(self):
+ self._test_osvif_unplug(False)
+
+ def test_osvif_unplug_fail(self):
+ self._test_osvif_unplug(True)
+
+ @mock.patch("nova.network.os_vif_util.nova_to_osvif_instance")
+ @mock.patch("nova.network.os_vif_util.nova_to_osvif_vif")
+ def test_config_os_vif_bridge(self, mock_convert_vif, mock_convert_inst):
+ mock_convert_vif.return_value = self.os_vif_bridge
+ mock_convert_inst.return_value = self.os_vif_inst_info
+
+ d = vif.LibvirtGenericVIFDriver()
+ hostimpl = host.Host("qemu:///system")
+ flavor = objects.Flavor(name='m1.small')
+ image_meta = objects.ImageMeta.from_dict({})
+ d = vif.LibvirtGenericVIFDriver()
+ cfg = d.get_config(self.instance, self.vif_bridge,
+ image_meta, flavor,
+ CONF.libvirt.virt_type,
+ hostimpl)
+
+ self._assertXmlEqual("""
+
+
+
+
+
+
+ """, cfg.to_xml())
+
+ @mock.patch("nova.network.os_vif_util.nova_to_osvif_instance")
+ @mock.patch("nova.network.os_vif_util.nova_to_osvif_vif")
+ def test_config_os_vif_bridge_nofw(self, mock_convert_vif,
+ mock_convert_inst):
+ self.flags(firewall_driver="nova.virt.firewall.NoopFirewallDriver")
+
+ mock_convert_vif.return_value = self.os_vif_bridge
+ mock_convert_inst.return_value = self.os_vif_inst_info
+
+ d = vif.LibvirtGenericVIFDriver()
+ hostimpl = host.Host("qemu:///system")
+ flavor = objects.Flavor(name='m1.small')
+ image_meta = objects.ImageMeta.from_dict({})
+ d = vif.LibvirtGenericVIFDriver()
+ cfg = d.get_config(self.instance, self.vif_bridge,
+ image_meta, flavor,
+ CONF.libvirt.virt_type,
+ hostimpl)
+
+ self._assertXmlEqual("""
+
+
+
+
+
+ """, cfg.to_xml())
+
+ @mock.patch("nova.network.os_vif_util.nova_to_osvif_instance")
+ @mock.patch("nova.network.os_vif_util.nova_to_osvif_vif")
+ def test_config_os_vif_ovs(self, mock_convert_vif, mock_convert_inst):
+ mock_convert_vif.return_value = self.os_vif_ovs
+ mock_convert_inst.return_value = self.os_vif_inst_info
+
+ d = vif.LibvirtGenericVIFDriver()
+ hostimpl = host.Host("qemu:///system")
+ flavor = objects.Flavor(name='m1.small')
+ image_meta = objects.ImageMeta.from_dict({})
+ d = vif.LibvirtGenericVIFDriver()
+ cfg = d.get_config(self.instance, self.vif_ovs,
+ image_meta, flavor,
+ CONF.libvirt.virt_type,
+ hostimpl)
+
+ self._assertXmlEqual("""
+
+
+
+
+
+
+
+
+ """, cfg.to_xml())
+
+ @mock.patch("nova.network.os_vif_util.nova_to_osvif_instance")
+ @mock.patch("nova.network.os_vif_util.nova_to_osvif_vif")
+ def test_config_os_vif_ovs_hybrid(self, mock_convert_vif,
+ mock_convert_inst):
+ mock_convert_vif.return_value = self.os_vif_ovs_hybrid
+ mock_convert_inst.return_value = self.os_vif_inst_info
+
+ d = vif.LibvirtGenericVIFDriver()
+ hostimpl = host.Host("qemu:///system")
+ flavor = objects.Flavor(name='m1.small')
+ image_meta = objects.ImageMeta.from_dict({})
+ d = vif.LibvirtGenericVIFDriver()
+ cfg = d.get_config(self.instance, self.vif_ovs,
+ image_meta, flavor,
+ CONF.libvirt.virt_type,
+ hostimpl)
+
+ self._assertXmlEqual("""
+
+
+
+
+
+
+ """, cfg.to_xml())
diff --git a/nova/virt/libvirt/designer.py b/nova/virt/libvirt/designer.py
index 2522efee4328..df22f02fd616 100644
--- a/nova/virt/libvirt/designer.py
+++ b/nova/virt/libvirt/designer.py
@@ -61,19 +61,6 @@ def set_vif_host_backend_ethernet_config(conf, tapname):
conf.script = ""
-def set_vif_host_backend_ovs_config(conf, brname, interfaceid, tapname=None):
- """Populate a LibvirtConfigGuestInterface instance
- with host backend details for an OpenVSwitch bridge.
- """
-
- conf.net_type = "bridge"
- conf.source_dev = brname
- conf.vporttype = "openvswitch"
- conf.add_vport_param("interfaceid", interfaceid)
- if tapname:
- conf.target_dev = tapname
-
-
def set_vif_host_backend_802qbg_config(conf, devname, managerid,
typeid, typeidversion,
instanceid, tapname=None):
diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py
index 2b1be374b5e5..b9e46a501102 100644
--- a/nova/virt/libvirt/vif.py
+++ b/nova/virt/libvirt/vif.py
@@ -2,6 +2,7 @@
# Copyright (C) 2011 Nicira, Inc
# Copyright 2011 OpenStack Foundation
# All Rights Reserved.
+# Copyright 2016 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
@@ -20,6 +21,8 @@
import copy
import os
+import os_vif
+from os_vif import exception as osv_exception
from oslo_concurrency import processutils
from oslo_log import log as logging
@@ -29,6 +32,7 @@ from nova.i18n import _
from nova.i18n import _LE
from nova.network import linux_net
from nova.network import model as network_model
+from nova.network import os_vif_util
from nova import objects
from nova import utils
from nova.virt.libvirt import config as vconfig
@@ -90,7 +94,7 @@ class LibvirtGenericVIFDriver(object):
devname = self.get_vif_devname(vif)
return prefix + devname[3:]
- def get_base_config(self, instance, vif, image_meta,
+ def get_base_config(self, instance, mac, image_meta,
inst_type, virt_type):
conf = vconfig.LibvirtConfigGuestInterface()
# Default to letting libvirt / the hypervisor choose the model
@@ -127,7 +131,7 @@ class LibvirtGenericVIFDriver(object):
driver = vhost_drv or driver
designer.set_vif_guest_frontend_config(
- conf, vif['address'], model, driver, vhost_queues)
+ conf, mac, model, driver, vhost_queues)
return conf
@@ -186,17 +190,28 @@ class LibvirtGenericVIFDriver(object):
return (("qvb%s" % iface_id)[:network_model.NIC_NAME_LEN],
("qvo%s" % iface_id)[:network_model.NIC_NAME_LEN])
+ @staticmethod
+ def is_no_op_firewall():
+ return CONF.firewall_driver == "nova.virt.firewall.NoopFirewallDriver"
+
def get_firewall_required(self, vif):
if vif.is_neutron_filtering_enabled():
return False
- if CONF.firewall_driver != "nova.virt.firewall.NoopFirewallDriver":
- return True
- return False
+ if self.is_no_op_firewall():
+ return False
+ return True
+
+ def get_firewall_required_os_vif(self, vif):
+ if vif.has_traffic_filtering:
+ return False
+ if self.is_no_op_firewall():
+ return False
+ return True
def get_config_bridge(self, instance, vif, image_meta,
inst_type, virt_type, host):
"""Get VIF configurations for bridge type."""
- conf = self.get_base_config(instance, vif, image_meta,
+ conf = self.get_base_config(instance, vif['address'], image_meta,
inst_type, virt_type)
designer.set_vif_host_backend_bridge_config(
@@ -211,42 +226,6 @@ class LibvirtGenericVIFDriver(object):
return conf
- def get_config_ovs_bridge(self, instance, vif, image_meta,
- inst_type, virt_type, host):
- conf = self.get_base_config(instance, vif, image_meta,
- inst_type, virt_type)
-
- designer.set_vif_host_backend_ovs_config(
- conf, self.get_bridge_name(vif),
- self.get_ovs_interfaceid(vif),
- self.get_vif_devname(vif))
-
- designer.set_vif_bandwidth_config(conf, inst_type)
-
- return conf
-
- def get_config_ovs_hybrid(self, instance, vif, image_meta,
- inst_type, virt_type, host):
- newvif = copy.deepcopy(vif)
- newvif['network']['bridge'] = self.get_br_name(vif['id'])
- return self.get_config_bridge(instance, newvif, image_meta,
- inst_type, virt_type, host)
-
- def get_config_ovs(self, instance, vif, image_meta,
- inst_type, virt_type, host):
- if self.get_firewall_required(vif) or vif.is_hybrid_plug_enabled():
- return self.get_config_ovs_hybrid(instance, vif,
- image_meta,
- inst_type,
- virt_type,
- host)
- else:
- return self.get_config_ovs_bridge(instance, vif,
- image_meta,
- inst_type,
- virt_type,
- host)
-
def get_config_ivs_hybrid(self, instance, vif, image_meta,
inst_type, virt_type, host):
newvif = copy.deepcopy(vif)
@@ -261,7 +240,7 @@ class LibvirtGenericVIFDriver(object):
def get_config_ivs_ethernet(self, instance, vif, image_meta,
inst_type, virt_type, host):
conf = self.get_base_config(instance,
- vif,
+ vif['address'],
image_meta,
inst_type,
virt_type)
@@ -288,7 +267,7 @@ class LibvirtGenericVIFDriver(object):
def get_config_802qbg(self, instance, vif, image_meta,
inst_type, virt_type, host):
- conf = self.get_base_config(instance, vif, image_meta,
+ conf = self.get_base_config(instance, vif['address'], image_meta,
inst_type, virt_type)
params = vif["qbg_params"]
@@ -305,7 +284,7 @@ class LibvirtGenericVIFDriver(object):
def get_config_802qbh(self, instance, vif, image_meta,
inst_type, virt_type, host):
- conf = self.get_base_config(instance, vif, image_meta,
+ conf = self.get_base_config(instance, vif['address'], image_meta,
inst_type, virt_type)
profile = vif["profile"]
@@ -324,7 +303,7 @@ class LibvirtGenericVIFDriver(object):
def get_config_hw_veb(self, instance, vif, image_meta,
inst_type, virt_type, host):
- conf = self.get_base_config(instance, vif, image_meta,
+ conf = self.get_base_config(instance, vif['address'], image_meta,
inst_type, virt_type)
profile = vif["profile"]
@@ -347,7 +326,7 @@ class LibvirtGenericVIFDriver(object):
def get_config_macvtap(self, instance, vif, image_meta,
inst_type, virt_type, host):
- conf = self.get_base_config(instance, vif, image_meta,
+ conf = self.get_base_config(instance, vif['address'], image_meta,
inst_type, virt_type)
vif_details = vif['details']
@@ -378,7 +357,7 @@ class LibvirtGenericVIFDriver(object):
def get_config_iovisor(self, instance, vif, image_meta,
inst_type, virt_type, host):
- conf = self.get_base_config(instance, vif, image_meta,
+ conf = self.get_base_config(instance, vif['address'], image_meta,
inst_type, virt_type)
dev = self.get_vif_devname(vif)
@@ -390,7 +369,7 @@ class LibvirtGenericVIFDriver(object):
def get_config_midonet(self, instance, vif, image_meta,
inst_type, virt_type, host):
- conf = self.get_base_config(instance, vif, image_meta,
+ conf = self.get_base_config(instance, vif['address'], image_meta,
inst_type, virt_type)
dev = self.get_vif_devname(vif)
@@ -400,7 +379,7 @@ class LibvirtGenericVIFDriver(object):
def get_config_tap(self, instance, vif, image_meta,
inst_type, virt_type, host):
- conf = self.get_base_config(instance, vif, image_meta,
+ conf = self.get_base_config(instance, vif['address'], image_meta,
inst_type, virt_type)
dev = self.get_vif_devname(vif)
@@ -420,7 +399,7 @@ class LibvirtGenericVIFDriver(object):
def get_config_vhostuser(self, instance, vif, image_meta,
inst_type, virt_type, host):
- conf = self.get_base_config(instance, vif, image_meta,
+ conf = self.get_base_config(instance, vif['address'], image_meta,
inst_type, virt_type)
mode, sock_path = self._get_vhostuser_settings(vif)
designer.set_vif_host_backend_vhostuser_config(conf, mode, sock_path)
@@ -439,7 +418,7 @@ class LibvirtGenericVIFDriver(object):
def get_config_vrouter(self, instance, vif, image_meta,
inst_type, virt_type, host):
- conf = self.get_base_config(instance, vif, image_meta,
+ conf = self.get_base_config(instance, vif['address'], image_meta,
inst_type, virt_type)
dev = self.get_vif_devname(vif)
designer.set_vif_host_backend_ethernet_config(conf, dev)
@@ -447,6 +426,69 @@ class LibvirtGenericVIFDriver(object):
designer.set_vif_bandwidth_config(conf, inst_type)
return conf
+ def _set_config_VIFBridge(self, instance, vif, conf):
+ conf.net_type = "bridge"
+ conf.source_dev = vif.bridge_name
+ conf.target_dev = vif.vif_name
+
+ if self.get_firewall_required_os_vif(vif):
+ mac_id = vif.address.replace(':', '')
+ name = "nova-instance-" + instance.name + "-" + mac_id
+ conf.filtername = name
+
+ def _set_config_VIFOpenVSwitch(self, instance, vif, conf):
+ conf.net_type = "bridge"
+ conf.source_dev = vif.bridge_name
+ conf.target_dev = vif.vif_name
+ self._set_config_VIFPortProfile(instance, vif, conf)
+
+ def _set_config_VIFPortProfileOpenVSwitch(self, profile, conf):
+ conf.vporttype = "openvswitch"
+ conf.add_vport_param("interfaceid",
+ profile.interface_id)
+
+ def _set_config_VIFPortProfile(self, instance, vif, conf):
+ # Set any port profile that may be required
+ profilefunc = "_set_config_" + vif.port_profile.obj_name()
+ func = getattr(self, profilefunc, None)
+ if not func:
+ raise exception.NovaException(
+ "Unsupported VIF port profile type %(obj)s func %(func)s" %
+ {'obj': vif.port_profile.obj_name(), 'func': profilefunc})
+
+ func(vif.port_profile, conf)
+
+ def _get_config_os_vif(self, instance, vif, image_meta, inst_type,
+ virt_type, host):
+ """Get the domain config for a VIF
+
+ :param instance: nova.objects.Instance
+ :param vif: os_vif.objects.vif.VIFBase subclass
+ :param image_meta: nova.objects.ImageMeta
+ :param inst_type: nova.objects.Flavor
+ :param virt_type: virtualization type
+ :param host: nova.virt.libvirt.host.Host
+
+ :returns: nova.virt.libvirt.config.LibvirtConfigGuestInterface
+ """
+
+ # Do the config that's common to all vif types
+ conf = self.get_base_config(instance, vif.address, image_meta,
+ inst_type, virt_type)
+
+ # Do the VIF type specific config
+ viffunc = "_set_config_" + vif.obj_name()
+ func = getattr(self, viffunc, None)
+ if not func:
+ raise exception.NovaException(
+ "Unsupported VIF type %(obj)s func %(func)s" %
+ {'obj': vif.obj_name(), 'func': viffunc})
+ func(instance, vif, conf)
+
+ designer.set_vif_bandwidth_config(conf, inst_type)
+
+ return conf
+
def get_config(self, instance, vif, image_meta,
inst_type, virt_type, host):
vif_type = vif['type']
@@ -460,6 +502,14 @@ class LibvirtGenericVIFDriver(object):
raise exception.NovaException(
_("vif_type parameter must be present "
"for this vif_driver implementation"))
+
+ # Try os-vif codepath first
+ vif_obj = os_vif_util.nova_to_osvif_vif(vif)
+ if vif_obj is not None:
+ return self._get_config_os_vif(instance, vif_obj, image_meta,
+ inst_type, virt_type, host)
+
+ # Legacy non-os-vif codepath
vif_slug = self._normalize_vif_type(vif_type)
func = getattr(self, 'get_config_%s' % vif_slug, None)
if not func:
@@ -468,35 +518,6 @@ class LibvirtGenericVIFDriver(object):
return func(instance, vif, image_meta,
inst_type, virt_type, host)
- def plug_bridge(self, instance, vif):
- """Ensure that the bridge exists, and add VIF to it."""
- network = vif['network']
- if (not network.get_meta('multi_host', False) and
- network.get_meta('should_create_bridge', False)):
- if network.get_meta('should_create_vlan', False):
- iface = CONF.vlan_interface or \
- network.get_meta('bridge_interface')
- LOG.debug('Ensuring vlan %(vlan)s and bridge %(bridge)s',
- {'vlan': network.get_meta('vlan'),
- 'bridge': self.get_bridge_name(vif)},
- instance=instance)
- linux_net.LinuxBridgeInterfaceDriver.ensure_vlan_bridge(
- network.get_meta('vlan'),
- self.get_bridge_name(vif),
- iface)
- else:
- iface = CONF.flat_interface or \
- network.get_meta('bridge_interface')
- LOG.debug("Ensuring bridge %s",
- self.get_bridge_name(vif), instance=instance)
- linux_net.LinuxBridgeInterfaceDriver.ensure_bridge(
- self.get_bridge_name(vif),
- iface)
-
- def plug_ovs_bridge(self, instance, vif):
- """No manual plugging required."""
- pass
-
def _plug_bridge_with_port(self, instance, vif, port):
iface_id = self.get_ovs_interfaceid(vif)
br_name = self.get_br_name(vif['id'])
@@ -544,12 +565,6 @@ class LibvirtGenericVIFDriver(object):
"""
self._plug_bridge_with_port(instance, vif, port='ovs')
- def plug_ovs(self, instance, vif):
- if self.get_firewall_required(vif) or vif.is_hybrid_plug_enabled():
- self.plug_ovs_hybrid(instance, vif)
- else:
- self.plug_ovs_bridge(instance, vif)
-
def plug_ivs_ethernet(self, instance, vif):
iface_id = self.get_ovs_interfaceid(vif)
dev = self.get_vif_devname(vif)
@@ -757,6 +772,16 @@ class LibvirtGenericVIFDriver(object):
except processutils.ProcessExecutionError:
LOG.exception(_LE("Failed while plugging vif"), instance=instance)
+ def _plug_os_vif(self, instance, vif):
+ instance_info = os_vif_util.nova_to_osvif_instance(instance)
+
+ try:
+ os_vif.plug(vif, instance_info)
+ except osv_exception.ExceptionBase as ex:
+ msg = (_("Failure running os_vif plugin plug method: %(ex)s")
+ % {'ex': ex})
+ raise exception.NovaException(msg)
+
def plug(self, instance, vif):
vif_type = vif['type']
@@ -769,6 +794,14 @@ class LibvirtGenericVIFDriver(object):
raise exception.VirtualInterfacePlugException(
_("vif_type parameter must be present "
"for this vif_driver implementation"))
+
+ # Try os-vif codepath first
+ vif_obj = os_vif_util.nova_to_osvif_vif(vif)
+ if vif_obj is not None:
+ self._plug_os_vif(instance, vif_obj)
+ return
+
+ # Legacy non-os-vif codepath
vif_slug = self._normalize_vif_type(vif_type)
func = getattr(self, 'plug_%s' % vif_slug, None)
if not func:
@@ -777,14 +810,6 @@ class LibvirtGenericVIFDriver(object):
"vif_type=%s") % vif_type)
func(instance, vif)
- def unplug_bridge(self, instance, vif):
- """No manual unplugging required."""
- pass
-
- def unplug_ovs_bridge(self, instance, vif):
- """No manual unplugging required."""
- pass
-
def unplug_ovs_hybrid(self, instance, vif):
"""UnPlug using hybrid strategy
@@ -809,12 +834,6 @@ class LibvirtGenericVIFDriver(object):
LOG.exception(_LE("Failed while unplugging vif"),
instance=instance)
- def unplug_ovs(self, instance, vif):
- if self.get_firewall_required(vif) or vif.is_hybrid_plug_enabled():
- self.unplug_ovs_hybrid(instance, vif)
- else:
- self.unplug_ovs_bridge(instance, vif)
-
def unplug_ivs_ethernet(self, instance, vif):
"""Unplug the VIF by deleting the port from the bridge."""
try:
@@ -974,6 +993,16 @@ class LibvirtGenericVIFDriver(object):
LOG.exception(
_LE("Failed while unplugging vif"), instance=instance)
+ def _unplug_os_vif(self, instance, vif):
+ instance_info = os_vif_util.nova_to_osvif_instance(instance)
+
+ try:
+ os_vif.unplug(vif, instance_info)
+ except osv_exception.ExceptionBase as ex:
+ msg = (_("Failure running os_vif plugin unplug method: %(ex)s")
+ % {'ex': ex})
+ raise exception.NovaException(msg)
+
def unplug(self, instance, vif):
vif_type = vif['type']
@@ -986,6 +1015,14 @@ class LibvirtGenericVIFDriver(object):
raise exception.NovaException(
_("vif_type parameter must be present "
"for this vif_driver implementation"))
+
+ # Try os-vif codepath first
+ vif_obj = os_vif_util.nova_to_osvif_vif(vif)
+ if vif_obj is not None:
+ self._unplug_os_vif(instance, vif_obj)
+ return
+
+ # Legacy non-os-vif codepath
vif_slug = self._normalize_vif_type(vif_type)
func = getattr(self, 'unplug_%s' % vif_slug, None)
if not func:
diff --git a/releasenotes/notes/libvirt-uses-os-vif-plugins-31a0617de0c248b9.yaml b/releasenotes/notes/libvirt-uses-os-vif-plugins-31a0617de0c248b9.yaml
new file mode 100644
index 000000000000..768d34f39264
--- /dev/null
+++ b/releasenotes/notes/libvirt-uses-os-vif-plugins-31a0617de0c248b9.yaml
@@ -0,0 +1,35 @@
+---
+features:
+ - The Libvirt driver now uses os-vif plugins for
+ handling plug/unplug actions for the Linux Bridge
+ and OpenVSwitch VIF types. Each os-vif plugin will
+ have its own group in nova.conf for configuration
+ parameters it needs. These plugins will be installed
+ by default as part of the os-vif module installation
+ so no special action is required.
+upgrade:
+ - With the introduction of os-vif, some networking related
+ configuration options have moved, and users will need to update
+ their ``nova.conf``.
+
+ For OpenVSwitch users the following options have moved from
+ ``[DEFAULT]`` to ``[vif_plug_ovs]``
+
+ - network_device_mtu
+ - ovs_vsctl_timeout
+
+ For Linux Bridge users the following options have moved from
+ ``[DEFAULT]`` to ``[vif_plug_linux_bridge]``
+
+ - use_ipv6
+ - iptables_top_regex
+ - iptables_bottom_regex
+ - iptables_drop_action
+ - forward_bridge_interface
+ - vlan_interface
+ - flat_interface
+ - network_device_mtu
+
+ For backwards compatibility, and ease of upgrade, these options
+ will continue to work from ``[DEFAULT]`` during the Newton
+ release. However they will not in future releases.