diff --git a/neutron/common/ovn/utils.py b/neutron/common/ovn/utils.py index 14cfd19f5f8..c13f5ecc71e 100644 --- a/neutron/common/ovn/utils.py +++ b/neutron/common/ovn/utils.py @@ -1000,3 +1000,10 @@ def validate_port_binding_and_virtual_port( raise n_exc.BadRequest( resource='port', msg='A virtual logical switch port cannot be bound to a host') + + +def get_requested_chassis(requested_chassis): + """Returns a list with the items in the LSP.options:requested-chassis""" + if isinstance(requested_chassis, str): + return requested_chassis.split(',') + return [] diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovsdb_monitor.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovsdb_monitor.py index 9b0ba129aa9..c10df10b149 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovsdb_monitor.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovsdb_monitor.py @@ -277,6 +277,15 @@ class PortBindingChassisUpdateEvent(row_event.RowEvent): {'port': row.logical_port, 'binding': row.uuid}) return False + req_chassis = utils.get_requested_chassis( + row.options.get(ovn_const.LSP_OPTIONS_REQUESTED_CHASSIS_KEY, '')) + if len(req_chassis) > 1: + # This event has been issued during a LSP migration. During this + # process, the LSP will change the port binding but the port status + # will be handled by the ``LogicalSwitchPortUpdateDownEvent`` and + # ``LogicalSwitchPortUpdateUpEvent`` events. + return False + return bool(lsp.up) def run(self, event, row, old=None): diff --git a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovsdb_monitor.py b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovsdb_monitor.py index 9523be67b03..469782a9967 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovsdb_monitor.py +++ b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovsdb_monitor.py @@ -357,6 +357,7 @@ class TestPortBindingChassisUpdateEvent(base.BaseTestCase): self.driver.set_port_status_up.assert_called() else: self.driver.set_port_status_up.assert_not_called() + self.driver.set_port_status_up.reset_mock() def test_event_matches(self): # NOTE(twilson) This primarily tests implementation details. If a @@ -366,10 +367,24 @@ class TestPortBindingChassisUpdateEvent(base.BaseTestCase): attrs={'name': 'Port_Binding'}) ovsdb_row = fakes.FakeOvsdbRow.create_one_ovsdb_row self.driver.nb_ovn.lookup.return_value = ovsdb_row(attrs={'up': True}) + + # Port binding change. self._test_event( self.event.ROW_UPDATE, ovsdb_row(attrs={'_table': pbtable, 'chassis': 'one', - 'type': '_fake_', 'logical_port': 'foo'}), + 'type': '_fake_', 'logical_port': 'foo', + 'options': {}}), + ovsdb_row(attrs={'_table': pbtable, 'chassis': 'two', + 'type': '_fake_'})) + + # Port binding change because of a live migration in progress. + options = { + ovn_const.LSP_OPTIONS_REQUESTED_CHASSIS_KEY: 'chassis1,chassis2'} + self._test_event( + self.event.ROW_UPDATE, + ovsdb_row(attrs={'_table': pbtable, 'chassis': 'one', + 'type': '_fake_', 'logical_port': 'foo', + 'options': options}), ovsdb_row(attrs={'_table': pbtable, 'chassis': 'two', 'type': '_fake_'}))