network: introduce helper APIs for dealing with os-vif objects

This introduces a os_vif_utils module to nova/network which
contains logic for converting between the existing Nova
python objects in the nova.network.model namespace, and
the os-vif objects under os_vif.objects

The conversion is currently only wired up for the Linux
Bridge and OVS VIF types, which are directly supported
by os-vif. Conversion of other types will follow as &
when os-vif plugins are created for them.

This object model conversion is only expected to exist
for a short-term. The intention is that Neutron will
later be converted so that it sends across a serialized
os_vif.objects.vif.VIFBase object, instead of the port
binding dict. When this happens, Nova will be able to
directly deserialize the os-vif objects, skipping all
use of the nova.network.model objects.

As part of using os-vif, each registered plugin gets the
ability to read config parameters from nova.conf in a
private section named 'vif_plug_<plugin name>'. For
example the OpenVSwitch plugin will be in 'vif_plug_ovs'.

Plugins which make use of oslo.privsep for running some
privileged code will have a further private section in
nova.conf named 'vif_plug_<plugin namee>_privileged'
from which the privsep library will pull its configuration.
It is unlikely that operators will need to set any params
in this section, since the defaults should work optimally
for almost all scenarios.

Blueprint: os-vif-library
Change-Id: Id78858bc55ce4f3f0727cad644ef9c8f9f718556
This commit is contained in:
Daniel P. Berrange 2016-01-19 14:17:35 +00:00
parent b5822aa446
commit a8a0d89fdd
5 changed files with 949 additions and 2 deletions

375
nova/network/os_vif_util.py Normal file
View File

@ -0,0 +1,375 @@
# 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
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
'''
This module contains code for converting from the original
nova.network.model data structure, to the new os-vif based
versioned object model os_vif.objects.*
'''
import sys
import os_vif
from os_vif import objects
from oslo_config import cfg
from oslo_log import log as logging
from nova import exception
from nova.network import model
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
# Ensure os-vif objects are registered and plugins loaded
os_vif.initialize()
def _get_vif_name(vif):
"""Get a VIF device name
:param vif: the nova.nework.model.VIF instance
Get a string suitable for use as a host OS network
device name
:returns: a device name
"""
if vif.get('devname', None) is not None:
return vif['devname']
return ('nic' + vif['id'])[:model.NIC_NAME_LEN]
def _get_hybrid_bridge_name(vif):
"""Get a bridge device name
:param vif: the nova.nework.model.VIF instance
Get a string suitable for use as a host OS bridge
device name
:returns: a bridge name
"""
return ('qbr' + vif['id'])[:model.NIC_NAME_LEN]
def _is_firewall_required(vif):
"""Check if local firewall is required
:param vif: the nova.nework.model.VIF instance
:returns: True if local firewall is required
"""
if vif.is_neutron_filtering_enabled():
return False
if CONF.firewall_driver != "nova.virt.firewall.NoopFirewallDriver":
return True
return False
def nova_to_osvif_instance(instance):
"""Convert a Nova instance object to an os-vif instance object
:param vif: a nova.objects.Instance instance
:returns: a os_vif.objects.instance_info.InstanceInfo
"""
info = objects.instance_info.InstanceInfo(
uuid=instance.uuid,
name=instance.name)
if (instance.obj_attr_is_set("project_id") and
instance.project_id is not None):
info.project_id = instance.project_id
return info
def _nova_to_osvif_ip(ip):
"""Convert Nova IP object into os_vif object
:param route: nova.network.model.IP instance
:returns: os_vif.objects.fixed_ip.FixedIP instance
"""
floating_ips = [fip['address'] for fip in ip.get('floating_ips', [])]
return objects.fixed_ip.FixedIP(
address=ip['address'],
floating_ips=floating_ips)
def _nova_to_osvif_ips(ips):
"""Convert Nova IP list into os_vif object
:param routes: list of nova.network.model.IP instances
:returns: os_vif.objects.fixed_ip.FixedIPList instance
"""
return objects.fixed_ip.FixedIPList(
objects=[_nova_to_osvif_ip(ip) for ip in ips])
def _nova_to_osvif_route(route):
"""Convert Nova route object into os_vif object
:param route: nova.network.model.Route instance
:returns: os_vif.objects.route.Route instance
"""
obj = objects.route.Route(
cidr=route['cidr'],
interface=route['interface'])
if (route['gateway'] is not None and
route['gateway']['address'] is not None):
obj.gateway = route['gateway']['address']
return obj
def _nova_to_osvif_routes(routes):
"""Convert Nova route list into os_vif object
:param routes: list of nova.network.model.Route instances
:returns: os_vif.objects.route.RouteList instance
"""
return objects.route.RouteList(
objects=[_nova_to_osvif_route(route) for route in routes])
def _nova_to_osvif_subnet(subnet):
"""Convert Nova subnet object into os_vif object
:param subnet: nova.network.model.Subnet instance
:returns: os_vif.objects.subnet.Subnet instance
"""
dnsaddrs = [ip['address'] for ip in subnet['dns']]
obj = objects.subnet.Subnet(
dns=dnsaddrs,
ips=_nova_to_osvif_ips(subnet['ips']),
routes=_nova_to_osvif_routes(subnet['routes']))
if subnet['cidr'] is not None:
obj.cidr = subnet['cidr']
if (subnet['gateway'] is not None and
subnet['gateway']['address'] is not None):
obj.gateway = subnet['gateway']['address']
return obj
def _nova_to_osvif_subnets(subnets):
"""Convert Nova subnet list into os_vif object
:param subnets: list of nova.network.model.Subnet instances
:returns: os_vif.objects.subnet.SubnetList instance
"""
return objects.subnet.SubnetList(
objects=[_nova_to_osvif_subnet(subnet) for subnet in subnets])
def _nova_to_osvif_network(network):
"""Convert Nova network object into os_vif object
:param network: nova.network.model.Network instance
:returns: os_vif.objects.network.Network instance
"""
netobj = objects.network.Network(
id=network['id'],
subnets=_nova_to_osvif_subnets(network['subnets']))
if network["bridge"] is not None:
netobj.bridge = network['bridge']
if network['label'] is not None:
netobj.label = network['label']
if network.get_meta("multi_host") is not None:
netobj.multi_host = network.get_meta("multi_host")
if network.get_meta("should_provide_bridge") is not None:
netobj.should_provide_bridge = \
network.get_meta("should_provide_bridge")
if network.get_meta("bridge_interface") is not None:
netobj.bridge_interface = network.get_meta("bridge_interface")
if network.get_meta("should_provide_vlan") is not None:
netobj.should_provide_vlan = network.get_meta("should_provide_vlan")
if network.get_meta("vlan") is not None:
netobj.vlan = network.get_meta("vlan")
return netobj
def _get_vif_instance(vif, cls, **kwargs):
"""Instantiate an os-vif VIF instance
:param vif: the nova.nework.model.VIF instance
:param cls: class for a os_vif.objects.vif.VIFBase subclass
:returns: a os_vif.objects.vif.VIFBase instance
"""
return cls(
id=vif['id'],
address=vif['address'],
network=_nova_to_osvif_network(vif['network']),
has_traffic_filtering=vif.is_neutron_filtering_enabled(),
preserve_on_delete=vif['preserve_on_delete'],
active=vif['active'],
**kwargs)
# VIF_TYPE_BRIDGE = 'bridge'
def _nova_to_osvif_vif_bridge(vif):
obj = _get_vif_instance(
vif,
objects.vif.VIFBridge,
plugin="linux_bridge",
vif_name=_get_vif_name(vif))
if vif["network"]["bridge"] is not None:
obj.bridge_name = vif["network"]["bridge"]
return obj
# VIF_TYPE_OVS = 'ovs'
def _nova_to_osvif_vif_ovs(vif):
profile = objects.vif.VIFPortProfileOpenVSwitch(
interface_id=vif.get('ovs_interfaceid') or vif['id'])
if _is_firewall_required(vif) or vif.is_hybrid_plug_enabled():
obj = _get_vif_instance(
vif,
objects.vif.VIFBridge,
port_profile=profile,
plugin="ovs",
vif_name=_get_vif_name(vif),
bridge_name=_get_hybrid_bridge_name(vif))
else:
obj = _get_vif_instance(
vif,
objects.vif.VIFOpenVSwitch,
port_profile=profile,
plugin="ovs",
vif_name=_get_vif_name(vif))
if vif["network"]["bridge"] is not None:
obj.bridge_name = vif["network"]["bridge"]
return obj
# VIF_TYPE_IVS = 'ivs'
def _nova_to_osvif_vif_ivs(vif):
raise NotImplementedError()
# VIF_TYPE_DVS = 'dvs'
def _nova_to_osvif_vif_dvs(vif):
raise NotImplementedError()
# VIF_TYPE_IOVISOR = 'iovisor'
def _nova_to_osvif_vif_iovisor(vif):
raise NotImplementedError()
# VIF_TYPE_802_QBG = '802.1qbg'
def _nova_to_osvif_vif_802_1qbg(vif):
raise NotImplementedError()
# VIF_TYPE_802_QBH = '802.1qbh'
def _nova_to_osvif_vif_802_1qbh(vif):
raise NotImplementedError()
# VIF_TYPE_HW_VEB = 'hw_veb'
def _nova_to_osvif_vif_hw_veb(vif):
raise NotImplementedError()
# VIF_TYPE_IB_HOSTDEV = 'ib_hostdev'
def _nova_to_osvif_vif_ib_hostdev(vif):
raise NotImplementedError()
# VIF_TYPE_MIDONET = 'midonet'
def _nova_to_osvif_vif_midonet(vif):
raise NotImplementedError()
# VIF_TYPE_VHOSTUSER = 'vhostuser'
def _nova_to_osvif_vif_vhostuser(vif):
raise NotImplementedError()
# VIF_TYPE_VROUTER = 'vrouter'
def _nova_to_osvif_vif_vrouter(vif):
raise NotImplementedError()
# VIF_TYPE_TAP = 'tap'
def _nova_to_osvif_vif_tap(vif):
raise NotImplementedError()
# VIF_TYPE_MACVTAP = 'macvtap'
def _nova_to_osvif_vif_macvtap(vif):
raise NotImplementedError()
# VIF_TYPE_HOSTDEV = 'hostdev_physical'
def _nova_to_osvif_vif_hostdev_physical(vif):
raise NotImplementedError()
def nova_to_osvif_vif(vif):
"""Convert a Nova VIF model to an os-vif object
:param vif: a nova.network.model.VIF instance
Attempt to convert a nova VIF instance into an os-vif
VIF object, pointing to a suitable plugin. This will
return None if there is no os-vif plugin available yet.
:returns: a os_vif.objects.vif.VIFBase subclass, or None
if not supported with os-vif yet
"""
LOG.debug("Converting VIF %s", vif)
funcname = "_nova_to_osvif_vif_" + vif['type'].replace(".", "_")
func = getattr(sys.modules[__name__], funcname, None)
if not func:
raise exception.NovaException(
"Unsupported VIF type %(type)s convert '%(func)s'" %
{'type': vif['type'], 'func': funcname})
try:
vifobj = func(vif)
LOG.debug("Converted object %s", vifobj)
return vifobj
except NotImplementedError:
LOG.debug("No conversion for VIF type %s yet",
vif['type'])
return None

View File

@ -0,0 +1,550 @@
# 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
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from os_vif import objects as osv_objects
from nova import exception
from nova.network import model
from nova.network import os_vif_util
from nova import objects
from nova import test
class OSVIFUtilTestCase(test.NoDBTestCase):
def setUp(self):
super(OSVIFUtilTestCase, self).setUp()
osv_objects.register_all()
# Remove when all os-vif objects include the
# ComparableVersionedObject mix-in
def assertObjEqual(self, expect, actual):
actual.obj_reset_changes(recursive=True)
expect.obj_reset_changes(recursive=True)
self.assertEqual(expect.obj_to_primitive(),
actual.obj_to_primitive())
def _test_is_firewall_required(self, port_filter, driver, expect):
vif = model.VIF(
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
type=model.VIF_TYPE_BRIDGE,
address="22:52:25:62:e2:aa",
network=model.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
label="Demo Net",
subnets=[]),
details={
model.VIF_DETAILS_PORT_FILTER: port_filter,
}
)
self.flags(firewall_driver=driver)
self.assertEqual(expect, os_vif_util._is_firewall_required(vif))
def test_is_firewall_required_via_vif(self):
self._test_is_firewall_required(
True, "nova.virt.libvirt.firewall.IptablesFirewallDriver", False)
def test_is_firewall_required_via_driver(self):
self._test_is_firewall_required(
False, "nova.virt.libvirt.firewall.IptablesFirewallDriver", True)
def test_is_firewall_required_not(self):
self._test_is_firewall_required(
False, "nova.virt.firewall.NoopFirewallDriver", False)
def test_nova_to_osvif_instance(self):
inst = objects.Instance(
id="1242",
uuid="d5b1090c-9e00-4fa4-9504-4b1494857970",
project_id="2f37d7f6-e51a-4a1f-8b6e-b0917ffc8390")
info = os_vif_util.nova_to_osvif_instance(inst)
expect = osv_objects.instance_info.InstanceInfo(
uuid="d5b1090c-9e00-4fa4-9504-4b1494857970",
name="instance-000004da",
project_id="2f37d7f6-e51a-4a1f-8b6e-b0917ffc8390")
self.assertObjEqual(info, expect)
def test_nova_to_osvif_instance_minimal(self):
inst = objects.Instance(
id="1242",
uuid="d5b1090c-9e00-4fa4-9504-4b1494857970")
actual = os_vif_util.nova_to_osvif_instance(inst)
expect = osv_objects.instance_info.InstanceInfo(
uuid=inst.uuid,
name=inst.name)
self.assertObjEqual(expect, actual)
def test_nova_to_osvif_ips(self):
ips = [
model.FixedIP(
address="192.168.122.24",
floating_ips=[
model.IP(address="192.168.122.100",
type="floating"),
model.IP(address="192.168.122.101",
type="floating"),
model.IP(address="192.168.122.102",
type="floating"),
],
version=4),
model.FixedIP(
address="2001::beef",
version=6),
]
actual = os_vif_util._nova_to_osvif_ips(ips)
expect = osv_objects.fixed_ip.FixedIPList(
objects=[
osv_objects.fixed_ip.FixedIP(
address="192.168.122.24",
floating_ips=[
"192.168.122.100",
"192.168.122.101",
"192.168.122.102",
]),
osv_objects.fixed_ip.FixedIP(
address="2001::beef",
floating_ips=[]),
],
)
self.assertObjEqual(expect, actual)
def test_nova_to_osvif_routes(self):
routes = [
model.Route(cidr="192.168.1.0/24",
gateway=model.IP(
address="192.168.1.254",
type='gateway'),
interface="eth0"),
model.Route(cidr="10.0.0.0/8",
gateway=model.IP(
address="10.0.0.1",
type='gateway'),
interface="eth1"),
]
expect = osv_objects.route.RouteList(
objects=[
osv_objects.route.Route(
cidr="192.168.1.0/24",
gateway="192.168.1.254",
interface="eth0"),
osv_objects.route.Route(
cidr="10.0.0.0/8",
gateway="10.0.0.1",
interface="eth1"),
])
actual = os_vif_util._nova_to_osvif_routes(routes)
self.assertObjEqual(expect, actual)
def test_nova_to_osvif_subnets(self):
subnets = [
model.Subnet(cidr="192.168.1.0/24",
dns=[
model.IP(
address="192.168.1.1",
type="dns"),
model.IP(
address="192.168.1.2",
type="dns"),
],
gateway=model.IP(
address="192.168.1.254",
type='gateway'),
ips=[
model.FixedIP(
address="192.168.1.100",
),
model.FixedIP(
address="192.168.1.101",
),
],
routes=[
model.Route(
cidr="10.0.0.1/24",
gateway=model.IP(
address="192.168.1.254",
type="gateway"),
interface="eth0"),
]),
model.Subnet(dns=[
model.IP(
address="192.168.1.1",
type="dns"),
model.IP(
address="192.168.1.2",
type="dns"),
],
ips=[
model.FixedIP(
address="192.168.1.100",
),
model.FixedIP(
address="192.168.1.101",
),
],
routes=[
model.Route(
cidr="10.0.0.1/24",
gateway=model.IP(
address="192.168.1.254",
type="gateway"),
interface="eth0"),
]),
model.Subnet(dns=[
model.IP(
address="192.168.1.1",
type="dns"),
model.IP(
address="192.168.1.2",
type="dns"),
],
gateway=model.IP(
type='gateway'),
ips=[
model.FixedIP(
address="192.168.1.100",
),
model.FixedIP(
address="192.168.1.101",
),
],
routes=[
model.Route(
cidr="10.0.0.1/24",
gateway=model.IP(
address="192.168.1.254",
type="gateway"),
interface="eth0"),
]),
]
expect = osv_objects.subnet.SubnetList(
objects=[
osv_objects.subnet.Subnet(
cidr="192.168.1.0/24",
dns=["192.168.1.1",
"192.168.1.2"],
gateway="192.168.1.254",
ips=osv_objects.fixed_ip.FixedIPList(
objects=[
osv_objects.fixed_ip.FixedIP(
address="192.168.1.100",
floating_ips=[]),
osv_objects.fixed_ip.FixedIP(
address="192.168.1.101",
floating_ips=[]),
]),
routes=osv_objects.route.RouteList(
objects=[
osv_objects.route.Route(
cidr="10.0.0.1/24",
gateway="192.168.1.254",
interface="eth0")
]),
),
osv_objects.subnet.Subnet(
dns=["192.168.1.1",
"192.168.1.2"],
ips=osv_objects.fixed_ip.FixedIPList(
objects=[
osv_objects.fixed_ip.FixedIP(
address="192.168.1.100",
floating_ips=[]),
osv_objects.fixed_ip.FixedIP(
address="192.168.1.101",
floating_ips=[]),
]),
routes=osv_objects.route.RouteList(
objects=[
osv_objects.route.Route(
cidr="10.0.0.1/24",
gateway="192.168.1.254",
interface="eth0")
]),
),
osv_objects.subnet.Subnet(
dns=["192.168.1.1",
"192.168.1.2"],
ips=osv_objects.fixed_ip.FixedIPList(
objects=[
osv_objects.fixed_ip.FixedIP(
address="192.168.1.100",
floating_ips=[]),
osv_objects.fixed_ip.FixedIP(
address="192.168.1.101",
floating_ips=[]),
]),
routes=osv_objects.route.RouteList(
objects=[
osv_objects.route.Route(
cidr="10.0.0.1/24",
gateway="192.168.1.254",
interface="eth0")
]),
),
])
actual = os_vif_util._nova_to_osvif_subnets(subnets)
self.assertObjEqual(expect, actual)
def test_nova_to_osvif_network(self):
network = model.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
bridge="br0",
subnets=[
model.Subnet(cidr="192.168.1.0/24",
gateway=model.IP(
address="192.168.1.254",
type='gateway')),
])
expect = osv_objects.network.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
bridge="br0",
subnets=osv_objects.subnet.SubnetList(
objects=[
osv_objects.subnet.Subnet(
cidr="192.168.1.0/24",
dns=[],
gateway="192.168.1.254",
ips=osv_objects.fixed_ip.FixedIPList(
objects=[]),
routes=osv_objects.route.RouteList(
objects=[]),
)
]))
actual = os_vif_util._nova_to_osvif_network(network)
self.assertObjEqual(expect, actual)
def test_nova_to_osvif_network_extra(self):
network = model.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
bridge="br0",
multi_host=True,
should_provide_bridge=True,
should_provide_vlan=True,
bridge_interface="eth0",
vlan=1729,
subnets=[
model.Subnet(cidr="192.168.1.0/24",
gateway=model.IP(
address="192.168.1.254",
type='gateway')),
])
expect = osv_objects.network.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
bridge="br0",
multi_host=True,
should_provide_bridge=True,
should_provide_vlan=True,
bridge_interface="eth0",
vlan=1729,
subnets=osv_objects.subnet.SubnetList(
objects=[
osv_objects.subnet.Subnet(
cidr="192.168.1.0/24",
dns=[],
gateway="192.168.1.254",
ips=osv_objects.fixed_ip.FixedIPList(
objects=[]),
routes=osv_objects.route.RouteList(
objects=[]),
)
]))
actual = os_vif_util._nova_to_osvif_network(network)
self.assertObjEqual(expect, actual)
def test_nova_to_osvif_network_labeled_no_bridge(self):
network = model.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
label="Demo Net",
subnets=[
model.Subnet(cidr="192.168.1.0/24",
gateway=model.IP(
address="192.168.1.254",
type='gateway')),
])
expect = osv_objects.network.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
label="Demo Net",
subnets=osv_objects.subnet.SubnetList(
objects=[
osv_objects.subnet.Subnet(
cidr="192.168.1.0/24",
dns=[],
gateway="192.168.1.254",
ips=osv_objects.fixed_ip.FixedIPList(
objects=[]),
routes=osv_objects.route.RouteList(
objects=[]),
)
]))
actual = os_vif_util._nova_to_osvif_network(network)
self.assertObjEqual(expect, actual)
def test_nova_to_osvif_vif_linux_bridge(self):
vif = model.VIF(
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
type=model.VIF_TYPE_BRIDGE,
address="22:52:25:62:e2:aa",
network=model.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
label="Demo Net",
subnets=[]),
details={
model.VIF_DETAILS_PORT_FILTER: True,
}
)
actual = os_vif_util.nova_to_osvif_vif(vif)
expect = osv_objects.vif.VIFBridge(
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
active=False,
address="22:52:25:62:e2:aa",
has_traffic_filtering=True,
plugin="linux_bridge",
preserve_on_delete=False,
vif_name="nicdc065497-3c",
network=osv_objects.network.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
label="Demo Net",
subnets=osv_objects.subnet.SubnetList(
objects=[])))
self.assertObjEqual(expect, actual)
def test_nova_to_osvif_vif_ovs_plain(self):
vif = model.VIF(
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
type=model.VIF_TYPE_OVS,
address="22:52:25:62:e2:aa",
network=model.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
label="Demo Net",
subnets=[]),
details={
model.VIF_DETAILS_PORT_FILTER: True,
}
)
actual = os_vif_util.nova_to_osvif_vif(vif)
expect = osv_objects.vif.VIFOpenVSwitch(
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
active=False,
address="22:52:25:62:e2:aa",
has_traffic_filtering=True,
plugin="ovs",
port_profile=osv_objects.vif.VIFPortProfileOpenVSwitch(
interface_id="dc065497-3c8d-4f44-8fb4-e1d33c16a536"),
preserve_on_delete=False,
vif_name="nicdc065497-3c",
network=osv_objects.network.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
label="Demo Net",
subnets=osv_objects.subnet.SubnetList(
objects=[])))
self.assertObjEqual(expect, actual)
def test_nova_to_osvif_vif_ovs_hybrid(self):
vif = model.VIF(
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
type=model.VIF_TYPE_OVS,
address="22:52:25:62:e2:aa",
network=model.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
label="Demo Net",
subnets=[]),
details={
model.VIF_DETAILS_PORT_FILTER: False,
}
)
actual = os_vif_util.nova_to_osvif_vif(vif)
expect = osv_objects.vif.VIFBridge(
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
active=False,
address="22:52:25:62:e2:aa",
has_traffic_filtering=False,
plugin="ovs",
bridge_name="qbrdc065497-3c",
port_profile=osv_objects.vif.VIFPortProfileOpenVSwitch(
interface_id="dc065497-3c8d-4f44-8fb4-e1d33c16a536"),
preserve_on_delete=False,
vif_name="nicdc065497-3c",
network=osv_objects.network.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
label="Demo Net",
subnets=osv_objects.subnet.SubnetList(
objects=[])))
self.assertObjEqual(expect, actual)
def test_nova_to_osvif_vif_ivs_plain(self):
vif = model.VIF(
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
type=model.VIF_TYPE_IVS,
address="22:52:25:62:e2:aa",
network=model.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
label="Demo Net",
subnets=[]),
details={
model.VIF_DETAILS_PORT_FILTER: True,
}
)
actual = os_vif_util.nova_to_osvif_vif(vif)
self.assertIsNone(actual)
def test_nova_to_osvif_vif_unknown(self):
vif = model.VIF(
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
type="wibble",
address="22:52:25:62:e2:aa",
network=model.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
label="Demo Net",
subnets=[]),
)
self.assertRaises(exception.NovaException,
os_vif_util.nova_to_osvif_vif,
vif)

View File

@ -281,7 +281,7 @@ class TestNotificationObjectVersions(test.NoDBTestCase):
def test_versions(self):
checker = fixture.ObjectVersionChecker(
base.NovaObjectRegistry.obj_classes())
test_objects.get_nova_objects())
notification_object_data.update(test_objects.object_data)
expected, actual = checker.test_hashes(notification_object_data)
self.assertEqual(expected, actual,

View File

@ -1206,10 +1206,31 @@ object_data = {
}
def get_nova_objects():
"""Get Nova versioned objects
This returns a dict of versioned objects which are
in the Nova project namespace only. ie excludes
objects from os-vif and other 3rd party modules
:return: a dict mapping class names to lists of versioned objects
"""
all_classes = base.NovaObjectRegistry.obj_classes()
nova_classes = {}
for name in all_classes:
objclasses = all_classes[name]
if (objclasses[0].OBJ_PROJECT_NAMESPACE !=
base.NovaObject.OBJ_PROJECT_NAMESPACE):
continue
nova_classes[name] = objclasses
return nova_classes
class TestObjectVersions(test.NoDBTestCase):
def test_versions(self):
checker = fixture.ObjectVersionChecker(
base.NovaObjectRegistry.obj_classes())
get_nova_objects())
fingerprints = checker.get_hashes()
if os.getenv('GENERATE_HASHES'):

View File

@ -54,6 +54,7 @@ oslo.middleware>=3.0.0 # Apache-2.0
psutil<2.0.0,>=1.1.1 # BSD
oslo.versionedobjects>=1.13.0 # Apache-2.0
os-brick>=1.3.0 # Apache-2.0
os-vif>=1.0.0 # Apache-2.0
os-win>=0.2.3 # Apache-2.0
castellan>=0.4.0 # Apache-2.0
microversion-parse>=0.1.2 # Apache-2.0