Skip to content

Commit 6309414

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "[OVN][Trunk] Add port binding info on subport when parent is bound" into stable/yoga
2 parents 5ae479c + cd4f345 commit 6309414

File tree

3 files changed

+62
-20
lines changed

3 files changed

+62
-20
lines changed

neutron/services/trunk/drivers/ovn/trunk_driver.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,13 @@ def _set_sub_ports(self, parent_port, subports):
4949
context = n_context.get_admin_context()
5050
db_parent_port = port_obj.Port.get_object(context, id=parent_port)
5151
parent_port_status = db_parent_port.status
52+
parent_port_bindings = db_parent_port.bindings[0]
5253
for subport in subports:
5354
with db_api.CONTEXT_WRITER.using(context), (
5455
txn(check_error=True)) as ovn_txn:
5556
port = self._set_binding_profile(context, subport, parent_port,
56-
parent_port_status, ovn_txn)
57+
parent_port_status,
58+
parent_port_bindings, ovn_txn)
5759
db_rev.bump_revision(context, port, ovn_const.TYPE_PORTS)
5860

5961
def _unset_sub_ports(self, subports):
@@ -67,7 +69,8 @@ def _unset_sub_ports(self, subports):
6769

6870
@db_base_plugin_common.convert_result_to_dict
6971
def _set_binding_profile(self, context, subport, parent_port,
70-
parent_port_status, ovn_txn):
72+
parent_port_status,
73+
parent_port_bindings, ovn_txn):
7174
LOG.debug("Setting parent %s for subport %s",
7275
parent_port, subport.port_id)
7376
db_port = port_obj.Port.get_object(context, id=subport.port_id)
@@ -79,6 +82,9 @@ def _set_binding_profile(self, context, subport, parent_port,
7982
check_rev_cmd = self.plugin_driver.nb_ovn.check_revision_number(
8083
db_port.id, db_port, ovn_const.TYPE_PORTS)
8184
ovn_txn.add(check_rev_cmd)
85+
parent_binding_host = ''
86+
if parent_port_bindings.host:
87+
parent_binding_host = parent_port_bindings.host
8288
try:
8389
# NOTE(flaviof): We expect binding's host to be set. Otherwise,
8490
# sub-port will not transition from DOWN to ACTIVE.
@@ -94,6 +100,7 @@ def _set_binding_profile(self, context, subport, parent_port,
94100
port_obj.PortBinding.update_object(
95101
context,
96102
{'profile': binding.profile,
103+
'host': parent_binding_host,
97104
'vif_type': portbindings.VIF_TYPE_OVS},
98105
port_id=subport.port_id,
99106
host=binding.host)
@@ -155,6 +162,14 @@ def _unset_binding_profile(self, context, subport, ovn_txn):
155162
LOG.debug("Done unsetting parent for subport %s", subport.port_id)
156163
return db_port
157164

165+
def trunk_updated(self, trunk):
166+
# Check if parent port is handled by OVN.
167+
if not self.plugin_driver.nb_ovn.lookup('Logical_Switch_Port',
168+
trunk.port_id, default=None):
169+
return
170+
if trunk.sub_ports:
171+
self._set_sub_ports(trunk.port_id, trunk.sub_ports)
172+
158173
def trunk_created(self, trunk):
159174
# Check if parent port is handled by OVN.
160175
if not self.plugin_driver.nb_ovn.lookup('Logical_Switch_Port',
@@ -189,6 +204,8 @@ def subports_deleted(self, trunk, subports):
189204
def trunk_event(self, resource, event, trunk_plugin, payload):
190205
if event == events.AFTER_CREATE:
191206
self.trunk_created(payload.states[0])
207+
elif event == events.AFTER_UPDATE:
208+
self.trunk_updated(payload.states[0])
192209
elif event == events.AFTER_DELETE:
193210
self.trunk_deleted(payload.states[0])
194211

@@ -215,13 +232,16 @@ def register(self, resource, event, trigger, payload=None):
215232
super(OVNTrunkDriver, self).register(
216233
resource, event, trigger, payload=payload)
217234
self._handler = OVNTrunkHandler(self.plugin_driver)
218-
for trunk_event in (events.AFTER_CREATE, events.AFTER_DELETE):
235+
for _event in (events.AFTER_CREATE, events.AFTER_UPDATE,
236+
events.AFTER_DELETE):
219237
registry.subscribe(self._handler.trunk_event,
220238
resources.TRUNK,
221-
trunk_event)
239+
_event)
240+
241+
for _event in (events.AFTER_CREATE, events.AFTER_DELETE):
222242
registry.subscribe(self._handler.subport_event,
223243
resources.SUBPORTS,
224-
trunk_event)
244+
_event)
225245

226246
@classmethod
227247
def create(cls, plugin_driver):

neutron/tests/functional/services/trunk/drivers/ovn/test_trunk_driver.py

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,23 @@
1414

1515
import contextlib
1616

17-
from neutron.services.trunk import plugin as trunk_plugin
18-
from neutron.tests.functional import base
17+
from neutron_lib.api.definitions import portbindings
1918
from neutron_lib import constants as n_consts
20-
from neutron_lib.objects import registry as obj_reg
19+
from neutron_lib.db import api as db_api
2120
from neutron_lib.plugins import utils
2221
from neutron_lib.services.trunk import constants as trunk_consts
2322
from oslo_utils import uuidutils
2423

2524
from neutron.common.ovn import constants as ovn_const
25+
from neutron.objects import ports as port_obj
26+
from neutron.services.trunk import plugin as trunk_plugin
27+
from neutron.tests.functional import base
2628

2729

2830
class TestOVNTrunkDriver(base.TestOVNFunctionalBase):
2931

30-
def setUp(self):
31-
super(TestOVNTrunkDriver, self).setUp()
32+
def setUp(self, **kwargs):
33+
super().setUp(**kwargs)
3234
self.trunk_plugin = trunk_plugin.TrunkPlugin()
3335
self.trunk_plugin.add_segmentation_type(
3436
trunk_consts.SEGMENTATION_TYPE_VLAN,
@@ -39,7 +41,8 @@ def trunk(self, sub_ports=None):
3941
sub_ports = sub_ports or []
4042
with self.network() as network:
4143
with self.subnet(network=network) as subnet:
42-
with self.port(subnet=subnet) as parent_port:
44+
with self.port(subnet=subnet,
45+
device_owner='compute:nova') as parent_port:
4346
tenant_id = uuidutils.generate_uuid()
4447
trunk = {'trunk': {
4548
'port_id': parent_port['port']['id'],
@@ -64,17 +67,14 @@ def _get_ovn_trunk_info(self):
6467
if row.parent_name and row.tag:
6568
device_owner = row.external_ids[
6669
ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY]
67-
revision_number = row.external_ids[
68-
ovn_const.OVN_REV_NUM_EXT_ID_KEY]
6970
ovn_trunk_info.append({'port_id': row.name,
7071
'parent_port_id': row.parent_name,
7172
'tag': row.tag,
7273
'device_owner': device_owner,
73-
'revision_number': revision_number,
7474
})
7575
return ovn_trunk_info
7676

77-
def _verify_trunk_info(self, trunk, has_items):
77+
def _verify_trunk_info(self, trunk, has_items, host=''):
7878
ovn_subports_info = self._get_ovn_trunk_info()
7979
neutron_subports_info = []
8080
for subport in trunk.get('sub_ports', []):
@@ -83,19 +83,27 @@ def _verify_trunk_info(self, trunk, has_items):
8383
'parent_port_id': [trunk['port_id']],
8484
'tag': [subport['segmentation_id']],
8585
'device_owner': trunk_consts.TRUNK_SUBPORT_OWNER,
86-
'revision_number': '2',
8786
})
88-
# Check that the subport has the binding is active.
89-
binding = obj_reg.load_class('PortBinding').get_object(
90-
self.context, port_id=subport['port_id'], host='')
91-
self.assertEqual(n_consts.PORT_STATUS_ACTIVE, binding['status'])
87+
# Check the subport binding.
88+
pb = port_obj.PortBinding.get_object(
89+
self.context, port_id=subport['port_id'], host=host)
90+
self.assertEqual(n_consts.PORT_STATUS_ACTIVE, pb.status)
91+
self.assertEqual(host, pb.host)
9292

9393
self.assertCountEqual(ovn_subports_info, neutron_subports_info)
9494
self.assertEqual(has_items, len(neutron_subports_info) != 0)
9595

9696
if trunk.get('status'):
9797
self.assertEqual(trunk_consts.TRUNK_ACTIVE_STATUS, trunk['status'])
9898

99+
def _bind_port(self, port_id, host):
100+
with db_api.CONTEXT_WRITER.using(self.context):
101+
pb = port_obj.PortBinding.get_object(self.context,
102+
port_id=port_id, host='')
103+
pb.delete()
104+
port_obj.PortBinding(self.context, port_id=port_id, host=host,
105+
vif_type=portbindings.VIF_TYPE_OVS).create()
106+
99107
def test_trunk_create(self):
100108
with self.trunk() as trunk:
101109
self._verify_trunk_info(trunk, has_items=False)
@@ -113,10 +121,22 @@ def test_subport_add(self):
113121
new_trunk = self.trunk_plugin.get_trunk(self.context,
114122
trunk['id'])
115123
self._verify_trunk_info(new_trunk, has_items=True)
124+
# Bind parent port. That will trigger the binding of the
125+
# trunk subports too, using the same host ID.
126+
self._bind_port(trunk['port_id'], 'host1')
127+
self.mech_driver.set_port_status_up(trunk['port_id'])
128+
self._verify_trunk_info(new_trunk, has_items=True,
129+
host='host1')
116130

117131
def test_subport_delete(self):
118132
with self.subport() as subport:
119133
with self.trunk([subport]) as trunk:
134+
# Bind parent port.
135+
self._bind_port(trunk['port_id'], 'host1')
136+
self.mech_driver.set_port_status_up(trunk['port_id'])
137+
self._verify_trunk_info(trunk, has_items=True,
138+
host='host1')
139+
120140
self.trunk_plugin.remove_subports(self.context, trunk['id'],
121141
{'sub_ports': [subport]})
122142
new_trunk = self.trunk_plugin.get_trunk(self.context,

neutron/tests/unit/services/trunk/drivers/ovn/test_trunk_driver.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ def test_create_trunk(self):
122122
mock.call(mock.ANY,
123123
{'profile': {'parent_name': trunk.port_id,
124124
'tag': s_port.segmentation_id},
125+
'host': mock.ANY,
125126
'vif_type': portbindings.VIF_TYPE_OVS},
126127
host=mock.ANY,
127128
port_id=s_port.port_id)
@@ -152,6 +153,7 @@ def test_create_trunk_port_db_exception(self):
152153
self.mock_update_pb.assert_called_once_with(
153154
mock.ANY, {'profile': {'parent_name': self.sub_port_1.trunk_id,
154155
'tag': self.sub_port_1.segmentation_id},
156+
'host': 'foo.com',
155157
'vif_type': portbindings.VIF_TYPE_OVS},
156158
host='foo.com', port_id=self.sub_port_1.port_id)
157159
self.mock_port_update.assert_not_called()

0 commit comments

Comments
 (0)