diff --git a/sonic-chassisd/scripts/chassisd b/sonic-chassisd/scripts/chassisd index 8e864574b19a..61697b17150e 100644 --- a/sonic-chassisd/scripts/chassisd +++ b/sonic-chassisd/scripts/chassisd @@ -24,7 +24,7 @@ try: from swsscommon import swsscommon from sonic_platform_base.module_base import ModuleBase except ImportError as e: - raise ImportError (str(e) + " - required module not found") + raise ImportError(str(e) + " - required module not found") # # Constants ==================================================================== @@ -59,13 +59,15 @@ INVALID_SLOT = ModuleBase.MODULE_INVALID_SLOT INVALID_MODULE_INDEX = -1 MODULE_ADMIN_DOWN = 0 -MODULE_ADMIN_UP = 1 +MODULE_ADMIN_UP = 1 # # Helper functions ============================================================= # # try get information from platform API and return a default value if caught NotImplementedError + + def try_get(callback, *args, **kwargs): """ Handy function to invoke the callback and catch NotImplementedError @@ -86,16 +88,18 @@ def try_get(callback, *args, **kwargs): # # Module Config Updater ======================================================== # + + class ModuleConfigUpdater(logger.Logger): def __init__(self, log_identifier, chassis): - """ - Constructor for ModuleConfigUpdater - :param chassis: Object representing a platform chassis - """ - super(ModuleConfigUpdater, self).__init__(log_identifier) + """ + Constructor for ModuleConfigUpdater + :param chassis: Object representing a platform chassis + """ + super(ModuleConfigUpdater, self).__init__(log_identifier) - self.chassis = chassis + self.chassis = chassis def deinit(self): """ @@ -108,8 +112,9 @@ class ModuleConfigUpdater(logger.Logger): not key.startswith(ModuleBase.MODULE_TYPE_LINE) and \ not key.startswith(ModuleBase.MODULE_TYPE_FABRIC): self.log_error("Incorrect module-name {}. Should start with {} or {} or {}".format(key, - ModuleBase.MODULE_TYPE_SUPERVISOR, ModuleBase.MODULE_TYPE_LINE, - ModuleBase.MODULE_TYPE_FABRIC)) + ModuleBase.MODULE_TYPE_SUPERVISOR, + ModuleBase.MODULE_TYPE_LINE, + ModuleBase.MODULE_TYPE_FABRIC)) return module_index = try_get(self.chassis.get_module_index, key, default=INVALID_MODULE_INDEX) @@ -121,32 +126,33 @@ class ModuleConfigUpdater(logger.Logger): if (admin_state == MODULE_ADMIN_DOWN) or (admin_state == MODULE_ADMIN_UP): # Setting the module to administratively up/down state - self.log_info("Changing module {} to admin {} state".format(key, - 'DOWN' if admin_state == MODULE_ADMIN_DOWN else 'UP')) + self.log_info("Changing module {} to admin {} state".format(key, 'DOWN' if admin_state == MODULE_ADMIN_DOWN else 'UP')) try_get(self.chassis.get_module(module_index).set_admin_state, admin_state, default=False) # # Module Updater ============================================================== # + + class ModuleUpdater(logger.Logger): def __init__(self, log_identifier, chassis): - """ - Constructor for ModuleUpdater - :param chassis: Object representing a platform chassis - """ - super(ModuleUpdater, self).__init__(log_identifier) - - self.chassis = chassis - self.num_modules = chassis.get_num_modules() - # Connect to STATE_DB and create chassis info tables - state_db = daemon_base.db_connect("STATE_DB") - self.chassis_table = swsscommon.Table(state_db, CHASSIS_INFO_TABLE) - self.module_table = swsscommon.Table(state_db, CHASSIS_MODULE_INFO_TABLE) - self.info_dict_keys = [CHASSIS_MODULE_INFO_NAME_FIELD, - CHASSIS_MODULE_INFO_DESC_FIELD, - CHASSIS_MODULE_INFO_SLOT_FIELD, - CHASSIS_MODULE_INFO_OPERSTATUS_FIELD] + """ + Constructor for ModuleUpdater + :param chassis: Object representing a platform chassis + """ + super(ModuleUpdater, self).__init__(log_identifier) + + self.chassis = chassis + self.num_modules = chassis.get_num_modules() + # Connect to STATE_DB and create chassis info tables + state_db = daemon_base.db_connect("STATE_DB") + self.chassis_table = swsscommon.Table(state_db, CHASSIS_INFO_TABLE) + self.module_table = swsscommon.Table(state_db, CHASSIS_MODULE_INFO_TABLE) + self.info_dict_keys = [CHASSIS_MODULE_INFO_NAME_FIELD, + CHASSIS_MODULE_INFO_DESC_FIELD, + CHASSIS_MODULE_INFO_SLOT_FIELD, + CHASSIS_MODULE_INFO_OPERSTATUS_FIELD] def deinit(self): """ @@ -182,12 +188,14 @@ class ModuleUpdater(logger.Logger): not key.startswith(ModuleBase.MODULE_TYPE_LINE) and \ not key.startswith(ModuleBase.MODULE_TYPE_FABRIC): self.log_error("Incorrect module-name {}. Should start with {} or {} or {}".format(key, - ModuleBase.MODULE_TYPE_SUPERVISOR, ModuleBase.MODULE_TYPE_LINE, - ModuleBase.MODULE_TYPE_FABRIC)) + ModuleBase.MODULE_TYPE_SUPERVISOR, + ModuleBase.MODULE_TYPE_LINE, + ModuleBase.MODULE_TYPE_FABRIC)) continue fvs = swsscommon.FieldValuePairs([(CHASSIS_MODULE_INFO_DESC_FIELD, module_info_dict[CHASSIS_MODULE_INFO_DESC_FIELD]), - (CHASSIS_MODULE_INFO_SLOT_FIELD, module_info_dict[CHASSIS_MODULE_INFO_SLOT_FIELD]), + (CHASSIS_MODULE_INFO_SLOT_FIELD, + module_info_dict[CHASSIS_MODULE_INFO_SLOT_FIELD]), (CHASSIS_MODULE_INFO_OPERSTATUS_FIELD, module_info_dict[CHASSIS_MODULE_INFO_OPERSTATUS_FIELD])]) self.module_table.set(key, fvs) @@ -200,7 +208,8 @@ class ModuleUpdater(logger.Logger): name = try_get(self.chassis.get_module(module_index).get_name) desc = try_get(self.chassis.get_module(module_index).get_description) slot = try_get(self.chassis.get_module(module_index).get_slot, default=INVALID_SLOT) - status = try_get(self.chassis.get_module(module_index).get_oper_status, default=ModuleBase.MODULE_STATUS_OFFLINE) + status = try_get(self.chassis.get_module(module_index).get_oper_status, + default=ModuleBase.MODULE_STATUS_OFFLINE) module_info_dict[CHASSIS_MODULE_INFO_NAME_FIELD] = name module_info_dict[CHASSIS_MODULE_INFO_DESC_FIELD] = str(desc) @@ -212,6 +221,8 @@ class ModuleUpdater(logger.Logger): # # Config Manager task ======================================================== # + + class ConfigManagerTask(ProcessTaskBase): def __init__(self): ProcessTaskBase.__init__(self) @@ -256,6 +267,7 @@ class ConfigManagerTask(ProcessTaskBase): # Daemon ======================================================================= # + class ChassisdDaemon(daemon_base.DaemonBase): def __init__(self, log_identifier): super(ChassisdDaemon, self).__init__(log_identifier) @@ -309,7 +321,7 @@ class ChassisdDaemon(daemon_base.DaemonBase): self.log_info("Start daemon main loop") while not self.stop.wait(CHASSIS_INFO_UPDATE_PERIOD_SECS): - self.module_updater.module_db_update() + self.module_updater.module_db_update() self.log_info("Stop daemon main loop") @@ -325,9 +337,11 @@ class ChassisdDaemon(daemon_base.DaemonBase): # Main ========================================================================= # + def main(): chassisd = ChassisdDaemon(SYSLOG_IDENTIFIER) chassisd.run() + if __name__ == '__main__': main() diff --git a/sonic-chassisd/setup.py b/sonic-chassisd/setup.py index fa415e597619..271c7a7942df 100644 --- a/sonic-chassisd/setup.py +++ b/sonic-chassisd/setup.py @@ -16,11 +16,11 @@ scripts=[ 'scripts/chassisd', ], - setup_requires= [ + setup_requires=[ 'pytest-runner', 'wheel' ], - tests_require = [ + tests_require=[ 'pytest', 'mock>=2.0.0', 'pytest-cov' diff --git a/sonic-chassisd/tests/mock_module_base.py b/sonic-chassisd/tests/mock_module_base.py index f49222980998..fcbe0ef58597 100644 --- a/sonic-chassisd/tests/mock_module_base.py +++ b/sonic-chassisd/tests/mock_module_base.py @@ -4,18 +4,18 @@ class ModuleBase(): # Possible card types for modular chassis MODULE_TYPE_SUPERVISOR = "SUPERVISOR" - MODULE_TYPE_LINE = "LINE-CARD" - MODULE_TYPE_FABRIC = "FABRIC-CARD" + MODULE_TYPE_LINE = "LINE-CARD" + MODULE_TYPE_FABRIC = "FABRIC-CARD" # Possible card status for modular chassis # Module state is Empty if no module is inserted in the slot - MODULE_STATUS_EMPTY = "Empty" + MODULE_STATUS_EMPTY = "Empty" # Module state if Offline if powered down. This is also the admin-down state. MODULE_STATUS_OFFLINE = "Offline" # Module state is Present when it is powered up, but not fully functional. MODULE_STATUS_PRESENT = "Present" # Module state is Present when it is powered up, but entered a fault state. # Module is not able to go Online. - MODULE_STATUS_FAULT = "Fault" + MODULE_STATUS_FAULT = "Fault" # Module state is Online when fully operational - MODULE_STATUS_ONLINE = "Online" + MODULE_STATUS_ONLINE = "Online" diff --git a/sonic-chassisd/tests/mock_platform.py b/sonic-chassisd/tests/mock_platform.py index a8350a2cdcd1..76ae4efbc1f7 100644 --- a/sonic-chassisd/tests/mock_platform.py +++ b/sonic-chassisd/tests/mock_platform.py @@ -52,6 +52,7 @@ def set_admin_state(self, up): def get_admin_state(self): return self.admin_state + class MockChassis: def __init__(self): self.module_list = [] diff --git a/sonic-chassisd/tests/mock_swsscommon.py b/sonic-chassisd/tests/mock_swsscommon.py index df8c052d596e..0ddd45e8d8d4 100644 --- a/sonic-chassisd/tests/mock_swsscommon.py +++ b/sonic-chassisd/tests/mock_swsscommon.py @@ -3,8 +3,8 @@ class Table: def __init__(self, db, table_name): - self.table_name = table_name - self.mock_dict = {} + self.table_name = table_name + self.mock_dict = {} def _del(self, key): del self.mock_dict[key] @@ -19,6 +19,7 @@ def get(self, key): return self.mock_dict[key] return None + class FieldValuePairs: def __init__(self, fvs): self.fv_dict = dict(fvs) diff --git a/sonic-chassisd/tests/test_chassisd.py b/sonic-chassisd/tests/test_chassisd.py index 19bffde95282..83eda91641b0 100644 --- a/sonic-chassisd/tests/test_chassisd.py +++ b/sonic-chassisd/tests/test_chassisd.py @@ -31,6 +31,7 @@ CHASSIS_INFO_KEY_TEMPLATE = 'CHASSIS {}' CHASSIS_INFO_CARD_NUM_FIELD = 'module_num' + def setup_function(): ModuleUpdater.log_notice = MagicMock() ModuleUpdater.log_warning = MagicMock() @@ -63,6 +64,7 @@ def test_moduleupdater_check_valid_fields(): assert slot == int(fvs[CHASSIS_MODULE_INFO_SLOT_FIELD]) assert status == fvs[CHASSIS_MODULE_INFO_OPERSTATUS_FIELD] + def test_moduleupdater_check_invalid_name(): chassis = MockChassis() index = 0 @@ -83,6 +85,7 @@ def test_moduleupdater_check_invalid_name(): fvs = module_updater.module_table.get(name) assert fvs == None + def test_moduleupdater_check_status_update(): chassis = MockChassis() index = 0 @@ -116,6 +119,7 @@ def test_moduleupdater_check_status_update(): print('Updated DB-entry {}'.format(fvs)) assert status == fvs[CHASSIS_MODULE_INFO_OPERSTATUS_FIELD] + def test_moduleupdater_check_deinit(): chassis = MockChassis() index = 0 @@ -141,6 +145,7 @@ def test_moduleupdater_check_deinit(): fvs = module_table.get(name) assert fvs == None + def test_configupdater_check_valid_names(): chassis = MockChassis() index = 0 @@ -162,6 +167,7 @@ def test_configupdater_check_valid_names(): # No change since invalid key assert module.get_admin_state() != admin_state + def test_configupdater_check_valid_index(): chassis = MockChassis() index = -1 @@ -183,6 +189,7 @@ def test_configupdater_check_valid_index(): # No change since invalid index assert module.get_admin_state() != admin_state + def test_configupdater_check_admin_state(): chassis = MockChassis() index = 0 @@ -206,6 +213,7 @@ def test_configupdater_check_admin_state(): config_updater.module_config_update(name, admin_state) assert module.get_admin_state() == admin_state + def test_configupdater_check_num_modules(): chassis = MockChassis() index = 0 diff --git a/sonic-ledd/scripts/ledd b/sonic-ledd/scripts/ledd index 342f73d85f08..445e47981fdc 100644 --- a/sonic-ledd/scripts/ledd +++ b/sonic-ledd/scripts/ledd @@ -14,7 +14,7 @@ try: from sonic_py_common.interface import backplane_prefix from swsscommon import swsscommon except ImportError as e: - raise ImportError (str(e) + " - required module not found") + raise ImportError(str(e) + " - required module not found") #============================= Constants ============================= @@ -22,7 +22,7 @@ VERSION = '1.0' SYSLOG_IDENTIFIER = "ledd" -USAGE_HELP=""" +USAGE_HELP = """ Usage: ledd [options] Options: @@ -37,6 +37,7 @@ SELECT_TIMEOUT = 1000 LEDUTIL_LOAD_ERROR = 1 + class DaemonLedd(daemon_base.DaemonBase): # Run daemon @@ -45,8 +46,8 @@ class DaemonLedd(daemon_base.DaemonBase): if (len(sys.argv) > 1): try: (options, remainder) = getopt.getopt(sys.argv[1:], - 'hv', - ['help', 'version']) + 'hv', + ['help', 'version']) except getopt.GetoptError as e: print(e) print(USAGE_HELP) @@ -118,9 +119,11 @@ class DaemonLedd(daemon_base.DaemonBase): return 1 + def main(): ledd = DaemonLedd(SYSLOG_IDENTIFIER) ledd.run() + if __name__ == '__main__': main() diff --git a/sonic-ledd/setup.py b/sonic-ledd/setup.py index b88d87d56689..4959d8031404 100644 --- a/sonic-ledd/setup.py +++ b/sonic-ledd/setup.py @@ -13,7 +13,7 @@ scripts=[ 'scripts/ledd', ], - setup_requires= [ + setup_requires=[ 'wheel' ], classifiers=[ diff --git a/sonic-pcied/scripts/pcied b/sonic-pcied/scripts/pcied index 31312dd4cf75..0b636673b7f5 100644 --- a/sonic-pcied/scripts/pcied +++ b/sonic-pcied/scripts/pcied @@ -141,5 +141,6 @@ def main(): pcied = DaemonPcied(SYSLOG_IDENTIFIER) pcied.run() + if __name__ == '__main__': main() diff --git a/sonic-pcied/setup.py b/sonic-pcied/setup.py index 8d6070056280..0d7d32118422 100644 --- a/sonic-pcied/setup.py +++ b/sonic-pcied/setup.py @@ -13,7 +13,7 @@ scripts=[ 'scripts/pcied', ], - setup_requires= [ + setup_requires=[ 'wheel' ], classifiers=[ diff --git a/sonic-psud/scripts/psud b/sonic-psud/scripts/psud index 722c3bbc6dd2..c2a6874cbe5f 100644 --- a/sonic-psud/scripts/psud +++ b/sonic-psud/scripts/psud @@ -23,7 +23,7 @@ try: else: from swsscommon import swsscommon except ImportError as e: - raise ImportError (str(e) + " - required module not found") + raise ImportError(str(e) + " - required module not found") # @@ -161,6 +161,8 @@ def log_on_status_changed(logger, normal_status, normal_log, abnormal_log): # # PSU Chassis Info ========================================================== # + + class PsuChassisInfo(logger.Logger): def __init__(self, log_identifier, chassis): @@ -183,11 +185,11 @@ class PsuChassisInfo(logger.Logger): total_module_consumed_power = 0.0 dict_index = 0 - total_entries_len = 2 #For total supplied and consumed + total_entries_len = 2 # For total supplied and consumed dict_len = self.chassis.get_num_psus() +\ - self.chassis.get_num_fan_drawers() +\ - self.chassis.get_num_modules() + \ - total_entries_len + self.chassis.get_num_fan_drawers() +\ + self.chassis.get_num_modules() + \ + total_entries_len fvs = swsscommon.FieldValuePairs(dict_len) @@ -228,11 +230,11 @@ class PsuChassisInfo(logger.Logger): fvs[dict_index] = (CHASSIS_INFO_POWER_CONSUMER_FIELD.format(name), str(module_power)) dict_index += 1 - #Record total supplied and consumed power + # Record total supplied and consumed power self.total_supplied_power = total_supplied_power self.total_consumed_power = total_fan_consumed_power + total_module_consumed_power - #Record in state DB in chassis table + # Record in state DB in chassis table fvs[dict_index] = (CHASSIS_INFO_TOTAL_POWER_SUPPLIED_FIELD, str(self.total_supplied_power)) fvs[dict_index + 1] = (CHASSIS_INFO_TOTAL_POWER_CONSUMED_FIELD, str(self.total_consumed_power)) chassis_tbl.set(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1), fvs) @@ -259,7 +261,7 @@ class PsuChassisInfo(logger.Logger): else: from sonic_platform.psu import Psu except ImportError as e: - raise ImportError (str(e) + " - required module not found") + raise ImportError(str(e) + " - required module not found") color = Psu.STATUS_LED_COLOR_GREEN if master_status else Psu.STATUS_LED_COLOR_RED Psu.set_status_master_led(color) @@ -268,6 +270,8 @@ class PsuChassisInfo(logger.Logger): # PSU status =================================================================== # + + class PsuStatus(object): def __init__(self, logger, psu): @@ -306,7 +310,7 @@ class PsuStatus(object): if not voltage or not high_threshold or not low_threshold: if self.voltage_good is not True: self.logger.log_warning('PSU voltage or high_threshold or low_threshold become unavailable, ' - 'voltage={}, high_threshold={}, low_threshold={}'.format(voltage, high_threshold, low_threshold)) + 'voltage={}, high_threshold={}, low_threshold={}'.format(voltage, high_threshold, low_threshold)) self.voltage_good = True return False @@ -321,7 +325,7 @@ class PsuStatus(object): if not temperature or not high_threshold: if self.temperature_good is not True: self.logger.log_warning('PSU temperature or high_threshold become unavailable, ' - 'temperature={}, high_threshold={}'.format(temperature, high_threshold)) + 'temperature={}, high_threshold={}'.format(temperature, high_threshold)) self.temperature_good = True return False @@ -397,7 +401,6 @@ class DaemonPsud(daemon_base.DaemonBase): fvs = swsscommon.FieldValuePairs([(CHASSIS_INFO_PSU_NUM_FIELD, str(psu_num))]) chassis_tbl.set(CHASSIS_INFO_KEY, fvs) - # Start main loop self.log_info("Start daemon main loop") @@ -433,7 +436,7 @@ class DaemonPsud(daemon_base.DaemonBase): self._update_single_psu_data(index + 1, psu, psu_tbl) except Exception as e: self.log_warning("Failed to update PSU data - {}".format(e)) - + def _update_single_psu_data(self, index, psu, psu_tbl): name = get_psu_key(index) presence = _wrapper_get_psus_presence(index) diff --git a/sonic-psud/setup.py b/sonic-psud/setup.py index 604c8e575cb6..7b572c36a8fa 100644 --- a/sonic-psud/setup.py +++ b/sonic-psud/setup.py @@ -16,11 +16,11 @@ scripts=[ 'scripts/psud', ], - setup_requires= [ + setup_requires=[ 'pytest-runner', 'wheel' ], - tests_require = [ + tests_require=[ 'pytest', 'mock>=2.0.0', 'pytest-cov' diff --git a/sonic-psud/tests/mock_device_base.py b/sonic-psud/tests/mock_device_base.py new file mode 100644 index 000000000000..2aa9b9349822 --- /dev/null +++ b/sonic-psud/tests/mock_device_base.py @@ -0,0 +1,11 @@ +class DeviceBase(): + # Device-types + DEVICE_TYPE_PSU = "PSU" + DEVICE_TYPE_FAN = "FAN" + DEVICE_TYPE_FANDRAWER = "FAN-DRAWER" + + # LED colors + STATUS_LED_COLOR_GREEN = "green" + STATUS_LED_COLOR_AMBER = "amber" + STATUS_LED_COLOR_RED = "red" + STATUS_LED_COLOR_OFF = "off" diff --git a/sonic-psud/tests/mock_platform.py b/sonic-psud/tests/mock_platform.py index 1f4e52fb04f9..a88a74370c68 100644 --- a/sonic-psud/tests/mock_platform.py +++ b/sonic-psud/tests/mock_platform.py @@ -1,3 +1,6 @@ +from .mock_device_base import DeviceBase + + class MockDevice: STATUS_LED_COLOR_GREEN = "green" STATUS_LED_COLOR_AMBER = "amber" @@ -25,6 +28,7 @@ def get_model(self): def get_serial(self): return self.serial + class MockPsu(MockDevice): psu_master_led_color = MockDevice.STATUS_LED_COLOR_OFF @@ -54,6 +58,7 @@ def set_status_master_led(cls, color): def get_status_master_led(cls): return cls.psu_master_led_color + class MockFanDrawer(MockDevice): def __init__(self, fan_drawer_presence, fan_drawer_status, fan_drawer_name): self.name = fan_drawer_name @@ -72,6 +77,7 @@ def set_maximum_consumed_power(self, consumed_power): def get_maximum_consumed_power(self): return self.max_consumed_power + class MockModule(MockDevice): def __init__(self, module_presence, module_status, module_name): self.name = module_name @@ -90,6 +96,7 @@ def set_maximum_consumed_power(self, consumed_power): def get_maximum_consumed_power(self): return self.max_consumed_power + class MockChassis: def __init__(self): diff --git a/sonic-psud/tests/mock_swsscommon.py b/sonic-psud/tests/mock_swsscommon.py index bd16d7f7eaa9..7ceabf43724d 100644 --- a/sonic-psud/tests/mock_swsscommon.py +++ b/sonic-psud/tests/mock_swsscommon.py @@ -3,8 +3,8 @@ class Table: def __init__(self, db, table_name): - self.table_name = table_name - self.mock_dict = {} + self.table_name = table_name + self.mock_dict = {} def _del(self, key): del self.mock_dict[key] @@ -19,6 +19,7 @@ def get(self, key): return self.mock_dict[key] return None + class FieldValuePairs(dict): def __init__(self, len): self.fv_dict = {} diff --git a/sonic-psud/tests/test_psud.py b/sonic-psud/tests/test_psud.py index 2000ef994ae9..841eebbee4d8 100644 --- a/sonic-psud/tests/test_psud.py +++ b/sonic-psud/tests/test_psud.py @@ -30,6 +30,7 @@ CHASSIS_INFO_TOTAL_POWER_SUPPLIED_FIELD = 'Total Supplied Power' CHASSIS_INFO_POWER_KEY_TEMPLATE = 'chassis_power_budget {}' + def setup_function(): PsuChassisInfo.log_notice = MagicMock() PsuChassisInfo.log_warning = MagicMock() @@ -39,7 +40,9 @@ def teardown_function(): PsuChassisInfo.log_notice.reset() PsuChassisInfo.log_warning.reset() -#Test cases to cover functionality in PsuChassisInfo class +# Test cases to cover functionality in PsuChassisInfo class + + def test_psuchassis_check_psu_supplied_power(): chassis = MockChassis() psu1 = MockPsu(True, True, "PSU 1") @@ -64,23 +67,24 @@ def test_psuchassis_check_psu_supplied_power(): chassis_info.run_power_budget(chassis_tbl) fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1)) - #Check if supplied power is recorded in DB + # Check if supplied power is recorded in DB assert total_power == float(fvs[CHASSIS_INFO_TOTAL_POWER_SUPPLIED_FIELD]) - #Check if psu1 is not present + # Check if psu1 is not present psu1.set_presence(False) total_power = psu2_power + psu3_power chassis_info.run_power_budget(chassis_tbl) fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1)) assert total_power == float(fvs[CHASSIS_INFO_TOTAL_POWER_SUPPLIED_FIELD]) - #Check if psu2 status is NOT_OK + # Check if psu2 status is NOT_OK psu2.set_status(False) total_power = psu3_power chassis_info.run_power_budget(chassis_tbl) fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1)) assert total_power == float(fvs[CHASSIS_INFO_TOTAL_POWER_SUPPLIED_FIELD]) + def test_psuchassis_check_consumed_power(): chassis = MockChassis() fan_drawer1 = MockFanDrawer(True, True, "FanDrawer 1") @@ -100,17 +104,17 @@ def test_psuchassis_check_consumed_power(): chassis_info.run_power_budget(chassis_tbl) fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1)) - #Check if supplied power is recorded in DB + # Check if supplied power is recorded in DB assert total_power == float(fvs[CHASSIS_INFO_TOTAL_POWER_CONSUMED_FIELD]) - #Check if fan_drawer1 present + # Check if fan_drawer1 present fan_drawer1.set_presence(False) total_power = module1_power chassis_info.run_power_budget(chassis_tbl) fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1)) assert total_power == float(fvs[CHASSIS_INFO_TOTAL_POWER_CONSUMED_FIELD]) - #Check if module1 present + # Check if module1 present fan_drawer1.set_presence(True) module1.set_presence(False) total_power = fan_drawer1_power @@ -118,6 +122,7 @@ def test_psuchassis_check_consumed_power(): fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1)) assert total_power == float(fvs[CHASSIS_INFO_TOTAL_POWER_CONSUMED_FIELD]) + def test_psuchassis_check_power_budget(): chassis = MockChassis() psu = MockPsu(True, True, "PSU 1") @@ -139,7 +144,7 @@ def test_psuchassis_check_power_budget(): chassis_tbl = swsscommon.Table(state_db, CHASSIS_INFO_TABLE) chassis_info = PsuChassisInfo(SYSLOG_IDENTIFIER, chassis) - #Check if supplied_power < consumed_power + # Check if supplied_power < consumed_power chassis_info.run_power_budget(chassis_tbl) if chassis_info.update_master_status(): chassis_info._set_psu_master_led(chassis_info.master_status_good) @@ -149,13 +154,13 @@ def test_psuchassis_check_power_budget(): assert chassis_info.master_status_good == False assert MockPsu.get_status_master_led() == MockPsu.STATUS_LED_COLOR_RED - #Add a PSU + # Add a PSU psu = MockPsu(True, True, "PSU 2") psu2_power = 800.0 psu.set_maximum_supplied_power(psu2_power) chassis.psu_list.append(psu) - #Check if supplied_power > consumed_power + # Check if supplied_power > consumed_power chassis_info.run_power_budget(chassis_tbl) if chassis_info.update_master_status(): chassis_info._set_psu_master_led(chassis_info.master_status_good) diff --git a/sonic-syseepromd/scripts/syseepromd b/sonic-syseepromd/scripts/syseepromd index 855186061233..ae7fbd09e982 100644 --- a/sonic-syseepromd/scripts/syseepromd +++ b/sonic-syseepromd/scripts/syseepromd @@ -16,7 +16,7 @@ try: from sonic_py_common import daemon_base from swsscommon import swsscommon except ImportError as e: - raise ImportError (str(e) + " - required module not found") + raise ImportError(str(e) + " - required module not found") PLATFORM_SPECIFIC_MODULE_NAME = 'eeprom' PLATFORM_SPECIFIC_CLASS_NAME = 'board' @@ -28,7 +28,7 @@ ERR_PLATFORM_NOT_SUPPORT = 1 ERR_FAILED_EEPROM = 2 ERR_FAILED_UPDATE_DB = 3 ERR_INVALID_PARAMETER = 4 -ERR_EEPROMUTIL_LOAD = 5 +ERR_EEPROMUTIL_LOAD = 5 EEPROM_TABLE_NAME = 'EEPROM_INFO' SYSLOG_IDENTIFIER = 'syseepromd' @@ -68,7 +68,7 @@ class DaemonSyseeprom(daemon_base.DaemonBase): def post_eeprom_to_db(self): eeprom = self._wrapper_read_eeprom() - if eeprom is None : + if eeprom is None: self.log_error("Failed to read eeprom") return ERR_FAILED_EEPROM @@ -121,7 +121,8 @@ class DaemonSyseeprom(daemon_base.DaemonBase): self.chassis = sonic_platform.platform.Platform().get_chassis() self.eeprom = self.chassis.get_eeprom() except Exception as e: - self.log_warning("Failed to load platform-specific eeprom from sonic_platform package due to {}".format(repr(e))) + self.log_warning( + "Failed to load platform-specific eeprom from sonic_platform package due to {}".format(repr(e))) # If we didn't successfully load the class from the sonic_platform package, try loading the old plugin if not self.eeprom: @@ -162,10 +163,11 @@ class DaemonSyseeprom(daemon_base.DaemonBase): # Main ========================================================================= # + def main(): syseepromd = DaemonSyseeprom(SYSLOG_IDENTIFIER) syseepromd.run() + if __name__ == '__main__': main() - diff --git a/sonic-syseepromd/setup.py b/sonic-syseepromd/setup.py index 5a8eb41f17ab..1f485b2fbca4 100644 --- a/sonic-syseepromd/setup.py +++ b/sonic-syseepromd/setup.py @@ -13,7 +13,7 @@ scripts=[ 'scripts/syseepromd', ], - setup_requires= [ + setup_requires=[ 'wheel' ], classifiers=[ diff --git a/sonic-thermalctld/scripts/thermalctld b/sonic-thermalctld/scripts/thermalctld index 2f448ddaa955..edadb90085d9 100644 --- a/sonic-thermalctld/scripts/thermalctld +++ b/sonic-thermalctld/scripts/thermalctld @@ -33,6 +33,8 @@ INVALID_SLOT = -1 # utility functions # try get information from platform API and return a default value if caught NotImplementedError + + def try_get(callback, default=NOT_AVAILABLE): """ Handy function to invoke the callback and catch NotImplementedError @@ -122,7 +124,7 @@ class FanStatus(logger.Logger): if current_status is True: self.log_warning('Fan speed or target_speed or tolerance become unavailable, ' - 'speed={}, target_speed={}, tolerance={}'.format(speed, target_speed, tolerance)) + 'speed={}, target_speed={}, tolerance={}'.format(speed, target_speed, tolerance)) return False return True @@ -172,10 +174,10 @@ class FanStatus(logger.Logger): :return: True if Fan works normal else False """ return self.presence and \ - self.status and \ - not self.under_speed and \ - not self.over_speed and \ - not self.invalid_direction + self.status and \ + not self.under_speed and \ + not self.over_speed and \ + not self.invalid_direction # @@ -246,7 +248,7 @@ class FanUpdater(logger.Logger): self.log_warning('Failed to update PSU FAN status - {}'.format(repr(e))) self._update_led_color() - + bad_fan_count = FanStatus.get_bad_fan_count() if bad_fan_count > 0 and old_bad_fan_count != bad_fan_count: self.log_warning("Insufficient number of working fans warning: {} fans are not working.".format( @@ -455,7 +457,7 @@ class TemperatureStatus(logger.Logger): if temperature == NOT_AVAILABLE or threshold == NOT_AVAILABLE: if current_status is True: self.log_warning('Thermal temperature or threshold become unavailable, ' - 'temperature={}, threshold={}'.format(temperature, threshold)) + 'temperature={}, threshold={}'.format(temperature, threshold)) return False return True @@ -555,7 +557,7 @@ class TemperatureUpdater(logger.Logger): Update all temperature information to database :return: """ - self.log_debug("Start temperature updating") + self.log_debug("Start temperature updating") for index, thermal in enumerate(self.chassis.get_all_thermals()): try: self._refresh_temperature_status(CHASSIS_INFO_KEY, thermal, index) @@ -618,7 +620,7 @@ class TemperatureUpdater(logger.Logger): low_threshold = try_get(thermal.get_low_threshold) high_critical_threshold = try_get(thermal.get_high_critical_threshold) low_critical_threshold = try_get(thermal.get_low_critical_threshold) - + warning = False if temperature != NOT_AVAILABLE and temperature_status.set_over_temperature(temperature, high_threshold): self._log_on_status_changed(not temperature_status.over_temperature, @@ -724,7 +726,7 @@ class ThermalControlDaemon(daemon_base.DaemonBase): self.stop_event = threading.Event() # Thermal control daemon is designed to never exit, it must always - # return non zero exit code when exiting and so that supervisord will + # return non zero exit code when exiting and so that supervisord will # restart it automatically. self.exit_code = 1 diff --git a/sonic-thermalctld/setup.py b/sonic-thermalctld/setup.py index abf1c8deb2b6..426c7bb842ba 100644 --- a/sonic-thermalctld/setup.py +++ b/sonic-thermalctld/setup.py @@ -16,11 +16,11 @@ scripts=[ 'scripts/thermalctld', ], - setup_requires= [ + setup_requires=[ 'pytest-runner', 'wheel' ], - tests_require = [ + tests_require=[ 'pytest', 'mock>=2.0.0' ], diff --git a/sonic-thermalctld/tests/mock_platform.py b/sonic-thermalctld/tests/mock_platform.py index 223d0c64ebae..168de9754b0f 100644 --- a/sonic-thermalctld/tests/mock_platform.py +++ b/sonic-thermalctld/tests/mock_platform.py @@ -112,7 +112,7 @@ def set_status_led(self, value): class MockThermal(MockDevice): - def __init__(self, index = None): + def __init__(self, index=None): MockDevice.__init__(self) self.name = None self.name = 'Thermal {}'.format(index) if index != None else None @@ -168,7 +168,7 @@ class MockErrorThermal(MockThermal): def get_temperature(self): raise Exception('Fail to get temperature') - + class MockChassis: def __init__(self): self.fan_list = [] diff --git a/sonic-thermalctld/tests/mock_swsscommon.py b/sonic-thermalctld/tests/mock_swsscommon.py index 5907316f210c..c46c8a70a64d 100644 --- a/sonic-thermalctld/tests/mock_swsscommon.py +++ b/sonic-thermalctld/tests/mock_swsscommon.py @@ -1,10 +1,11 @@ STATE_DB = '' CHASSIS_STATE_DB = '' + class Table: def __init__(self, db, table_name): - self.table_name = table_name - self.mock_dict = {} + self.table_name = table_name + self.mock_dict = {} def _del(self, key): del self.mock_dict[key] @@ -22,6 +23,7 @@ def get(self, key): def get_size(self): return (len(self.mock_dict)) + class FieldValuePairs: def __init__(self, fvs): self.fv_dict = dict(fvs) diff --git a/sonic-thermalctld/tests/test_thermalctld.py b/sonic-thermalctld/tests/test_thermalctld.py index d3779fb09796..a9390cfc5f5a 100644 --- a/sonic-thermalctld/tests/test_thermalctld.py +++ b/sonic-thermalctld/tests/test_thermalctld.py @@ -24,6 +24,7 @@ TEMPER_INFO_TABLE_NAME = 'TEMPERATURE_INFO' + def setup_function(): FanStatus.log_notice = MagicMock() FanStatus.log_warning = MagicMock() @@ -189,11 +190,12 @@ def test_insufficient_fan_number(): fan_updater.update() assert fan_updater.log_notice.call_count == 1 fan_updater.log_warning.assert_called_with('Insufficient number of working fans warning: 1 fans are not working.') - + fan_list[1].status = True fan_updater.update() assert fan_updater.log_notice.call_count == 3 - fan_updater.log_notice.assert_called_with('Insufficient number of working fans warning cleared: all fans are back to normal.') + fan_updater.log_notice.assert_called_with( + 'Insufficient number of working fans warning cleared: all fans are back to normal.') def test_temperature_status_set_over_temper(): @@ -286,7 +288,9 @@ def test_update_thermal_with_exception(): temperature_updater.update() temperature_updater.log_warning.assert_called() -#Modular chassis related tests +# Modular chassis related tests + + def test_updater_thermal_check_modular_chassis(): chassis = MockChassis() assert chassis.is_modular_chassis() == False @@ -305,6 +309,7 @@ def test_updater_thermal_check_modular_chassis(): assert temperature_updater.chassis_table != None assert temperature_updater.chassis_table.table_name == TEMPER_INFO_TABLE_NAME+'_'+str(my_slot) + def test_updater_thermal_check_chassis_table(): chassis = MockChassis() @@ -326,6 +331,7 @@ def test_updater_thermal_check_chassis_table(): temperature_updater.deinit() assert temperature_updater.chassis_table.get_size() == 0 + def test_updater_thermal_check_min_max(): chassis = MockChassis() diff --git a/sonic-xcvrd/setup.py b/sonic-xcvrd/setup.py index 174504f79e8f..8ed5c38c2aca 100644 --- a/sonic-xcvrd/setup.py +++ b/sonic-xcvrd/setup.py @@ -1,30 +1,30 @@ from setuptools import setup, find_packages setup( - name = 'sonic-xcvrd', - version = '1.0', - description = 'Transceiver monitoring daemon for SONiC', - license = 'Apache 2.0', - author = 'SONiC Team', - author_email = 'linuxnetdev@microsoft.com', - url = 'https://github.com/Azure/sonic-platform-daemons', - maintainer = 'Kebo Liu', - maintainer_email = 'kebol@mellanox.com', - packages = find_packages(), - entry_points = { + name='sonic-xcvrd', + version='1.0', + description='Transceiver monitoring daemon for SONiC', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-platform-daemons', + maintainer='Kebo Liu', + maintainer_email='kebol@mellanox.com', + packages=find_packages(), + entry_points={ 'console_scripts': [ 'xcvrd = xcvrd.xcvrd:main', ] }, - install_requires = [ + install_requires=[ # NOTE: This package also requires swsscommon, but it is not currently installed as a wheel 'enum34; python_version < "3.4"', 'sonic-py-common', ], - setup_requires = [ + setup_requires=[ 'wheel' ], - classifiers = [ + classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: No Input/Output (Daemon)', 'Intended Audience :: Developers', @@ -37,5 +37,5 @@ 'Programming Language :: Python :: 3.7', 'Topic :: System :: Hardware', ], - keywords = 'sonic SONiC TRANSCEIVER transceiver daemon XCVRD xcvrd', + keywords='sonic SONiC TRANSCEIVER transceiver daemon XCVRD xcvrd', ) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 91cbd53f60f6..fa45779bc384 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -23,7 +23,7 @@ from .xcvrd_utilities import y_cable_helper except ImportError as e: - raise ImportError (str(e) + " - required module not found") + raise ImportError(str(e) + " - required module not found") # # Constants ==================================================================== @@ -49,9 +49,9 @@ SFP_STATUS_INSERTED = '1' # SFP error code enum, new elements can be added to the enum if new errors need to be supported. -SFP_STATUS_ERR_ENUM = Enum('SFP_STATUS_ERR_ENUM', ['SFP_STATUS_ERR_I2C_STUCK', 'SFP_STATUS_ERR_BAD_EEPROM', - 'SFP_STATUS_ERR_UNSUPPORTED_CABLE', 'SFP_STATUS_ERR_HIGH_TEMP', - 'SFP_STATUS_ERR_BAD_CABLE'], start=2) +SFP_STATUS_ERR_ENUM = Enum('SFP_STATUS_ERR_ENUM', ['SFP_STATUS_ERR_I2C_STUCK', 'SFP_STATUS_ERR_BAD_EEPROM', + 'SFP_STATUS_ERR_UNSUPPORTED_CABLE', 'SFP_STATUS_ERR_HIGH_TEMP', + 'SFP_STATUS_ERR_BAD_CABLE'], start=2) # Convert the error code to string and store them in a set for convenience errors_block_eeprom_reading = set(str(error_code.value) for error_code in SFP_STATUS_ERR_ENUM) @@ -73,7 +73,7 @@ SFPUTIL_LOAD_ERROR = 1 PORT_CONFIG_LOAD_ERROR = 2 NOT_IMPLEMENTED_ERROR = 3 -SFP_SYSTEM_ERROR = 4 +SFP_SYSTEM_ERROR = 4 RETRY_TIMES_FOR_SYSTEM_READY = 24 RETRY_PERIOD_FOR_SYSTEM_READY_MSECS = 5000 @@ -103,26 +103,32 @@ # # Find out the underneath physical port list by logical name + + def logical_port_name_to_physical_port_list(port_name): if port_name.startswith("Ethernet"): if platform_sfputil.is_logical_port(port_name): return platform_sfputil.get_logical_to_physical(port_name) else: - helper_logger.log_error("Invalid port '%s'" % port_name) + helper_logger.log_error("Invalid port '{}'".format(port_name)) return None else: return [int(port_name)] # Get physical port name + + def get_physical_port_name(logical_port, physical_port, ganged): if logical_port == physical_port: return logical_port elif ganged: - return logical_port + ":%d (ganged)" % physical_port + return logical_port + ":{} (ganged)".format(physical_port) else: return logical_port # Strip units and beautify + + def strip_unit_and_beautify(value, unit): # Strip unit from raw data if type(value) is str: @@ -133,6 +139,7 @@ def strip_unit_and_beautify(value, unit): else: return str(value) + def _wrapper_get_presence(physical_port): if platform_chassis is not None: try: @@ -141,6 +148,7 @@ def _wrapper_get_presence(physical_port): pass return platform_sfputil.get_presence(physical_port) + def _wrapper_is_replaceable(physical_port): if platform_chassis is not None: try: @@ -149,6 +157,7 @@ def _wrapper_is_replaceable(physical_port): pass return False + def _wrapper_get_transceiver_info(physical_port): if platform_chassis is not None: try: @@ -157,6 +166,7 @@ def _wrapper_get_transceiver_info(physical_port): pass return platform_sfputil.get_transceiver_info_dict(physical_port) + def _wrapper_get_transceiver_dom_info(physical_port): if platform_chassis is not None: try: @@ -165,6 +175,7 @@ def _wrapper_get_transceiver_dom_info(physical_port): pass return platform_sfputil.get_transceiver_dom_info_dict(physical_port) + def _wrapper_get_transceiver_dom_threshold_info(physical_port): if platform_chassis is not None: try: @@ -173,16 +184,18 @@ def _wrapper_get_transceiver_dom_threshold_info(physical_port): pass return platform_sfputil.get_transceiver_dom_threshold_info_dict(physical_port) + def _wrapper_get_transceiver_change_event(timeout): if platform_chassis is not None: try: - status, events = platform_chassis.get_change_event(timeout) + status, events = platform_chassis.get_change_event(timeout) sfp_events = events['sfp'] return status, sfp_events except NotImplementedError: pass return platform_sfputil.get_transceiver_change_event(timeout) + def _wrapper_get_sfp_type(physical_port): if platform_chassis: try: @@ -192,6 +205,8 @@ def _wrapper_get_sfp_type(physical_port): return None # Remove unnecessary unit from the raw data + + def beautify_dom_info_dict(dom_info_dict): dom_info_dict['temperature'] = strip_unit_and_beautify(dom_info_dict['temperature'], TEMP_UNIT) dom_info_dict['voltage'] = strip_unit_and_beautify(dom_info_dict['voltage'], VOLT_UNIT) @@ -208,6 +223,7 @@ def beautify_dom_info_dict(dom_info_dict): dom_info_dict['tx3power'] = strip_unit_and_beautify(dom_info_dict['tx3power'], POWER_UNIT) dom_info_dict['tx4power'] = strip_unit_and_beautify(dom_info_dict['tx4power'], POWER_UNIT) + def beautify_dom_threshold_info_dict(dom_info_dict): dom_info_dict['temphighalarm'] = strip_unit_and_beautify(dom_info_dict['temphighalarm'], TEMP_UNIT) dom_info_dict['temphighwarning'] = strip_unit_and_beautify(dom_info_dict['temphighwarning'], TEMP_UNIT) @@ -235,14 +251,16 @@ def beautify_dom_threshold_info_dict(dom_info_dict): dom_info_dict['txbiaslowwarning'] = strip_unit_and_beautify(dom_info_dict['txbiaslowwarning'], BIAS_UNIT) # Update port sfp info in db -def post_port_sfp_info_to_db(logical_port_name, table, transceiver_dict, + + +def post_port_sfp_info_to_db(logical_port_name, table, transceiver_dict, stop_event=threading.Event()): ganged_port = False ganged_member_num = 1 physical_port_list = logical_port_name_to_physical_port_list(logical_port_name) if physical_port_list is None: - helper_logger.log_error("No physical ports found for logical port '%s'" % logical_port_name) + helper_logger.log_error("No physical ports found for logical port '{}'".format(logical_port_name)) return PHYSICAL_PORT_NOT_EXIST if len(physical_port_list) > 1: @@ -262,25 +280,27 @@ def post_port_sfp_info_to_db(logical_port_name, table, transceiver_dict, port_info_dict = _wrapper_get_transceiver_info(physical_port) if port_info_dict is not None: is_replaceable = _wrapper_is_replaceable(physical_port) - transceiver_dict[physical_port]=port_info_dict - fvs = swsscommon.FieldValuePairs([('type', port_info_dict['type']), - ('hardware_rev', port_info_dict['hardware_rev']), - ('serial', port_info_dict['serial']), - ('manufacturer', port_info_dict['manufacturer']), - ('model', port_info_dict['model']), - ('vendor_oui',port_info_dict['vendor_oui']), - ('vendor_date',port_info_dict['vendor_date']), - ('connector',port_info_dict['connector']), - ('encoding',port_info_dict['encoding']), - ('ext_identifier',port_info_dict['ext_identifier']), - ('ext_rateselect_compliance',port_info_dict['ext_rateselect_compliance']), - ('cable_type',port_info_dict['cable_type']), - ('cable_length',port_info_dict['cable_length']), - ('specification_compliance',port_info_dict['specification_compliance']), - ('nominal_bit_rate',port_info_dict['nominal_bit_rate']), - ('application_advertisement',port_info_dict['application_advertisement'] if 'application_advertisement' in port_info_dict else 'N/A'), - ('is_replaceable',str(is_replaceable)), - ]) + transceiver_dict[physical_port] = port_info_dict + fvs = swsscommon.FieldValuePairs( + [('type', port_info_dict['type']), + ('hardware_rev', port_info_dict['hardware_rev']), + ('serial', port_info_dict['serial']), + ('manufacturer', port_info_dict['manufacturer']), + ('model', port_info_dict['model']), + ('vendor_oui', port_info_dict['vendor_oui']), + ('vendor_date', port_info_dict['vendor_date']), + ('connector', port_info_dict['connector']), + ('encoding', port_info_dict['encoding']), + ('ext_identifier', port_info_dict['ext_identifier']), + ('ext_rateselect_compliance', port_info_dict['ext_rateselect_compliance']), + ('cable_type', port_info_dict['cable_type']), + ('cable_length', port_info_dict['cable_length']), + ('specification_compliance', port_info_dict['specification_compliance']), + ('nominal_bit_rate', port_info_dict['nominal_bit_rate']), + ('application_advertisement', port_info_dict['application_advertisement'] + if 'application_advertisement' in port_info_dict else 'N/A'), + ('is_replaceable', str(is_replaceable)), + ]) table.set(port_name, fvs) else: return SFP_EEPROM_NOT_READY @@ -290,6 +310,8 @@ def post_port_sfp_info_to_db(logical_port_name, table, transceiver_dict, sys.exit(NOT_IMPLEMENTED_ERROR) # Update port dom threshold info in db + + def post_port_dom_threshold_info_to_db(logical_port_name, table, stop=threading.Event()): ganged_port = False @@ -297,8 +319,7 @@ def post_port_dom_threshold_info_to_db(logical_port_name, table, physical_port_list = logical_port_name_to_physical_port_list(logical_port_name) if physical_port_list is None: - helper_logger.log_error("No physical ports found for logical port '%s'" - % logical_port_name) + helper_logger.log_error("No physical ports found for logical port '{}'".format(logical_port_name)) return PHYSICAL_PORT_NOT_EXIST if len(physical_port_list) > 1: @@ -320,27 +341,27 @@ def post_port_dom_threshold_info_to_db(logical_port_name, table, if dom_info_dict is not None: beautify_dom_threshold_info_dict(dom_info_dict) fvs = swsscommon.FieldValuePairs( - [('temphighalarm', dom_info_dict['temphighalarm']), - ('temphighwarning', dom_info_dict['temphighwarning']), - ('templowalarm', dom_info_dict['templowalarm']), - ('templowwarning', dom_info_dict['templowwarning']), - ('vcchighalarm', dom_info_dict['vcchighalarm']), - ('vcchighwarning', dom_info_dict['vcchighwarning']), - ('vcclowalarm', dom_info_dict['vcclowalarm']), - ('vcclowwarning', dom_info_dict['vcclowwarning']), - ('txpowerhighalarm', dom_info_dict['txpowerhighalarm']), - ('txpowerlowalarm', dom_info_dict['txpowerlowalarm']), - ('txpowerhighwarning', dom_info_dict['txpowerhighwarning']), - ('txpowerlowwarning', dom_info_dict['txpowerlowwarning']), - ('rxpowerhighalarm', dom_info_dict['rxpowerhighalarm']), - ('rxpowerlowalarm', dom_info_dict['rxpowerlowalarm']), - ('rxpowerhighwarning', dom_info_dict['rxpowerhighwarning']), - ('rxpowerlowwarning', dom_info_dict['rxpowerlowwarning']), - ('txbiashighalarm', dom_info_dict['txbiashighalarm']), - ('txbiaslowalarm', dom_info_dict['txbiaslowalarm']), - ('txbiashighwarning', dom_info_dict['txbiashighwarning']), - ('txbiaslowwarning', dom_info_dict['txbiaslowwarning']) - ]) + [('temphighalarm', dom_info_dict['temphighalarm']), + ('temphighwarning', dom_info_dict['temphighwarning']), + ('templowalarm', dom_info_dict['templowalarm']), + ('templowwarning', dom_info_dict['templowwarning']), + ('vcchighalarm', dom_info_dict['vcchighalarm']), + ('vcchighwarning', dom_info_dict['vcchighwarning']), + ('vcclowalarm', dom_info_dict['vcclowalarm']), + ('vcclowwarning', dom_info_dict['vcclowwarning']), + ('txpowerhighalarm', dom_info_dict['txpowerhighalarm']), + ('txpowerlowalarm', dom_info_dict['txpowerlowalarm']), + ('txpowerhighwarning', dom_info_dict['txpowerhighwarning']), + ('txpowerlowwarning', dom_info_dict['txpowerlowwarning']), + ('rxpowerhighalarm', dom_info_dict['rxpowerhighalarm']), + ('rxpowerlowalarm', dom_info_dict['rxpowerlowalarm']), + ('rxpowerhighwarning', dom_info_dict['rxpowerhighwarning']), + ('rxpowerlowwarning', dom_info_dict['rxpowerlowwarning']), + ('txbiashighalarm', dom_info_dict['txbiashighalarm']), + ('txbiaslowalarm', dom_info_dict['txbiaslowalarm']), + ('txbiashighwarning', dom_info_dict['txbiashighwarning']), + ('txbiaslowwarning', dom_info_dict['txbiaslowwarning']) + ]) table.set(port_name, fvs) else: return SFP_EEPROM_NOT_READY @@ -350,13 +371,15 @@ def post_port_dom_threshold_info_to_db(logical_port_name, table, sys.exit(NOT_IMPLEMENTED_ERROR) # Update port dom sensor info in db + + def post_port_dom_info_to_db(logical_port_name, table, stop_event=threading.Event()): ganged_port = False ganged_member_num = 1 physical_port_list = logical_port_name_to_physical_port_list(logical_port_name) if physical_port_list is None: - helper_logger.log_error("No physical ports found for logical port '%s'" % logical_port_name) + helper_logger.log_error("No physical ports found for logical port '{}'".format(logical_port_name)) return PHYSICAL_PORT_NOT_EXIST if len(physical_port_list) > 1: @@ -404,24 +427,24 @@ def post_port_dom_info_to_db(logical_port_name, table, stop_event=threading.Even ('tx6power', dom_info_dict['tx6power']), ('tx7power', dom_info_dict['tx7power']), ('tx8power', dom_info_dict['tx8power']) - ]) + ]) else: fvs = swsscommon.FieldValuePairs( - [('temperature', dom_info_dict['temperature']), - ('voltage', dom_info_dict['voltage']), - ('rx1power', dom_info_dict['rx1power']), - ('rx2power', dom_info_dict['rx2power']), - ('rx3power', dom_info_dict['rx3power']), - ('rx4power', dom_info_dict['rx4power']), - ('tx1bias', dom_info_dict['tx1bias']), - ('tx2bias', dom_info_dict['tx2bias']), - ('tx3bias', dom_info_dict['tx3bias']), - ('tx4bias', dom_info_dict['tx4bias']), - ('tx1power', dom_info_dict['tx1power']), - ('tx2power', dom_info_dict['tx2power']), - ('tx3power', dom_info_dict['tx3power']), - ('tx4power', dom_info_dict['tx4power']) - ]) + [('temperature', dom_info_dict['temperature']), + ('voltage', dom_info_dict['voltage']), + ('rx1power', dom_info_dict['rx1power']), + ('rx2power', dom_info_dict['rx2power']), + ('rx3power', dom_info_dict['rx3power']), + ('rx4power', dom_info_dict['rx4power']), + ('tx1bias', dom_info_dict['tx1bias']), + ('tx2bias', dom_info_dict['tx2bias']), + ('tx3bias', dom_info_dict['tx3bias']), + ('tx4bias', dom_info_dict['tx4bias']), + ('tx1power', dom_info_dict['tx1power']), + ('tx2power', dom_info_dict['tx2power']), + ('tx3power', dom_info_dict['tx3power']), + ('tx4power', dom_info_dict['tx4power']) + ]) table.set(port_name, fvs) @@ -433,6 +456,8 @@ def post_port_dom_info_to_db(logical_port_name, table, stop_event=threading.Even sys.exit(NOT_IMPLEMENTED_ERROR) # Update port dom/sfp info in db + + def post_port_sfp_dom_info_to_db(is_warm_start, stop_event=threading.Event()): # Connect to STATE_DB and create transceiver dom/sfp info tables transceiver_dict, state_db, appl_db, int_tbl, dom_tbl, app_port_tbl = {}, {}, {}, {}, {}, {} @@ -462,19 +487,21 @@ def post_port_sfp_dom_info_to_db(is_warm_start, stop_event=threading.Event()): post_port_dom_info_to_db(logical_port_name, dom_tbl[asic_index], stop_event) post_port_dom_threshold_info_to_db(logical_port_name, dom_tbl[asic_index], stop_event) - ## Do not notify media settings during warm reboot to avoid dataplane traffic impact + # Do not notify media settings during warm reboot to avoid dataplane traffic impact if is_warm_start == False: notify_media_setting(logical_port_name, transceiver_dict, app_port_tbl[asic_index]) transceiver_dict.clear() # Delete port dom/sfp info from db + + def del_port_sfp_dom_info_from_db(logical_port_name, int_tbl, dom_tbl): ganged_port = False ganged_member_num = 1 physical_port_list = logical_port_name_to_physical_port_list(logical_port_name) if physical_port_list is None: - helper_logger.log_error("No physical ports found for logical port '%s'" % logical_port_name) + helper_logger.log_error("No physical ports found for logical port '{}'".format(logical_port_name)) return PHYSICAL_PORT_NOT_EXIST if len(physical_port_list) > 1: @@ -495,9 +522,11 @@ def del_port_sfp_dom_info_from_db(logical_port_name, int_tbl, dom_tbl): sys.exit(NOT_IMPLEMENTED_ERROR) # recover missing sfp table entries if any + + def recover_missing_sfp_table_entries(sfp_util, int_tbl, status_tbl, stop_event): transceiver_dict = {} - + logical_port_list = sfp_util.logical for logical_port_name in logical_port_list: if stop_event.is_set(): @@ -512,7 +541,7 @@ def recover_missing_sfp_table_entries(sfp_util, int_tbl, status_tbl, stop_event) keys = int_tbl[asic_index].getKeys() if logical_port_name not in keys and not detect_port_in_error_status(logical_port_name, status_tbl[asic_index]): post_port_sfp_info_to_db(logical_port_name, int_tbl[asic_index], transceiver_dict, stop_event) - + def check_port_in_range(range_str, physical_port): range_separator = '-' @@ -573,8 +602,7 @@ def get_media_settings_value(physical_port, key): if default_dict != 0: return default_dict else: - helper_logger.log_error("Error: No values for physical port '%d'" - % physical_port) + helper_logger.log_error("Error: No values for physical port '{}'".format(physical_port)) return {} if key[0] in media_dict: return media_dict[key[0]] @@ -587,9 +615,10 @@ def get_media_settings_value(physical_port, key): else: return {} else: - if default_dict != 0: + if default_dict != 0: return default_dict + def get_media_settings_key(physical_port, transceiver_dict): sup_compliance_str = '10/40G Ethernet Compliance Code' sup_len_str = 'Length Cable Assembly(m)' @@ -622,11 +651,12 @@ def get_media_settings_key(physical_port, transceiver_dict): return [vendor_key, media_key] + def get_media_val_str_from_dict(media_dict): media_str = '' lane_str = 'lane' lane_separator = ',' - tmp_dict={} + tmp_dict = {} for keys in media_dict: lane_num = int(keys.strip()[len(lane_str):]) @@ -638,6 +668,7 @@ def get_media_val_str_from_dict(media_dict): media_str += lane_separator return media_str + def get_media_val_str(num_logical_ports, lane_dict, logical_idx): lane_str = "lane" logical_media_dict = {} @@ -651,17 +682,18 @@ def get_media_val_str(num_logical_ports, lane_dict, logical_idx): num_lanes_per_logical_port = num_lanes_on_port/num_logical_ports start_lane = logical_idx * num_lanes_per_logical_port - for lane_idx in range(start_lane, start_lane + \ + for lane_idx in range(start_lane, start_lane + num_lanes_per_logical_port): - lane_idx_str = lane_str + str(lane_idx) - logical_lane_idx_str = lane_str + str(lane_idx - start_lane) - logical_media_dict[logical_lane_idx_str] = lane_dict[lane_idx_str] + lane_idx_str = lane_str + str(lane_idx) + logical_lane_idx_str = lane_str + str(lane_idx - start_lane) + logical_media_dict[logical_lane_idx_str] = lane_dict[lane_idx_str] media_val_str = get_media_val_str_from_dict(logical_media_dict) else: media_val_str = get_media_val_str_from_dict(lane_dict) return media_val_str + def notify_media_setting(logical_port_name, transceiver_dict, app_port_tbl): if len(media_settings) == 0: @@ -672,8 +704,7 @@ def notify_media_setting(logical_port_name, transceiver_dict, physical_port_list = logical_port_name_to_physical_port_list(logical_port_name) if physical_port_list is None: - helper_logger.log_error("Error: No physical ports found for " - "logical port '%s'" % logical_port_name) + helper_logger.log_error("Error: No physical ports found for logical port '{}'".format(logical_port_name)) return PHYSICAL_PORT_NOT_EXIST if len(physical_port_list) > 1: @@ -684,12 +715,10 @@ def notify_media_setting(logical_port_name, transceiver_dict, num_logical_ports = len(logical_port_list) logical_idx = logical_port_list.index(logical_port_name) if not _wrapper_get_presence(physical_port): - helper_logger.log_info("Media %d presence not detected during notify" - % physical_port) + helper_logger.log_info("Media {} presence not detected during notify".format(physical_port)) continue if physical_port not in transceiver_dict: - helper_logger.log_error("Media %d eeprom not populated in " - "transceiver dict" % physical_port) + helper_logger.log_error("Media {} eeprom not populated in transceiver dict".format(physical_port)) continue port_name = get_physical_port_name(logical_port_name, @@ -707,7 +736,7 @@ def notify_media_setting(logical_port_name, transceiver_dict, index = 0 for media_key in media_dict: if type(media_dict[media_key]) is dict: - media_val_str = get_media_val_str(num_logical_ports, \ + media_val_str = get_media_val_str(num_logical_ports, media_dict[media_key], logical_idx) else: @@ -725,19 +754,25 @@ def waiting_time_compensation_with_sleep(time_start, time_to_wait): time.sleep(time_to_wait - time_diff) # Update port SFP status table on receiving SFP change event + + def update_port_transceiver_status_table(logical_port_name, status_tbl, status): fvs = swsscommon.FieldValuePairs([('status', status)]) status_tbl.set(logical_port_name, fvs) # Delete port from SFP status table + + def delete_port_from_status_table(logical_port_name, status_tbl): status_tbl._del(logical_port_name) # Check whether port in error status + + def detect_port_in_error_status(logical_port_name, status_tbl): rec, fvp = status_tbl.get(logical_port_name) if rec: - status_dict = dict(fvp) + status_dict = dict(fvp) if status_dict['status'] in errors_block_eeprom_reading: return True else: @@ -746,6 +781,8 @@ def detect_port_in_error_status(logical_port_name, status_tbl): return False # Init TRANSCEIVER_STATUS table + + def init_port_sfp_status_tbl(stop_event=threading.Event()): # Connect to STATE_DB and create transceiver status table state_db, status_tbl = {}, {} @@ -771,7 +808,7 @@ def init_port_sfp_status_tbl(stop_event=threading.Event()): physical_port_list = logical_port_name_to_physical_port_list(logical_port_name) if physical_port_list is None: - helper_logger.log_error("No physical ports found for logical port '%s'" % logical_port_name) + helper_logger.log_error("No physical ports found for logical port '{}'".format(logical_port_name)) update_port_transceiver_status_table(logical_port_name, status_tbl[asic_index], SFP_STATUS_REMOVED) for physical_port in physical_port_list: @@ -788,6 +825,8 @@ def init_port_sfp_status_tbl(stop_event=threading.Event()): # # Thread wrapper class to update dom info periodically + + class DomInfoUpdateTask(object): def __init__(self): self.task_thread = None @@ -835,6 +874,8 @@ def task_stop(self): self.task_thread.join() # Process wrapper class to update sfp state info periodically + + class SfpStateUpdateTask(object): def __init__(self): self.task_process = None @@ -900,16 +941,16 @@ def task_worker(self, stopping_event, sfp_error_event, y_cable_presence): # - Initial state: INIT, before received system ready or a normal event # - Final state: EXIT # - other state: NORMAL, after has received system-ready or a normal event - + # events definition # - SYSTEM_NOT_READY # - SYSTEM_BECOME_READY - # - + # - # - NORMAL_EVENT # - sfp insertion/removal # - timeout returned by sfputil.get_change_event with status = true # - SYSTEM_FAIL - + # State transition: # 1. SYSTEM_NOT_READY # - INIT @@ -940,7 +981,6 @@ def task_worker(self, stopping_event, sfp_error_event, y_cable_presence): # - NORMAL # Treat as an error, transition to INIT - # State event next state # INIT SYSTEM NOT READY INIT / EXIT # INIT SYSTEM FAIL INIT / EXIT @@ -966,16 +1006,17 @@ def task_worker(self, stopping_event, sfp_error_event, y_cable_presence): if state == STATE_INIT: # system not ready, wait and retry if retry >= RETRY_TIMES_FOR_SYSTEM_READY: - helper_logger.log_error("System failed to get ready in {} secs or received system error. Exiting...".format((RETRY_PERIOD_FOR_SYSTEM_READY_MSECS/1000)*RETRY_TIMES_FOR_SYSTEM_READY)) + helper_logger.log_error("System failed to get ready in {} secs or received system error. Exiting...".format( + (RETRY_PERIOD_FOR_SYSTEM_READY_MSECS/1000)*RETRY_TIMES_FOR_SYSTEM_READY)) next_state = STATE_EXIT sfp_error_event.set() else: retry = retry + 1 - # get_transceiver_change_event may return immediately, - # we want the retry expired in expected time period, - # So need to calc the time diff, - # if time diff less that the pre-defined waiting time, + # get_transceiver_change_event may return immediately, + # we want the retry expired in expected time period, + # So need to calc the time diff, + # if time diff less that the pre-defined waiting time, # use sleep() to complete the time. time_now = time.time() time_diff = time_now - time_start @@ -1019,7 +1060,8 @@ def task_worker(self, stopping_event, sfp_error_event, y_cable_presence): if value == SFP_STATUS_INSERTED: helper_logger.log_info("Got SFP inserted event") # A plugin event will clear the error state. - update_port_transceiver_status_table(logical_port, status_tbl[asic_index], SFP_STATUS_INSERTED) + update_port_transceiver_status_table( + logical_port, status_tbl[asic_index], SFP_STATUS_INSERTED) helper_logger.log_info("receive plug in and update port sfp status table.") rc = post_port_sfp_info_to_db(logical_port, int_tbl[asic_index], transceiver_dict) # If we didn't get the sfp info, assuming the eeprom is not ready, give a try again. @@ -1033,7 +1075,8 @@ def task_worker(self, stopping_event, sfp_error_event, y_cable_presence): transceiver_dict.clear() elif value == SFP_STATUS_REMOVED: helper_logger.log_info("Got SFP removed event") - update_port_transceiver_status_table(logical_port, status_tbl[asic_index], SFP_STATUS_REMOVED) + update_port_transceiver_status_table( + logical_port, status_tbl[asic_index], SFP_STATUS_REMOVED) helper_logger.log_info("receive plug out and pdate port sfp status table.") del_port_sfp_dom_info_from_db(logical_port, int_tbl[asic_index], dom_tbl[asic_index]) elif value in errors_block_eeprom_reading: @@ -1054,21 +1097,23 @@ def task_worker(self, stopping_event, sfp_error_event, y_cable_presence): continue # Since ports could be connected to a mux cable, if there is a change event process the change for being on a Y cable Port - y_cable_helper.change_ports_status_for_y_cable_change_event(port_dict, y_cable_presence, stopping_event) + y_cable_helper.change_ports_status_for_y_cable_change_event( + port_dict, y_cable_presence, stopping_event) else: next_state = STATE_EXIT elif event == SYSTEM_FAIL: if state == STATE_INIT: # To overcome a case that system is only temporarily not available, - # when get system fail event will wait and retry for a certain period, + # when get system fail event will wait and retry for a certain period, # if system recovered in this period xcvrd will transit to INIT state # and continue run, if can not recover then exit. if retry >= RETRY_TIMES_FOR_SYSTEM_FAIL: - helper_logger.log_error("System failed to recover in {} secs. Exiting...".format((RETRY_PERIOD_FOR_SYSTEM_FAIL_MSECS/1000)*RETRY_TIMES_FOR_SYSTEM_FAIL)) + helper_logger.log_error("System failed to recover in {} secs. Exiting...".format( + (RETRY_PERIOD_FOR_SYSTEM_FAIL_MSECS/1000)*RETRY_TIMES_FOR_SYSTEM_FAIL)) next_state = STATE_EXIT sfp_error_event.set() else: - retry = retry + 1 + retry = retry + 1 waiting_time_compensation_with_sleep(time_start, RETRY_PERIOD_FOR_SYSTEM_FAIL_MSECS/1000) elif state == STATE_NORMAL: helper_logger.log_error("Got system_fail in normal state, treat as error, transition to INIT...") @@ -1096,7 +1141,8 @@ def task_run(self, sfp_error_event, y_cable_presence): if self.task_stopping_event.is_set(): return - self.task_process = multiprocessing.Process(target=self.task_worker,args=(self.task_stopping_event, sfp_error_event, y_cable_presence)) + self.task_process = multiprocessing.Process(target=self.task_worker, args=( + self.task_stopping_event, sfp_error_event, y_cable_presence)) self.task_process.start() def task_stop(self): @@ -1107,6 +1153,7 @@ def task_stop(self): # Daemon ======================================================================= # + class DaemonXcvrd(daemon_base.DaemonBase): def __init__(self, log_identifier): super(DaemonXcvrd, self).__init__(log_identifier) @@ -1179,7 +1226,7 @@ def init(self): import sonic_platform_base.sonic_sfp.sfputilhelper platform_chassis = sonic_platform.platform.Platform().get_chassis() self.log_info("chassis loaded {}".format(platform_chassis)) - # we have to make use of sfputil for some features + # we have to make use of sfputil for some features # even though when new platform api is used for all vendors. # in this sense, we treat it as a part of new platform api. # we have already moved sfputil to sonic_platform_base @@ -1193,7 +1240,7 @@ def init(self): try: platform_sfputil = self.load_platform_util(PLATFORM_SPECIFIC_MODULE_NAME, PLATFORM_SPECIFIC_CLASS_NAME) except Exception as e: - self.log_error("Failed to load sfputil: %s" % (str(e)), True) + self.log_error("Failed to load sfputil: {}".format(str(e)), True) sys.exit(SFPUTIL_LOAD_ERROR) if multi_asic.is_multi_asic(): @@ -1211,7 +1258,7 @@ def init(self): port_config_file_path = device_info.get_path_to_port_config_file() platform_sfputil.read_porttab_mappings(port_config_file_path, 0) except Exception as e: - self.log_error("Failed to read port info: %s" % (str(e)), True) + self.log_error("Failed to read port info: {}".format(str(e)), True) sys.exit(PORT_CONFIG_LOAD_ERROR) # Connect to STATE_DB and create transceiver dom/sfp info tables @@ -1246,7 +1293,8 @@ def init(self): init_port_sfp_status_tbl(self.stop_event) # Init port y_cable status table - y_cable_helper.init_ports_status_for_y_cable(platform_sfputil, platform_chassis, self.y_cable_presence, self.stop_event) + y_cable_helper.init_ports_status_for_y_cable( + platform_sfputil, platform_chassis, self.y_cable_presence, self.stop_event) # Deinitialize daemon def deinit(self): @@ -1267,8 +1315,8 @@ def deinit(self): if self.y_cable_presence[0] is True: y_cable_helper.delete_ports_status_for_y_cable() - # Run daemon + def run(self): self.log_info("Starting up...") @@ -1321,9 +1369,12 @@ def run(self): # # This is our main entry point for xcvrd script + + def main(): xcvrd = DaemonXcvrd(SYSLOG_IDENTIFIER) xcvrd.run() + if __name__ == '__main__': main() diff --git a/sonic-xcvrd/xcvrd/xcvrd_utilities/y_cable_helper.py b/sonic-xcvrd/xcvrd/xcvrd_utilities/y_cable_helper.py index bf3edacfb8e0..a50fbe25c03e 100644 --- a/sonic-xcvrd/xcvrd/xcvrd_utilities/y_cable_helper.py +++ b/sonic-xcvrd/xcvrd/xcvrd_utilities/y_cable_helper.py @@ -81,10 +81,12 @@ def _wrapper_get_presence(physical_port): def delete_port_from_y_cable_table(logical_port_name, y_cable_tbl): y_cable_tbl._del(logical_port_name) + # Delete port from Y cable status table def delete_port_from_y_cable_command_table(logical_port_name, y_cable_command_tbl): y_cable_command_tbl._del(logical_port_name) + def update_table_mux_status_for_response_tbl(table_name, status, logical_port_name): fvs = swsscommon.FieldValuePairs([('response', status)]) table_name.set(logical_port_name, fvs) @@ -589,7 +591,6 @@ def task_worker(self): fvp_dict = dict(fvp_m) if "command" in fvp_dict: - # check if xcvrd got a probe command probe_identifier = fvp_dict["command"]