Merge "libvirt: convert over to use os-vif for Linux Bridge & OVS"

This commit is contained in:
Jenkins 2016-08-11 03:45:43 +00:00 committed by Gerrit Code Review
commit d93913fe7f
6 changed files with 385 additions and 219 deletions

View File

@ -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',

View File

@ -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)

View File

@ -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("""
<interface type="bridge">
<mac address="22:52:25:62:e2:aa"/>
<model type="virtio"/>
<source bridge="br100"/>
<target dev="nicdc065497-3c"/>
<filterref
filter="nova-instance-instance-00000001-22522562e2aa"/>
</interface>""", 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("""
<interface type="bridge">
<mac address="22:52:25:62:e2:aa"/>
<model type="virtio"/>
<source bridge="br100"/>
<target dev="nicdc065497-3c"/>
</interface>""", 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("""
<interface type="bridge">
<mac address="22:52:25:62:e2:aa"/>
<model type="virtio"/>
<source bridge="br0"/>
<target dev="nicdc065497-3c"/>
<virtualport type="openvswitch">
<parameters
interfaceid="07bd6cea-fb37-4594-b769-90fc51854ee9"/>
</virtualport>
</interface>""", 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("""
<interface type="bridge">
<mac address="22:52:25:62:e2:aa"/>
<model type="virtio"/>
<source bridge="br0"/>
<target dev="nicdc065497-3c"/>
<filterref
filter="nova-instance-instance-00000001-22522562e2aa"/>
</interface>""", cfg.to_xml())

View File

@ -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):

View File

@ -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:

View File

@ -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.