Add create_port field in VIFPortProfileOpenVSwitch profile

In case of Smart NIC, os-vif is used to plug the representor port to the
integration bridge, so the Neutron agent that runs on the Smart NIC must
behave like libvirt and do plug/unplug for the representor port.

Change-Id: Ic2c3c88ad0c3865dae96c717b5d137f1ea18326f
This commit is contained in:
Hamdy Khader 2019-02-10 16:31:23 +02:00
parent 192d6fd114
commit 9611f04722
5 changed files with 63 additions and 6 deletions

View File

@ -226,7 +226,8 @@ class VIFPortProfileOpenVSwitch(VIFPortProfileBase):
# Version 1.0: Initial release
# Version 1.1: Added 'datapath_type'
# Version 1.2: VIFPortProfileBase updated to 1.1
VERSION = '1.2'
# Version 1.3: Added 'create_port'
VERSION = '1.3'
fields = {
'interface_id': fields.UUIDField(),
@ -234,6 +235,9 @@ class VIFPortProfileOpenVSwitch(VIFPortProfileBase):
# Datapath type of the bridge
'datapath_type': fields.StringField(nullable=True),
# If set, the os-vif plugin should add the port to the bridge
'create_port': fields.BooleanField(default=False),
}
def obj_make_compatible(self, primitive, target_version):
@ -245,6 +249,8 @@ class VIFPortProfileOpenVSwitch(VIFPortProfileBase):
if target_version < (1, 2):
super(VIFPortProfileOpenVSwitch, self).obj_make_compatible(
primitive, "1.0")
if target_version < (1, 3) and 'create_port' in primitive:
del primitive['create_port']
@base.VersionedObjectRegistry.register
@ -253,7 +259,8 @@ class VIFPortProfileFPOpenVSwitch(VIFPortProfileOpenVSwitch):
# Version 1.0: Initial release
# Version 1.1: VIFPortProfileOpenVSwitch updated to 1.1
# Version 1.2: VIFPortProfileOpenVSwitch updated to 1.2
VERSION = '1.2'
# Version 1.3: VIFPortProfileOpenVSwitch updated to 1.3
VERSION = '1.3'
fields = {
# Name of the bridge (managed by fast path) to connect to
@ -271,6 +278,9 @@ class VIFPortProfileFPOpenVSwitch(VIFPortProfileOpenVSwitch):
if target_version < (1, 2):
super(VIFPortProfileFPOpenVSwitch, self).obj_make_compatible(
primitive, "1.1")
if target_version < (1, 3):
super(VIFPortProfileFPOpenVSwitch, self).obj_make_compatible(
primitive, "1.2")
@removals.removed_class("VIFPortProfileOVSRepresentor",
@ -284,7 +294,8 @@ class VIFPortProfileOVSRepresentor(VIFPortProfileOpenVSwitch):
# Version 1.0: Initial release
# Version 1.1: VIFPortProfileOpenVSwitch updated to 1.1
# Version 1.2: VIFPortProfileOpenVSwitch updated to 1.2
VERSION = '1.2'
# Version 1.3: VIFPortProfileOpenVSwitch updated to 1.3
VERSION = '1.3'
fields = {
# Name to set on the representor (if set)
@ -302,6 +313,9 @@ class VIFPortProfileOVSRepresentor(VIFPortProfileOpenVSwitch):
if target_version < (1, 2):
super(VIFPortProfileOVSRepresentor, self).obj_make_compatible(
primitive, "1.1")
if target_version < (1, 3):
super(VIFPortProfileOVSRepresentor, self).obj_make_compatible(
primitive, "1.2")
@base.VersionedObjectRegistry.register

View File

@ -40,12 +40,12 @@ object_data = {
'VIFPortProfile8021Qbg': '1.1-b3011621809dca9216b50579ce9d6b19',
'VIFPortProfile8021Qbh': '1.1-226b61b2e76ba452f7b31530cff80ac9',
'VIFPortProfileBase': '1.1-4982d1621df12ebd1f3b07948f3d0e5f',
'VIFPortProfileOpenVSwitch': '1.2-25aec86b7ec9fcb3434f896f694818de',
'VIFPortProfileFPOpenVSwitch': '1.2-4a4f230d89a5ea0e43011f678b626dd9',
'VIFPortProfileOpenVSwitch': '1.3-1ad9a350a9cae19c977d21fcce7c8c7f',
'VIFPortProfileFPOpenVSwitch': '1.3-06c425743430e7702ef112e09b987346',
'VIFPortProfileFPBridge': '1.1-49f1952bf50bab7a95112c908534751f',
'VIFPortProfileFPTap': '1.1-fd178229477604dfb65de5ce929488e5',
'VIFVHostUser': '1.1-1f95b43be1f884f090ca1f4d79adfd35',
'VIFPortProfileOVSRepresentor': '1.2-d0609e93ea884ef7b4949177e9fcdc39',
'VIFPortProfileOVSRepresentor': '1.3-f625e17143473b93d6c7f97ded9f785a',
'VIFNestedDPDK': '1.0-fdbaf6b20afd116529929b21aa7158dc',
'VIFPortProfileK8sDPDK': '1.1-e2a2abd112b14e0239e76b99d9b252ae',
'DatapathOffloadBase': '1.0-77509ea1ea0dd750d5864b9bd87d3f9d',

View File

@ -106,6 +106,17 @@ class TestVIFS(base.TestCase):
self.assertEqual('netdev', data['datapath_type'])
self.assertNotIn('datapath_offload', data)
def test_port_profile_ovs_backport_1_2(self):
obj = objects.vif.VIFPortProfileOpenVSwitch(
interface_id="07bd6cea-fb37-4594-b769-90fc51854ee9",
create_port=True)
primitive = obj.obj_to_primitive(target_version='1.2')
self.assertEqual('1.2', primitive['versioned_object.version'])
data = primitive['versioned_object.data']
self.assertEqual('07bd6cea-fb37-4594-b769-90fc51854ee9',
data['interface_id'])
self.assertNotIn('create_port', data)
def test_vif_direct_plain(self):
self._test_vif(objects.vif.VIFDirect,
vif_name="vif123",

View File

@ -247,6 +247,13 @@ class OvsPlugin(plugin.PluginBase):
# this comment will be removed when we actully fix #1734320 in
# all cases.
# NOTE(hamdyk): As a WA to the above note, one can use
# VIFPortProfileOpenVSwitch.create_port flag to explicitly
# plug the port to the switch.
if ("create_port" in vif.port_profile and
vif.port_profile.create_port):
self._create_vif_port(vif, vif.vif_name, instance_info)
def _plug_vf_passthrough(self, vif, instance_info):
self.ovsdb.ensure_ovs_bridge(
vif.network.bridge, constants.OVS_DATAPATH_SYSTEM)

View File

@ -61,6 +61,10 @@ class PluginTest(testtools.TestCase):
interface_id='e65867e0-9340-4a7f-a256-09af6eb7a3aa',
datapath_type='netdev')
self.profile_ovs_smart_nic = objects.vif.VIFPortProfileOpenVSwitch(
interface_id='e65867e0-9340-4a7f-a256-09af6eb7a3aa',
create_port=True)
self.profile_ovs_no_datatype = objects.vif.VIFPortProfileOpenVSwitch(
interface_id='e65867e0-9340-4a7f-a256-09af6eb7a3aa',
datapath_type='')
@ -80,6 +84,13 @@ class PluginTest(testtools.TestCase):
vif_name='tap-xxx-yyy-zzz',
port_profile=self.profile_ovs)
self.vif_ovs_smart_nic = objects.vif.VIFOpenVSwitch(
id='b679325f-ca89-4ee0-a8be-6db1409b69ea',
address='ca:fe:de:ad:be:ef',
network=self.network_ovs,
vif_name='rep0-0',
port_profile=self.profile_ovs_smart_nic)
self.vif_vhostuser = objects.vif.VIFVHostUser(
id='b679325f-ca89-4ee0-a8be-6db1409b69ea',
address='ca:fe:de:ad:be:ef',
@ -445,3 +456,17 @@ class PluginTest(testtools.TestCase):
calls['get_representor_port'])
delete_ovs_vif_port.assert_has_calls(calls['delete_ovs_vif_port'])
set_interface_state.assert_has_calls(calls['set_interface_state'])
@mock.patch.object(ovsdb_lib.BaseOVS, 'ensure_ovs_bridge')
@mock.patch.object(ovs.OvsPlugin, "_create_vif_port")
def test_plug_vif_ovs_smart_nic(self, create_port, ensure_bridge):
plugin = ovs.OvsPlugin.load(constants.PLUGIN_NAME)
plugin.plug(self.vif_ovs_smart_nic, self.instance)
ensure_bridge.assert_called_once()
create_port.assert_called_once()
@mock.patch.object(ovs.OvsPlugin, '_unplug_vif_generic')
def test_unplug_vif_ovs_smart_nic(self, delete_port):
plugin = ovs.OvsPlugin.load(constants.PLUGIN_NAME)
plugin.unplug(self.vif_ovs_smart_nic, self.instance)
delete_port.assert_called_once()