From 7d7c85e1a394557c0eddc8f5b69fa82d9044c0b2 Mon Sep 17 00:00:00 2001 From: mprabhu-nokia <66807480+mprabhu-nokia@users.noreply.github.com> Date: Fri, 11 Feb 2022 08:08:26 +0530 Subject: [PATCH] Modular chassis: Psud set master led on first run (#206) On first run, the PSU master-led on supervisor of modular-chassis is not set. Description The PSU master-led on modular chassis indicates the power-buget status. Similar to individual PSU leds that are set on first_run, the master-led also will be set to based on initial status (RED or GREEN with LED status ON). Motivation and Context Without the forced setting of first_run, the master-led status will default to per vendor default. In some cases, this could be amber blinking etc --- sonic-psud/scripts/psud | 44 ++++++++++--------- sonic-psud/tests/test_PsuChassisInfo.py | 56 ++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/sonic-psud/scripts/psud b/sonic-psud/scripts/psud index 055aa065b06b..6ae24da4499d 100644 --- a/sonic-psud/scripts/psud +++ b/sonic-psud/scripts/psud @@ -175,6 +175,7 @@ class PsuChassisInfo(logger.Logger): super(PsuChassisInfo, self).__init__(log_identifier) self.chassis = chassis + self.first_run = True self.master_status_good = True self.total_consumed_power = 0.0 self.total_supplied_power = 0.0 @@ -242,30 +243,30 @@ class PsuChassisInfo(logger.Logger): chassis_tbl.set(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1), fvs) def update_master_status(self): - if not self.total_supplied_power or not self.total_consumed_power: - if self.master_status_good is not True: - self.master_status_good = True - return False - - master_status_good = (self.total_consumed_power < self.total_supplied_power) - if master_status_good == self.master_status_good: - return False + set_led = self.first_run + master_status_good = False - self.master_status_good = master_status_good + if self.total_supplied_power != 0.0 and self.total_consumed_power != 0.0: + master_status_good = (self.total_consumed_power < self.total_supplied_power) + if master_status_good != self.master_status_good: + set_led = True - # Update the PSU master status LED - # set_status_master_led() is a class method implemented in PsuBase - # so we do not need to catch NotImplementedError here - color = Psu.STATUS_LED_COLOR_GREEN if master_status_good else Psu.STATUS_LED_COLOR_RED - Psu.set_status_master_led(color) + self.master_status_good = master_status_good - log_on_status_changed(self, self.master_status_good, - 'PSU supplied power warning cleared: supplied power is back to normal.', - 'PSU supplied power warning: {}W supplied-power less than {}W consumed-power'.format( - self.total_supplied_power, self.total_consumed_power) - ) + if set_led: + # Update the PSU master status LED + # set_status_master_led() is a class method implemented in PsuBase + # so we do not need to catch NotImplementedError here + color = Psu.STATUS_LED_COLOR_GREEN if master_status_good else Psu.STATUS_LED_COLOR_RED + Psu.set_status_master_led(color) + + log_on_status_changed(self, self.master_status_good, + 'PSU supplied power warning cleared: supplied power is back to normal.', + 'PSU supplied power warning: {}W supplied-power less than {}W consumed-power'.format( + self.total_supplied_power, self.total_consumed_power) + ) - return True + return set_led # PSU status =================================================================== # @@ -605,6 +606,9 @@ class DaemonPsud(daemon_base.DaemonBase): self.psu_chassis_info.run_power_budget(self.chassis_tbl) self.psu_chassis_info.update_master_status() + if self.first_run: + self.first_run = False + # # Main ========================================================================= diff --git a/sonic-psud/tests/test_PsuChassisInfo.py b/sonic-psud/tests/test_PsuChassisInfo.py index 4231b497ec5e..f408362689b8 100644 --- a/sonic-psud/tests/test_PsuChassisInfo.py +++ b/sonic-psud/tests/test_PsuChassisInfo.py @@ -65,6 +65,7 @@ def test_update_master_status(self): chassis = MockChassis() chassis_info = psud.PsuChassisInfo(SYSLOG_IDENTIFIER, chassis) + # With first_run set as True # Test good values while in bad state chassis_info.total_supplied_power = 510.0 chassis_info.total_consumed_power = 350.0 @@ -75,13 +76,44 @@ def test_update_master_status(self): # Test good values while in good state ret = chassis_info.update_master_status() - assert ret == False + assert ret == True assert chassis_info.master_status_good == True # Test unknown total_supplied_power (0.0) chassis_info.total_supplied_power = 0.0 chassis_info.master_status_good = False ret = chassis_info.update_master_status() + assert ret == True + assert chassis_info.master_status_good == False + + # Test bad values while in good state + chassis_info.total_supplied_power = 300.0 + chassis_info.total_consumed_power = 350.0 + chassis_info.master_status_good = True + ret = chassis_info.update_master_status() + assert ret == True + assert chassis_info.master_status_good == False + + # With first_run set as False + chassis_info.first_run = False + + # Test good values while in bad state + chassis_info.total_supplied_power = 510.0 + chassis_info.total_consumed_power = 350.0 + chassis_info.master_status_good = False + ret = chassis_info.update_master_status() + assert ret == True + assert chassis_info.master_status_good == True + + # Test good values while in good state + ret = chassis_info.update_master_status() + assert ret == False + assert chassis_info.master_status_good == True + + # Test unknown total_supplied_power (0.0) + chassis_info.total_supplied_power = 0.0 + chassis_info.master_status_good = True + ret = chassis_info.update_master_status() assert ret == False assert chassis_info.master_status_good == True @@ -91,7 +123,7 @@ def test_update_master_status(self): chassis_info.master_status_good = False ret = chassis_info.update_master_status() assert ret == False - assert chassis_info.master_status_good == True + assert chassis_info.master_status_good == False # Test bad values while in good state chassis_info.total_supplied_power = 300.0 @@ -106,6 +138,7 @@ def test_update_master_status(self): assert ret == False assert chassis_info.master_status_good == False + def test_supplied_power(self): chassis = MockChassis() psu1 = MockPsu("PSU 1", 0, True, True) @@ -204,6 +237,7 @@ def test_power_budget(self): state_db = daemon_base.db_connect("STATE_DB") chassis_tbl = mock_swsscommon.Table(state_db, CHASSIS_INFO_TABLE) chassis_info = psud.PsuChassisInfo(SYSLOG_IDENTIFIER, chassis) + chassis_info.first_run = False # Check case where supplied_power < consumed_power chassis_info.run_power_budget(chassis_tbl) @@ -237,6 +271,24 @@ def test_power_budget(self): # so we must call it on the class there. assert psud.Psu.get_status_master_led() == MockPsu.STATUS_LED_COLOR_GREEN + def test_first_run(self): + chassis = MockChassis() + chassis_info = psud.PsuChassisInfo(SYSLOG_IDENTIFIER, chassis) + + chassis_info.total_supplied_power = 0.0 + chassis_info.total_consumed_power = 350.0 + chassis_info.master_status_good = False + ret = chassis_info.update_master_status() + assert ret == True + assert psud.Psu.get_status_master_led() == MockPsu.STATUS_LED_COLOR_RED + + chassis_info.total_supplied_power = 510.0 + chassis_info.total_consumed_power = 350.0 + chassis_info.master_status_good = True + ret = chassis_info.update_master_status() + assert ret == True + assert psud.Psu.get_status_master_led() == MockPsu.STATUS_LED_COLOR_GREEN + def test_get_psu_key(self): assert psud.get_psu_key(0) == psud.PSU_INFO_KEY_TEMPLATE.format(0) assert psud.get_psu_key(1) == psud.PSU_INFO_KEY_TEMPLATE.format(1)