Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add intelligence to xcvrd to understand process restart and config reload #377

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 93 additions & 20 deletions sonic-xcvrd/tests/test_xcvrd.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ class TestXcvrdThreadException(object):
def test_CmisManagerTask_task_run_with_exception(self):
port_mapping = PortMapping()
stop_event = threading.Event()
cmis_manager = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
port_reinit_request_tbl = MagicMock()
cmis_manager = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event, port_reinit_request_tbl)
cmis_manager.wait_for_port_config_done = MagicMock(side_effect = NotImplementedError)
exception_received = None
trace = None
Expand Down Expand Up @@ -90,7 +91,8 @@ def test_SfpStateUpdateTask_task_run_with_exception(self):
port_mapping = PortMapping()
stop_event = threading.Event()
sfp_error_event = threading.Event()
sfp_state_update = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, stop_event, sfp_error_event)
port_reinit_request_tbl = MagicMock()
sfp_state_update = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, port_reinit_request_tbl, stop_event, sfp_error_event)
exception_received = None
trace = None
try:
Expand All @@ -106,6 +108,7 @@ def test_SfpStateUpdateTask_task_run_with_exception(self):
assert("sonic-xcvrd/xcvrd/xcvrd.py" in str(trace))
assert("subscribe_port_config_change" in str(trace))

@patch('xcvrd.xcvrd.DaemonXcvrd.subscribe_appl_proc_info_update', MagicMock(return_value = (None, None)))
@patch('xcvrd.xcvrd.SfpStateUpdateTask.is_alive', MagicMock(return_value = False))
@patch('xcvrd.xcvrd.DomInfoUpdateTask.is_alive', MagicMock(return_value = False))
@patch('xcvrd.xcvrd.CmisManagerTask.is_alive', MagicMock(return_value = False))
Expand All @@ -121,7 +124,7 @@ def test_SfpStateUpdateTask_task_run_with_exception(self):
def test_DaemonXcvrd_run_with_exception(self, mock_task_join1, mock_task_join2, mock_init, mock_os_kill):
mock_init.return_value = (PortMapping(), set())
xcvrd = DaemonXcvrd(SYSLOG_IDENTIFIER)
xcvrd.stop_event.wait = MagicMock()
xcvrd.stop_event.is_set = MagicMock(return_value = True)
xcvrd.run()

assert len(xcvrd.threads) == 3
Expand Down Expand Up @@ -401,7 +404,8 @@ def test_post_port_sfp_info_and_dom_thr_to_db_once(self):
stop_event = threading.Event()
xcvr_table_helper = XcvrTableHelper(DEFAULT_NAMESPACE)
sfp_error_event = threading.Event()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, stop_event, sfp_error_event)
port_reinit_request_tbl = MagicMock()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, port_reinit_request_tbl, stop_event, sfp_error_event)
task._post_port_sfp_info_and_dom_thr_to_db_once(port_mapping, xcvr_table_helper, stop_event)

@patch('xcvrd.xcvrd_utilities.port_mapping.PortMapping.logical_port_name_to_physical_port_list', MagicMock(return_value=[0]))
Expand All @@ -416,7 +420,8 @@ def test_init_port_sfp_status_tbl(self):
stop_event = threading.Event()
xcvr_table_helper = XcvrTableHelper(DEFAULT_NAMESPACE)
sfp_error_event = threading.Event()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, stop_event, sfp_error_event)
port_reinit_request_tbl = MagicMock()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, port_reinit_request_tbl, stop_event, sfp_error_event)
task._init_port_sfp_status_tbl(port_mapping, xcvr_table_helper, stop_event)

def test_get_media_settings_key(self):
Expand Down Expand Up @@ -575,6 +580,7 @@ def test_DaemonXcvrd_wait_for_port_config_done(self, mock_select, mock_sub_table
xcvrd.wait_for_port_config_done('')
assert swsscommon.Select.select.call_count == 2

@patch('xcvrd.xcvrd.DaemonXcvrd.subscribe_appl_proc_info_update', MagicMock(return_value = (None, None)))
@patch('xcvrd.xcvrd.DaemonXcvrd.init')
@patch('xcvrd.xcvrd.DaemonXcvrd.deinit')
@patch('xcvrd.xcvrd.DomInfoUpdateTask.start')
Expand All @@ -584,7 +590,7 @@ def test_DaemonXcvrd_wait_for_port_config_done(self, mock_select, mock_sub_table
def test_DaemonXcvrd_run(self, mock_task_stop1, mock_task_stop2, mock_task_run1, mock_task_run2, mock_deinit, mock_init):
mock_init.return_value = (PortMapping(), set())
xcvrd = DaemonXcvrd(SYSLOG_IDENTIFIER)
xcvrd.stop_event.wait = MagicMock()
xcvrd.stop_event.is_set = MagicMock(return_value=True)
xcvrd.run()
assert mock_task_stop1.call_count == 1
assert mock_task_stop2.call_count == 1
Expand All @@ -593,11 +599,42 @@ def test_DaemonXcvrd_run(self, mock_task_stop1, mock_task_stop2, mock_task_run1,
assert mock_deinit.call_count == 1
assert mock_init.call_count == 1

@patch('swsscommon.swsscommon.Select.addSelectable', MagicMock())
@patch('os.kill')
@patch('swsscommon.swsscommon.SubscriberStateTable')
@patch('swsscommon.swsscommon.Select.select')
@patch('xcvrd.xcvrd.DaemonXcvrd.init')
@patch('xcvrd.xcvrd.DaemonXcvrd.deinit')
@patch('xcvrd.xcvrd.DomInfoUpdateTask.start')
@patch('xcvrd.xcvrd.SfpStateUpdateTask.start')
@patch('xcvrd.xcvrd.DomInfoUpdateTask.join')
@patch('xcvrd.xcvrd.SfpStateUpdateTask.join')
def test_xcvrd_kill_with_proc_info_del_command(self, mock_task_stop1, mock_task_stop2, mock_task_run1, mock_task_run2, mock_deinit, mock_init, mock_select, mock_sub_table, mock_os_kill):
mock_init.return_value = (PortMapping())
mock_selectable = MagicMock()
mock_selectable.pop = MagicMock(
side_effect=[('XCVRD', swsscommon.DEL_COMMAND, None)])
mock_select.return_value = (swsscommon.Select.OBJECT, mock_selectable)
mock_sub_table.return_value = mock_selectable
xcvrd = DaemonXcvrd(SYSLOG_IDENTIFIER)
xcvrd.stop_event.is_set = MagicMock(return_value=False)

xcvrd.run()

assert mock_task_stop1.call_count == 1
assert mock_task_stop2.call_count == 1
assert mock_task_run1.call_count == 1
assert mock_task_run2.call_count == 1
assert mock_init.call_count == 1
assert mock_deinit.call_count == 1
assert mock_os_kill.call_count == 1

@patch('xcvrd.xcvrd._wrapper_get_sfp_type', MagicMock(return_value='QSFP_DD'))
def test_CmisManagerTask_handle_port_change_event(self):
port_mapping = PortMapping()
stop_event = threading.Event()
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
port_reinit_request_tbl = MagicMock()
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event, port_reinit_request_tbl)

assert not task.isPortConfigDone
port_change_event = PortChangeEvent('PortConfigDone', -1, 0, PortChangeEvent.PORT_SET)
Expand Down Expand Up @@ -625,7 +662,8 @@ def test_CmisManagerTask_handle_port_change_event(self):
def test_CmisManagerTask_get_configured_freq(self, mock_table_helper):
port_mapping = PortMapping()
stop_event = threading.Event()
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
port_reinit_request_tbl = MagicMock()
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event, port_reinit_request_tbl)
cfg_port_tbl = MagicMock()
cfg_port_tbl.get = MagicMock(return_value=(True, (('laser_freq', 193100),)))
mock_table_helper.get_cfg_port_tbl = MagicMock(return_value=cfg_port_tbl)
Expand All @@ -636,7 +674,8 @@ def test_CmisManagerTask_get_configured_freq(self, mock_table_helper):
def test_CmisManagerTask_get_configured_tx_power_from_db(self, mock_table_helper):
port_mapping = PortMapping()
stop_event = threading.Event()
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
port_reinit_request_tbl = MagicMock()
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event, port_reinit_request_tbl)
cfg_port_tbl = MagicMock()
cfg_port_tbl.get = MagicMock(return_value=(True, (('tx_power', -10),)))
mock_table_helper.get_cfg_port_tbl = MagicMock(return_value=cfg_port_tbl)
Expand All @@ -653,7 +692,8 @@ def test_CmisManagerTask_task_run_stop(self, mock_chassis):

port_mapping = PortMapping()
stop_event = threading.Event()
cmis_manager = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
port_reinit_request_tbl = MagicMock()
cmis_manager = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event, port_reinit_request_tbl)
cmis_manager.wait_for_port_config_done = MagicMock()
cmis_manager.start()
cmis_manager.join()
Expand Down Expand Up @@ -714,7 +754,8 @@ def get_application(lane):

port_mapping = PortMapping()
stop_event = threading.Event()
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
port_reinit_request_tbl = MagicMock()
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event, port_reinit_request_tbl)

assert task.is_cmis_application_update_required(mock_xcvr_api, app_new, host_lanes_mask) == expected

Expand Down Expand Up @@ -759,7 +800,8 @@ def get_host_lane_assignment_option_side_effect(app):
mock_xcvr_api.get_host_lane_assignment_option = MagicMock(side_effect=get_host_lane_assignment_option_side_effect)
port_mapping = PortMapping()
stop_event = threading.Event()
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
port_reinit_request_tbl = MagicMock()
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event, port_reinit_request_tbl)

appl = task.get_cmis_application_desired(mock_xcvr_api, host_lane_count, speed)
assert task.get_cmis_host_lanes_mask(mock_xcvr_api, appl, host_lane_count, subport) == expected
Expand Down Expand Up @@ -865,7 +907,8 @@ def test_CmisManagerTask_task_worker(self, mock_chassis):

port_mapping = PortMapping()
stop_event = threading.Event()
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
port_reinit_request_tbl = {'Ethernet0': True}
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event, port_reinit_request_tbl)

port_change_event = PortChangeEvent('PortConfigDone', -1, 0, PortChangeEvent.PORT_SET)
task.on_port_update_event(port_change_event)
Expand Down Expand Up @@ -996,7 +1039,8 @@ def test_SfpStateUpdateTask_handle_port_change_event(self, mock_update_status_hw
stop_event = threading.Event()
sfp_error_event = threading.Event()
port_mapping = PortMapping()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, stop_event, sfp_error_event)
port_reinit_request_tbl = MagicMock()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, port_reinit_request_tbl, stop_event, sfp_error_event)
task.xcvr_table_helper = XcvrTableHelper(DEFAULT_NAMESPACE)
task.xcvr_table_helper.get_status_tbl = mock_table_helper.get_status_tbl
task.xcvr_table_helper.get_intf_tbl = mock_table_helper.get_intf_tbl
Expand Down Expand Up @@ -1034,28 +1078,36 @@ def test_SfpStateUpdateTask_task_run_stop(self):
port_mapping = PortMapping()
stop_event = threading.Event()
sfp_error_event = threading.Event()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, stop_event, sfp_error_event)
port_reinit_request_tbl = MagicMock()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, port_reinit_request_tbl, stop_event, sfp_error_event)
task.start()
assert wait_until(5, 1, task.is_alive)
task.raise_exception()
task.join()
assert wait_until(5, 1, lambda: task.is_alive() is False)

@patch('xcvrd.xcvrd.XcvrTableHelper', MagicMock())
@patch('xcvrd.xcvrd.update_proc_info_xcvrd_to_db')
@patch('xcvrd.xcvrd.post_port_sfp_info_to_db')
def test_SfpStateUpdateTask_retry_eeprom_reading(self, mock_post_sfp_info):
def test_SfpStateUpdateTask_retry_eeprom_reading(self, mock_post_sfp_info, mock_update_proc_info_xcvrd_to_db):
mock_table = MagicMock()
mock_table.get = MagicMock(return_value=(False, None))

port_mapping = PortMapping()
port_mapping.get_asic_id_for_logical_port = MagicMock(return_value=0)
stop_event = threading.Event()
sfp_error_event = threading.Event()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, stop_event, sfp_error_event)
port_reinit_request_tbl = MagicMock()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, port_reinit_request_tbl, stop_event, sfp_error_event)
task.xcvr_table_helper = XcvrTableHelper(DEFAULT_NAMESPACE)
task.xcvr_table_helper.get_intf_tbl = MagicMock(return_value=mock_table)
task.xcvr_table_helper.get_dom_threshold_tbl = MagicMock(return_value=mock_table)
task.xcvr_table_helper.get_app_port_tbl = MagicMock(return_value=mock_table)
task.xcvr_table_helper.get_status_tbl = MagicMock(return_value=mock_table)
asic_to_unprocessed_logical_ports_dict = {0: ['Ethernet0']}
task.asic_to_unprocessed_logical_ports_dict = MagicMock()
task.asic_to_unprocessed_logical_ports_dict.__getitem__.side_effect = asic_to_unprocessed_logical_ports_dict.__getitem__

task.retry_eeprom_reading()
assert mock_post_sfp_info.call_count == 0

Expand All @@ -1072,13 +1124,15 @@ def test_SfpStateUpdateTask_retry_eeprom_reading(self, mock_post_sfp_info):
task.last_retry_eeprom_time = 0
mock_post_sfp_info.return_value = None
task.retry_eeprom_reading()
assert mock_update_proc_info_xcvrd_to_db.call_count == 1
assert 'Ethernet0' not in task.retry_eeprom_set

def test_SfpStateUpdateTask_mapping_event_from_change_event(self):
port_mapping = PortMapping()
stop_event = threading.Event()
sfp_error_event = threading.Event()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, stop_event, sfp_error_event)
port_reinit_request_tbl = MagicMock()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, port_reinit_request_tbl, stop_event, sfp_error_event)
port_dict = {}
assert task._mapping_event_from_change_event(False, port_dict) == SYSTEM_FAIL
assert port_dict[EVENT_ON_ALL_SFP] == SYSTEM_FAIL
Expand Down Expand Up @@ -1114,7 +1168,8 @@ def test_SfpStateUpdateTask_task_worker(self, mock_del_status_hw,
port_mapping = PortMapping()
stop_event = threading.Event()
sfp_error_event = threading.Event()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, stop_event, sfp_error_event)
port_reinit_request_tbl = MagicMock()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, port_reinit_request_tbl, stop_event, sfp_error_event)
task.xcvr_table_helper = XcvrTableHelper(DEFAULT_NAMESPACE)
mock_change_event.return_value = (True, {0: 0}, {})
mock_mapping_event.return_value = SYSTEM_NOT_READY
Expand Down Expand Up @@ -1224,7 +1279,8 @@ class MockTable:
port_mapping = PortMapping()
stop_event = threading.Event()
sfp_error_event = threading.Event()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, stop_event, sfp_error_event)
port_reinit_request_tbl = MagicMock()
task = SfpStateUpdateTask(DEFAULT_NAMESPACE, port_mapping, port_reinit_request_tbl, stop_event, sfp_error_event)
task.xcvr_table_helper = XcvrTableHelper(DEFAULT_NAMESPACE)
task.xcvr_table_helper.get_status_tbl = mock_table_helper.get_status_tbl
task.xcvr_table_helper.get_intf_tbl = mock_table_helper.get_intf_tbl
Expand Down Expand Up @@ -1490,6 +1546,7 @@ def test_get_media_val_str(self):
@patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', MagicMock(return_value=('/tmp', None)))
@patch('swsscommon.swsscommon.WarmStart', MagicMock())
@patch('xcvrd.xcvrd.DaemonXcvrd.wait_for_port_config_done', MagicMock())
@patch('xcvrd.xcvrd.init_appl_proc_info_tbl', MagicMock())
def test_DaemonXcvrd_init_deinit_fastboot_enabled(self):
xcvrd = DaemonXcvrd(SYSLOG_IDENTIFIER)
with patch("subprocess.check_output") as mock_run:
Expand All @@ -1498,6 +1555,22 @@ def test_DaemonXcvrd_init_deinit_fastboot_enabled(self):
xcvrd.init()
xcvrd.deinit()

@patch('sonic_py_common.multi_asic.get_asic_index_from_namespace', MagicMock(return_value=(0)))
def test_init_appl_proc_info_tbl(self):
class MockTable:
def get(self, key):
return [None, None]
def set(self, key, val):
pass

port_mapping = PortMapping()
port_change_event = PortChangeEvent('Ethernet0', 1, 0, PortChangeEvent.PORT_ADD)
port_mapping.handle_port_change_event(port_change_event)
xcvr_table_helper = XcvrTableHelper(DEFAULT_NAMESPACE)
xcvr_table_helper.get_appl_proc_info_tbl = MagicMock(return_value=MockTable())
port_reinit_request_tbl = init_appl_proc_info_tbl(DEFAULT_NAMESPACE, port_mapping, xcvr_table_helper)

assert port_reinit_request_tbl == dict({'Ethernet0' : True})

def wait_until(total_wait_time, interval, call_back, *args, **kwargs):
wait_time = 0
Expand Down
Loading