Skip to content

Commit

Permalink
Modular chassis: Psud set master led on first run (sonic-net#206)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mprabhu-nokia authored Feb 11, 2022
1 parent 7195dcc commit 7d7c85e
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 22 deletions.
44 changes: 24 additions & 20 deletions sonic-psud/scripts/psud
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 ===================================================================
#
Expand Down Expand Up @@ -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 =========================================================================
Expand Down
56 changes: 54 additions & 2 deletions sonic-psud/tests/test_PsuChassisInfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 7d7c85e

Please sign in to comment.