Merge "Use Port_Binding up column to set Neutron port status"
This commit is contained in:
commit
cb97054433
|
@ -281,6 +281,10 @@ LSP_OPTIONS_VIRTUAL_IP_KEY = 'virtual-ip'
|
|||
LSP_OPTIONS_MCAST_FLOOD_REPORTS = 'mcast_flood_reports'
|
||||
LSP_OPTIONS_MCAST_FLOOD = 'mcast_flood'
|
||||
|
||||
# Port Binding types
|
||||
PB_TYPE_PATCH = 'patch'
|
||||
PB_TYPE_VIRTUAL = 'virtual'
|
||||
|
||||
HA_CHASSIS_GROUP_DEFAULT_NAME = 'default_ha_chassis_group'
|
||||
HA_CHASSIS_GROUP_HIGHEST_PRIORITY = 32767
|
||||
|
||||
|
|
|
@ -230,47 +230,6 @@ class ChassisEvent(row_event.RowEvent):
|
|||
self.handle_ha_chassis_group_changes(event, row, old)
|
||||
|
||||
|
||||
class PortBindingChassisUpdateEvent(row_event.RowEvent):
|
||||
"""Event for matching a port moving chassis
|
||||
|
||||
If the LSP is up and the Port_Binding chassis has just changed,
|
||||
there is a good chance the host died without cleaning up the chassis
|
||||
column on the Port_Binding. The port never goes down, so we won't
|
||||
see update the driver with the LogicalSwitchPortUpdateUpEvent which
|
||||
only monitors for transitions from DOWN to UP.
|
||||
"""
|
||||
|
||||
def __init__(self, driver):
|
||||
self.driver = driver
|
||||
table = 'Port_Binding'
|
||||
events = (self.ROW_UPDATE,)
|
||||
super(PortBindingChassisUpdateEvent, self).__init__(
|
||||
events, table, None)
|
||||
self.event_name = self.__class__.__name__
|
||||
|
||||
def match_fn(self, event, row, old=None):
|
||||
# NOTE(twilson) ROW_UPDATE events always pass old, but chassis will
|
||||
# only be set if chassis has changed
|
||||
old_chassis = getattr(old, 'chassis', None)
|
||||
if not (row.chassis and old_chassis) or row.chassis == old_chassis:
|
||||
return False
|
||||
if row.type == ovn_const.OVN_CHASSIS_REDIRECT:
|
||||
return False
|
||||
try:
|
||||
lsp = self.driver.nb_ovn.lookup('Logical_Switch_Port',
|
||||
row.logical_port)
|
||||
except idlutils.RowNotFound:
|
||||
LOG.warning("Logical Switch Port %(port)s not found for "
|
||||
"Port_Binding %(binding)s",
|
||||
{'port': row.logical_port, 'binding': row.uuid})
|
||||
return False
|
||||
|
||||
return bool(lsp.up)
|
||||
|
||||
def run(self, event, row, old=None):
|
||||
self.driver.set_port_status_up(row.logical_port)
|
||||
|
||||
|
||||
class ChassisAgentEvent(BaseEvent):
|
||||
GLOBAL = True
|
||||
|
||||
|
@ -418,8 +377,8 @@ class PortBindingChassisEvent(row_event.RowEvent):
|
|||
router, host)
|
||||
|
||||
|
||||
class LogicalSwitchPortCreateUpEvent(row_event.RowEvent):
|
||||
"""Row create event - Logical_Switch_Port 'up' = True.
|
||||
class PortBindingCreateUpEvent(row_event.RowEvent):
|
||||
"""Row create event - Port_Binding 'up' = True.
|
||||
|
||||
On connection, we get a dump of all ports, so if there is a neutron
|
||||
port that is down that has since been activated, we'll catch it here.
|
||||
|
@ -428,73 +387,165 @@ class LogicalSwitchPortCreateUpEvent(row_event.RowEvent):
|
|||
|
||||
def __init__(self, driver):
|
||||
self.driver = driver
|
||||
table = 'Logical_Switch_Port'
|
||||
table = 'Port_Binding'
|
||||
events = (self.ROW_CREATE,)
|
||||
super(LogicalSwitchPortCreateUpEvent, self).__init__(
|
||||
events, table, (('up', '=', True),))
|
||||
self.event_name = 'LogicalSwitchPortCreateUpEvent'
|
||||
super().__init__(events, table, None)
|
||||
self.event_name = 'PortBindingCreateUpEvent'
|
||||
|
||||
def match_fn(self, event, row, old):
|
||||
if row.type == ovn_const.PB_TYPE_VIRTUAL:
|
||||
# NOTE(ltomasbo): Skipping as virtual ports are not being set to
|
||||
# ACTIVE
|
||||
return False
|
||||
elif row.type == ovn_const.PB_TYPE_PATCH:
|
||||
# NOTE(ltomasbo): Only handle the logical_switch_port side,
|
||||
# not the router side.
|
||||
if (row.logical_port.startswith('lrp-') or
|
||||
row.logical_port.startswith('cr-lrp')):
|
||||
return False
|
||||
return True
|
||||
# TODO(ltomasbo): Remove the checkings for 'up' column once minimal
|
||||
# ovn version has it (v21.03.0). The match_fn can be then replaced
|
||||
# by different init method above:
|
||||
# super().__init__(
|
||||
# events, table, (('up', '=', True), ('type', '=', ''),))
|
||||
if hasattr(row, 'up'):
|
||||
return bool(row.up[0])
|
||||
elif row.chassis:
|
||||
return True
|
||||
return False
|
||||
|
||||
def run(self, event, row, old):
|
||||
self.driver.set_port_status_up(row.name)
|
||||
self.driver.set_port_status_up(row.logical_port)
|
||||
|
||||
|
||||
class LogicalSwitchPortCreateDownEvent(row_event.RowEvent):
|
||||
"""Row create event - Logical_Switch_Port 'up' = False
|
||||
class PortBindingCreateDownEvent(row_event.RowEvent):
|
||||
"""Row create event - Port_Binding 'up' = False
|
||||
|
||||
On connection, we get a dump of all ports, so if there is a neutron
|
||||
port that is up that has since been deactivated, we'll catch it here.
|
||||
This event will not be generated for new ports getting created.
|
||||
"""
|
||||
|
||||
def __init__(self, driver):
|
||||
self.driver = driver
|
||||
table = 'Logical_Switch_Port'
|
||||
table = 'Port_Binding'
|
||||
events = (self.ROW_CREATE,)
|
||||
super(LogicalSwitchPortCreateDownEvent, self).__init__(
|
||||
events, table, (('up', '=', False),))
|
||||
self.event_name = 'LogicalSwitchPortCreateDownEvent'
|
||||
super().__init__(events, table, None)
|
||||
self.event_name = 'PortBindingCreateDownEvent'
|
||||
|
||||
def match_fn(self, event, row, old):
|
||||
if row.type in [ovn_const.PB_TYPE_VIRTUAL, ovn_const.PB_TYPE_PATCH]:
|
||||
# NOTE(ltomasbo): Skipping as virtual ports are not being set to
|
||||
# ACTIVE
|
||||
# Patch ports are set to UP on creation, no need to update
|
||||
return False
|
||||
|
||||
# TODO(ltomasbo): Remove the checkings for 'up' column once minimal
|
||||
# ovn version has it (v21.03.0). The match_fn can be then replaced
|
||||
# by different init method above:
|
||||
# super().__init__(
|
||||
# events, table, (('up', '=', False), ('type', '=', ''),))
|
||||
if hasattr(row, 'up'):
|
||||
return not bool(row.up[0])
|
||||
elif not row.chassis:
|
||||
return True
|
||||
return False
|
||||
|
||||
def run(self, event, row, old):
|
||||
self.driver.set_port_status_down(row.name)
|
||||
self.driver.set_port_status_down(row.logical_port)
|
||||
|
||||
|
||||
class LogicalSwitchPortUpdateUpEvent(row_event.RowEvent):
|
||||
"""Row update event - Logical_Switch_Port 'up' going from False to True
|
||||
class PortBindingUpdateUpEvent(row_event.RowEvent):
|
||||
"""Row update event - Port_Binding 'up' going from False to True
|
||||
|
||||
This happens when the VM goes up.
|
||||
New value of Logical_Switch_Port 'up' will be True and the old value will
|
||||
be False.
|
||||
New value of Port_Binding 'up' will be True and the old value will
|
||||
be False. Or if that column does not exists, the chassis will be set
|
||||
and the old chassis value will be empty.
|
||||
"""
|
||||
|
||||
def __init__(self, driver):
|
||||
self.driver = driver
|
||||
table = 'Logical_Switch_Port'
|
||||
table = 'Port_Binding'
|
||||
events = (self.ROW_UPDATE,)
|
||||
super(LogicalSwitchPortUpdateUpEvent, self).__init__(
|
||||
events, table, (('up', '=', True),),
|
||||
old_conditions=(('up', '=', False),))
|
||||
self.event_name = 'LogicalSwitchPortUpdateUpEvent'
|
||||
super().__init__(events, table, None)
|
||||
self.event_name = 'PortBindingUpdateUpEvent'
|
||||
|
||||
def match_fn(self, event, row, old):
|
||||
if row.type == ovn_const.PB_TYPE_VIRTUAL:
|
||||
# NOTE(ltomasbo): Skipping as virtual ports are not being set to
|
||||
# ACTIVE
|
||||
return False
|
||||
elif row.type == ovn_const.PB_TYPE_PATCH:
|
||||
# NOTE(ltomasbo): Only handle the logical_switch_port side,
|
||||
# not the router side.
|
||||
if (row.logical_port.startswith('lrp-') or
|
||||
row.logical_port.startswith('cr-lrp')):
|
||||
return False
|
||||
return True
|
||||
# TODO(ltomasbo): Remove the checkings for 'up' column once minimal
|
||||
# ovn version has it (v21.03.0). The match_fn can be then replaced
|
||||
# by different init method above:
|
||||
# super().__init__(
|
||||
# events, table, (('up', '=', True), ('type', '=', '')),
|
||||
# old_conditions=(('up', '=', False),))
|
||||
try:
|
||||
if hasattr(row, 'up'):
|
||||
return (bool(row.up[0]) and not bool(old.up[0]))
|
||||
elif row.chassis and not old.chassis:
|
||||
return True
|
||||
except AttributeError:
|
||||
# NOTE(ltomasbo): do not process if there is no old up/chassis
|
||||
# information
|
||||
return False
|
||||
return False
|
||||
|
||||
def run(self, event, row, old):
|
||||
self.driver.set_port_status_up(row.name)
|
||||
self.driver.set_port_status_up(row.logical_port)
|
||||
|
||||
|
||||
class LogicalSwitchPortUpdateDownEvent(row_event.RowEvent):
|
||||
"""Row update event - Logical_Switch_Port 'up' going from True to False
|
||||
class PortBindingUpdateDownEvent(row_event.RowEvent):
|
||||
"""Row update event - Port_Binding 'up' going from True to False
|
||||
|
||||
This happens when the VM goes down.
|
||||
New value of Logical_Switch_Port 'up' will be False and the old value will
|
||||
be True.
|
||||
New value of Port_Binding 'up' will be False and the old value will
|
||||
be True. Or if that column does not exists, the chassis will be unset
|
||||
and the old chassis will be set.
|
||||
"""
|
||||
|
||||
def __init__(self, driver):
|
||||
self.driver = driver
|
||||
table = 'Logical_Switch_Port'
|
||||
table = 'Port_Binding'
|
||||
events = (self.ROW_UPDATE,)
|
||||
super(LogicalSwitchPortUpdateDownEvent, self).__init__(
|
||||
events, table, (('up', '=', False),),
|
||||
old_conditions=(('up', '=', True),))
|
||||
self.event_name = 'LogicalSwitchPortUpdateDownEvent'
|
||||
super().__init__(events, table, None)
|
||||
self.event_name = 'PortBindingUpdateDownEvent'
|
||||
|
||||
def match_fn(self, event, row, old):
|
||||
if row.type in [ovn_const.PB_TYPE_VIRTUAL, ovn_const.PB_TYPE_PATCH]:
|
||||
# NOTE(ltomasbo): Skipping as virtual ports are not being set to
|
||||
# ACTIVE
|
||||
# Patch ports are set to UP on creation, no need to update
|
||||
return False
|
||||
# TODO(ltomasbo): Remove the checkings for 'up' column once minimal
|
||||
# ovn version has it (v21.03.0). The match_fn can be then replaced
|
||||
# by different init method above:
|
||||
# super().__init__(
|
||||
# events, table, (('up', '=', False), ('type', '=', '')),
|
||||
# old_conditions=(('up', '=', True),))
|
||||
try:
|
||||
if hasattr(row, 'up'):
|
||||
return (not bool(row.up[0]) and bool(old.up[0]))
|
||||
elif not row.chassis and old.chassis:
|
||||
return True
|
||||
except AttributeError:
|
||||
# NOTE(ltomasbo): do not process if there is no old up/chassis
|
||||
# information
|
||||
return False
|
||||
return False
|
||||
|
||||
def run(self, event, row, old):
|
||||
self.driver.set_port_status_down(row.name)
|
||||
self.driver.set_port_status_down(row.logical_port)
|
||||
|
||||
|
||||
class FIPAddDeleteEvent(row_event.RowEvent):
|
||||
|
@ -684,17 +735,9 @@ class OvnNbIdl(OvnIdlDistributedLock):
|
|||
|
||||
def __init__(self, driver, remote, schema):
|
||||
super(OvnNbIdl, self).__init__(driver, remote, schema)
|
||||
self._lsp_update_up_event = LogicalSwitchPortUpdateUpEvent(driver)
|
||||
self._lsp_update_down_event = LogicalSwitchPortUpdateDownEvent(driver)
|
||||
self._lsp_create_up_event = LogicalSwitchPortCreateUpEvent(driver)
|
||||
self._lsp_create_down_event = LogicalSwitchPortCreateDownEvent(driver)
|
||||
self._fip_create_delete_event = FIPAddDeleteEvent(driver)
|
||||
|
||||
self.notify_handler.watch_events([self._lsp_create_up_event,
|
||||
self._lsp_create_down_event,
|
||||
self._lsp_update_up_event,
|
||||
self._lsp_update_down_event,
|
||||
self._fip_create_delete_event])
|
||||
self.notify_handler.watch_events([self._fip_create_delete_event])
|
||||
|
||||
@classmethod
|
||||
def from_server(cls, connection_string, helper, driver):
|
||||
|
@ -702,34 +745,25 @@ class OvnNbIdl(OvnIdlDistributedLock):
|
|||
helper.register_all()
|
||||
return cls(driver, connection_string, helper)
|
||||
|
||||
def unwatch_logical_switch_port_create_events(self):
|
||||
"""Unwatch the logical switch port create events.
|
||||
|
||||
When the ovs idl client connects to the ovsdb-server, it gets
|
||||
a dump of all logical switch ports as events and we need to process
|
||||
them at start up.
|
||||
After the startup, there is no need to watch these events.
|
||||
So unwatch these events.
|
||||
"""
|
||||
self.notify_handler.unwatch_events([self._lsp_create_up_event,
|
||||
self._lsp_create_down_event])
|
||||
self._lsp_create_up_event = None
|
||||
self._lsp_create_down_event = None
|
||||
|
||||
def post_connect(self):
|
||||
self.unwatch_logical_switch_port_create_events()
|
||||
|
||||
|
||||
class OvnSbIdl(OvnIdlDistributedLock):
|
||||
|
||||
def __init__(self, driver, remote, schema, **kwargs):
|
||||
super(OvnSbIdl, self).__init__(driver, remote, schema, **kwargs)
|
||||
|
||||
self._pb_create_up_event = PortBindingCreateUpEvent(driver)
|
||||
self._pb_create_down_event = PortBindingCreateDownEvent(driver)
|
||||
|
||||
self.notify_handler.watch_events([
|
||||
ChassisAgentDeleteEvent(self.driver),
|
||||
ChassisAgentDownEvent(self.driver),
|
||||
ChassisAgentWriteEvent(self.driver),
|
||||
ChassisAgentTypeChangeEvent(self.driver),
|
||||
ChassisMetadataAgentWriteEvent(self.driver)])
|
||||
ChassisMetadataAgentWriteEvent(self.driver),
|
||||
self._pb_create_up_event,
|
||||
self._pb_create_down_event,
|
||||
PortBindingUpdateUpEvent(driver),
|
||||
PortBindingUpdateDownEvent(driver)])
|
||||
|
||||
@classmethod
|
||||
def from_server(cls, connection_string, helper, driver):
|
||||
|
@ -760,8 +794,23 @@ class OvnSbIdl(OvnIdlDistributedLock):
|
|||
self._chassis_event = ChassisEvent(self.driver)
|
||||
self._portbinding_event = PortBindingChassisEvent(self.driver)
|
||||
self.notify_handler.watch_events(
|
||||
[self._chassis_event, self._portbinding_event,
|
||||
PortBindingChassisUpdateEvent(self.driver)])
|
||||
[self._chassis_event, self._portbinding_event])
|
||||
|
||||
self.unwatch_port_binding_create_events()
|
||||
|
||||
def unwatch_port_binding_create_events(self):
|
||||
"""Unwatch the port binding create events.
|
||||
|
||||
When the ovs idl client connects to the ovsdb-server, it gets
|
||||
a dump of all port binding events and we need to process
|
||||
them at start up.
|
||||
After the startup, there is no need to watch these events.
|
||||
So unwatch these events.
|
||||
"""
|
||||
self.notify_handler.unwatch_events([self._pb_create_up_event,
|
||||
self._pb_create_down_event])
|
||||
self._pb_create_up_event = None
|
||||
self._pb_create_down_event = None
|
||||
|
||||
|
||||
class OvnInitPGNbIdl(OvnIdl):
|
||||
|
|
|
@ -191,12 +191,18 @@ class TestNBDbMonitor(base.TestOVNFunctionalBase):
|
|||
lambda: not self._check_mac_binding_exists(macb_id),
|
||||
timeout=15, sleep=1)
|
||||
|
||||
def _get_port_uuid(self, port_id):
|
||||
sb_port = self.sb_api.db_find(
|
||||
'Port_Binding', ('logical_port', '=', port_id)).execute()[0]
|
||||
return sb_port['_uuid']
|
||||
|
||||
def _test_port_binding_and_status(self, port_id, action, status):
|
||||
# This function binds or unbinds port to chassis and
|
||||
# checks if port status matches with input status
|
||||
core_plugin = directory.get_plugin()
|
||||
self.sb_api.check_for_row_by_value_and_retry(
|
||||
'Port_Binding', 'logical_port', port_id)
|
||||
port_uuid = self._get_port_uuid(port_id)
|
||||
|
||||
def check_port_status(status):
|
||||
port = core_plugin.get_ports(
|
||||
|
@ -205,8 +211,12 @@ class TestNBDbMonitor(base.TestOVNFunctionalBase):
|
|||
if action == 'bind':
|
||||
self.sb_api.lsp_bind(port_id, self.chassis,
|
||||
may_exist=True).execute(check_error=True)
|
||||
self.sb_api.db_set('Port_Binding', port_uuid,
|
||||
('up', True)).execute(check_error=True)
|
||||
else:
|
||||
self.sb_api.lsp_unbind(port_id).execute(check_error=True)
|
||||
self.sb_api.db_set('Port_Binding', port_uuid,
|
||||
('up', False)).execute(check_error=True)
|
||||
n_utils.wait_until_true(lambda: check_port_status(status))
|
||||
|
||||
def test_port_up_down_events(self):
|
||||
|
|
|
@ -86,7 +86,18 @@ OVN_SB_SCHEMA = {
|
|||
"min": 0, "max": "unlimited"}}},
|
||||
"isRoot": True,
|
||||
"indexes": [["name"]]
|
||||
}
|
||||
},
|
||||
"Port_Binding": {
|
||||
"columns": {
|
||||
"logical_port": {"type": "string"},
|
||||
"type": {"type": "string"},
|
||||
"chassis": {"type": {"key": {"type": "uuid",
|
||||
"refTable": "Chassis",
|
||||
"refType": "weak"},
|
||||
"min": 0, "max": 1}},
|
||||
"up": {"type": {"key": "boolean", "min": 0, "max": 1}}},
|
||||
"indexes": [["logical_port"]],
|
||||
"isRoot": True},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,35 +352,6 @@ class TestOvnIdlDistributedLock(base.BaseTestCase):
|
|||
self.fake_driver.agent_chassis_table)
|
||||
|
||||
|
||||
class TestPortBindingChassisUpdateEvent(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestPortBindingChassisUpdateEvent, self).setUp()
|
||||
self.driver = mock.Mock()
|
||||
self.event = ovsdb_monitor.PortBindingChassisUpdateEvent(self.driver)
|
||||
|
||||
def _test_event(self, event, row, old):
|
||||
if self.event.matches(event, row, old):
|
||||
self.event.run(event, row, old)
|
||||
self.driver.set_port_status_up.assert_called()
|
||||
else:
|
||||
self.driver.set_port_status_up.assert_not_called()
|
||||
|
||||
def test_event_matches(self):
|
||||
# NOTE(twilson) This primarily tests implementation details. If a
|
||||
# scenario test is written that handles shutting down a compute
|
||||
# node uncleanly and performing a 'host-evacuate', this can be removed
|
||||
pbtable = fakes.FakeOvsdbTable.create_one_ovsdb_table(
|
||||
attrs={'name': 'Port_Binding'})
|
||||
ovsdb_row = fakes.FakeOvsdbRow.create_one_ovsdb_row
|
||||
self.driver.nb_ovn.lookup.return_value = ovsdb_row(attrs={'up': True})
|
||||
self._test_event(
|
||||
self.event.ROW_UPDATE,
|
||||
ovsdb_row(attrs={'_table': pbtable, 'chassis': 'one',
|
||||
'type': '_fake_', 'logical_port': 'foo'}),
|
||||
ovsdb_row(attrs={'_table': pbtable, 'chassis': 'two',
|
||||
'type': '_fake_'}))
|
||||
|
||||
|
||||
class TestOvnNbIdlNotifyHandler(test_mech_driver.OVNMechanismDriverTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -378,109 +360,8 @@ class TestOvnNbIdlNotifyHandler(test_mech_driver.OVNMechanismDriverTestCase):
|
|||
helper.register_all()
|
||||
self.idl = ovsdb_monitor.OvnNbIdl(self.driver, "remote", helper)
|
||||
self.lp_table = self.idl.tables.get('Logical_Switch_Port')
|
||||
self.driver.set_port_status_up = mock.Mock()
|
||||
self.driver.set_port_status_down = mock.Mock()
|
||||
mock.patch.object(self.idl, 'handle_db_schema_changes').start()
|
||||
|
||||
def _test_lsp_helper(self, event, new_row_json, old_row_json=None,
|
||||
table=None):
|
||||
row_uuid = uuidutils.generate_uuid()
|
||||
if not table:
|
||||
table = self.lp_table
|
||||
lp_row = ovs_idl.Row.from_json(self.idl, table,
|
||||
row_uuid, new_row_json)
|
||||
if old_row_json:
|
||||
old_row = ovs_idl.Row.from_json(self.idl, table,
|
||||
row_uuid, old_row_json)
|
||||
else:
|
||||
old_row = None
|
||||
self.idl.notify(event, lp_row, updates=old_row)
|
||||
# Add a STOP EVENT to the queue
|
||||
self.idl.notify_handler.shutdown()
|
||||
# Execute the notifications queued
|
||||
self.idl.notify_handler.notify_loop()
|
||||
|
||||
def test_lsp_up_create_event(self):
|
||||
row_data = {"up": True, "name": "foo-name"}
|
||||
self._test_lsp_helper('create', row_data)
|
||||
self.driver.set_port_status_up.assert_called_once_with("foo-name")
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_lsp_down_create_event(self):
|
||||
row_data = {"up": False, "name": "foo-name"}
|
||||
self._test_lsp_helper('create', row_data)
|
||||
self.driver.set_port_status_down.assert_called_once_with("foo-name")
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
|
||||
def test_lsp_up_not_set_event(self):
|
||||
row_data = {"up": ['set', []], "name": "foo-name"}
|
||||
self._test_lsp_helper('create', row_data)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_unwatch_logical_switch_port_create_events(self):
|
||||
self.idl.unwatch_logical_switch_port_create_events()
|
||||
row_data = {"up": True, "name": "foo-name"}
|
||||
self._test_lsp_helper('create', row_data)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
row_data["up"] = False
|
||||
self._test_lsp_helper('create', row_data)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_post_connect(self):
|
||||
self.idl.post_connect()
|
||||
self.assertIsNone(self.idl._lsp_create_up_event)
|
||||
self.assertIsNone(self.idl._lsp_create_down_event)
|
||||
|
||||
def test_lsp_up_update_event(self):
|
||||
new_row_json = {"up": True, "name": "foo-name"}
|
||||
old_row_json = {"up": False}
|
||||
self._test_lsp_helper('update', new_row_json,
|
||||
old_row_json=old_row_json)
|
||||
self.driver.set_port_status_up.assert_called_once_with("foo-name")
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_lsp_down_update_event(self):
|
||||
new_row_json = {"up": False, "name": "foo-name"}
|
||||
old_row_json = {"up": True}
|
||||
self._test_lsp_helper('update', new_row_json,
|
||||
old_row_json=old_row_json)
|
||||
self.driver.set_port_status_down.assert_called_once_with("foo-name")
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
|
||||
def test_lsp_up_update_event_no_old_data(self):
|
||||
new_row_json = {"up": True, "name": "foo-name"}
|
||||
self._test_lsp_helper('update', new_row_json,
|
||||
old_row_json=None)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_lsp_down_update_event_no_old_data(self):
|
||||
new_row_json = {"up": False, "name": "foo-name"}
|
||||
self._test_lsp_helper('update', new_row_json,
|
||||
old_row_json=None)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_lsp_other_column_update_event(self):
|
||||
new_row_json = {"up": False, "name": "foo-name",
|
||||
"addresses": ["10.0.0.2"]}
|
||||
old_row_json = {"addresses": ["10.0.0.3"]}
|
||||
self._test_lsp_helper('update', new_row_json,
|
||||
old_row_json=old_row_json)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_notify_other_table(self):
|
||||
new_row_json = {"name": "foo-name"}
|
||||
self._test_lsp_helper('create', new_row_json,
|
||||
table=self.idl.tables.get("Logical_Switch"))
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
@mock.patch.object(hash_ring_manager.HashRingManager, 'get_node')
|
||||
def test_notify_different_target_node(self, mock_get_node):
|
||||
mock_get_node.return_value = 'this-is-a-different-node'
|
||||
|
@ -501,11 +382,12 @@ class TestOvnSbIdlNotifyHandler(test_mech_driver.OVNMechanismDriverTestCase):
|
|||
super(TestOvnSbIdlNotifyHandler, self).setUp()
|
||||
sb_helper = ovs_idl.SchemaHelper(schema_json=OVN_SB_SCHEMA)
|
||||
sb_helper.register_table('Chassis')
|
||||
sb_helper.register_table('Port_Binding')
|
||||
self.driver.agent_chassis_table = 'Chassis'
|
||||
self.sb_idl = ovsdb_monitor.OvnSbIdl(self.driver, "remote", sb_helper)
|
||||
self.sb_idl.post_connect()
|
||||
self.chassis_table = self.sb_idl.tables.get('Chassis')
|
||||
self.driver.update_segment_host_mapping = mock.Mock()
|
||||
self.driver.set_port_status_up = mock.Mock()
|
||||
self.driver.set_port_status_down = mock.Mock()
|
||||
self.l3_plugin = directory.get_plugin(n_const.L3)
|
||||
self.l3_plugin.schedule_unhosted_gateways = mock.Mock()
|
||||
|
||||
|
@ -516,9 +398,8 @@ class TestOvnSbIdlNotifyHandler(test_mech_driver.OVNMechanismDriverTestCase):
|
|||
"fake-phynet1:fake-br1"]]]
|
||||
}
|
||||
|
||||
def _test_chassis_helper(self, event, new_row_json, old_row_json=None):
|
||||
def _test_helper(self, event, table, new_row_json, old_row_json=None):
|
||||
row_uuid = uuidutils.generate_uuid()
|
||||
table = self.chassis_table
|
||||
row = ovs_idl.Row.from_json(self.sb_idl, table, row_uuid, new_row_json)
|
||||
if old_row_json:
|
||||
old_row = ovs_idl.Row.from_json(self.sb_idl, table,
|
||||
|
@ -531,6 +412,14 @@ class TestOvnSbIdlNotifyHandler(test_mech_driver.OVNMechanismDriverTestCase):
|
|||
# Execute the notifications queued
|
||||
self.sb_idl.notify_handler.notify_loop()
|
||||
|
||||
def _test_chassis_helper(self, event, new_row_json, old_row_json=None,
|
||||
table=None):
|
||||
self.sb_idl.post_connect()
|
||||
self.chassis_table = self.sb_idl.tables.get('Chassis')
|
||||
if not table:
|
||||
table = self.chassis_table
|
||||
self._test_helper(event, table, new_row_json, old_row_json)
|
||||
|
||||
def test_chassis_create_event(self):
|
||||
self._test_chassis_helper('create', self.row_json)
|
||||
self.driver.update_segment_host_mapping.assert_called_once_with(
|
||||
|
@ -601,6 +490,119 @@ class TestOvnSbIdlNotifyHandler(test_mech_driver.OVNMechanismDriverTestCase):
|
|||
self.l3_plugin.schedule_unhosted_gateways.assert_not_called()
|
||||
mock_ha.assert_not_called()
|
||||
|
||||
def _test_port_binding_helper(self, event, new_row_json,
|
||||
old_row_json=None, table=None):
|
||||
self.port_binding_table = self.sb_idl.tables.get('Port_Binding')
|
||||
if not table:
|
||||
table = self.port_binding_table
|
||||
self._test_helper(event, table, new_row_json, old_row_json)
|
||||
|
||||
def test_port_binding_up_create_event(self):
|
||||
row_data = {"type": "", "up": True, "logical_port": "foo-name"}
|
||||
self._test_port_binding_helper('create', row_data)
|
||||
self.driver.set_port_status_up.assert_called_once_with("foo-name")
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_port_binding_create_patch_type_event(self):
|
||||
# Note(ltomasbo): This will behave the same for up = True|False
|
||||
# as the port needs to transition to up anyway
|
||||
row_data = {"type": "patch", "logical_port": "foo-name"}
|
||||
self._test_port_binding_helper('create', row_data)
|
||||
self.driver.set_port_status_up.assert_called_once_with("foo-name")
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
row_data = {"type": "patch", "logical_port": "lrp-foo-name"}
|
||||
self._test_port_binding_helper('create', row_data)
|
||||
self.assertEqual(1, self.driver.set_port_status_up.call_count)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_port_binding_up_create_virtual_type_event(self):
|
||||
row_data = {"type": "virtual", "up": True,
|
||||
"logical_port": "foo-name"}
|
||||
self._test_port_binding_helper('create', row_data)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_port_binding_down_create_event(self):
|
||||
row_data = {"type": "", "up": False, "logical_port": "foo-name"}
|
||||
self._test_port_binding_helper('create', row_data)
|
||||
self.driver.set_port_status_down.assert_called_once_with("foo-name")
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
|
||||
def test_port_binding_down_create_virtual_type_event(self):
|
||||
row_data = {"type": "virtual", "up": False,
|
||||
"logical_port": "foo-name"}
|
||||
self._test_port_binding_helper('create', row_data)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_port_binding_up_update_event(self):
|
||||
new_row_json = {"type": "", "up": True, "logical_port": "foo-name"}
|
||||
old_row_json = {"type": "", "up": False, "logical_port": "foo-name"}
|
||||
self._test_port_binding_helper('update', new_row_json,
|
||||
old_row_json=old_row_json)
|
||||
self.driver.set_port_status_up.assert_called_once_with("foo-name")
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_port_binding_down_update_event(self):
|
||||
new_row_json = {"type": "", "up": False, "logical_port": "foo-name"}
|
||||
old_row_json = {"type": "", "up": True, "logical_port": "foo-name"}
|
||||
self._test_port_binding_helper('update', new_row_json,
|
||||
old_row_json=old_row_json)
|
||||
self.driver.set_port_status_down.assert_called_once_with("foo-name")
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
|
||||
def test_port_binding_up_update_event_no_old_data(self):
|
||||
new_row_json = {"type": "", "up": True, "logical_port": "foo-name"}
|
||||
self._test_port_binding_helper('update', new_row_json,
|
||||
old_row_json=None)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_port_binding_down_update_event_no_old_data(self):
|
||||
new_row_json = {"type": "", "up": False, "logical_port": "foo-name"}
|
||||
self._test_port_binding_helper('update', new_row_json,
|
||||
old_row_json=None)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_port_binding_other_column_update_event(self):
|
||||
new_row_json = {"type": "", "up": True, "name": "foo-name",
|
||||
"addresses": ["10.0.0.2"]}
|
||||
old_row_json = {"type": "", "up": True, "name": "foo-name",
|
||||
"addresses": ["10.0.0.3"]}
|
||||
self._test_port_binding_helper('update', new_row_json,
|
||||
old_row_json=old_row_json)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_notify_other_table(self):
|
||||
new_row_json = {"type": "", "up": True, "logical_port": "foo-name"}
|
||||
self._test_port_binding_helper(
|
||||
'create', new_row_json,
|
||||
table=self.sb_idl.tables.get("Chassis"))
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_unwatch_port_binding_create_events(self):
|
||||
self.sb_idl.unwatch_port_binding_create_events()
|
||||
row_data = {"type": "", "up": True, "logical_port": "foo-name"}
|
||||
self._test_port_binding_helper('create', row_data)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
row_data["up"] = False
|
||||
self._test_port_binding_helper('create', row_data)
|
||||
self.assertFalse(self.driver.set_port_status_up.called)
|
||||
self.assertFalse(self.driver.set_port_status_down.called)
|
||||
|
||||
def test_post_connect(self):
|
||||
self.assertIsNotNone(self.sb_idl._pb_create_up_event)
|
||||
self.assertIsNotNone(self.sb_idl._pb_create_down_event)
|
||||
self.sb_idl.post_connect()
|
||||
self.assertIsNone(self.sb_idl._pb_create_up_event)
|
||||
self.assertIsNone(self.sb_idl._pb_create_down_event)
|
||||
|
||||
|
||||
class TestChassisEvent(base.BaseTestCase):
|
||||
|
||||
|
|
Loading…
Reference in New Issue