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

PSUd changes to compute power-budget for Modular chassis #104

Merged
merged 4 commits into from
Nov 11, 2020
Merged
Changes from 1 commit
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
98 changes: 96 additions & 2 deletions sonic-psud/scripts/psud
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ try:
import sys
import threading

from sonic_py_common import daemon_base
from sonic_py_common import daemon_base, logger
from swsscommon import swsscommon
from sonic_platform_base.device_base import DeviceBase

except ImportError as e:
raise ImportError (str(e) + " - required module not found")

Expand All @@ -32,6 +34,10 @@ CHASSIS_INFO_TABLE = 'CHASSIS_INFO'
CHASSIS_INFO_KEY_TEMPLATE = 'chassis {}'
CHASSIS_INFO_PSU_NUM_FIELD = 'psu_num'

CHASSIS_INFO_POWER_CONSUMER_FIELD = '{} consumed_power'
CHASSIS_INFO_POWER_SUPPLIER_FIELD = '{} supplied_power'
CHASSIS_INFO_POWER_KEY_TEMPLATE = 'chassis_power_budget {}'

PSU_INFO_TABLE = 'PSU_INFO'
PSU_INFO_KEY_TEMPLATE = 'PSU {}'
PSU_INFO_PRESENCE_FIELD = 'presence'
Expand Down Expand Up @@ -133,8 +139,68 @@ def log_on_status_changed(logger, normal_status, normal_log, abnormal_log):
else:
logger.log_warning(abnormal_log)


#
# PSU Chassis Info ==========================================================
#
class PsuChassisInfo(object):
def __init__(self):
self.logger = logger.Logger(SYSLOG_IDENTIFIER)
self.master_status_good = False
self.total_consumed_power = 0.0
self.total_supplied_power = 0.0

def run_power_budget(self, chassis_tbl):
self.total_supplied_power = 0.0
self.total_consumed_power = 0.0

supplier_list = ['PSU']
consumer_list = platform_chassis.get_all_power_consumers()

fvs = swsscommon.FieldValuePairs(len(supplier_list) + len(consumer_list))

for index, psu in enumerate(platform_chassis.get_all_psus()):
presence = _wrapper_get_psus_presence(index + 1)
if not presence:
continue

power_good = _wrapper_get_psus_status(index + 1)
if not power_good:
continue

supplied_power = try_get(psu.get_maximum_supplied_power)
mprabhu-nokia marked this conversation as resolved.
Show resolved Hide resolved
self.total_supplied_power = self.total_supplied_power + supplied_power

for index, power_consumer in enumerate(consumer_list):
total_consumer_power = platform_chassis.get_total_consumer_power(power_consumer)
self.total_consumed_power = self.total_consumed_power + total_consumer_power

fvs[index] = (CHASSIS_INFO_POWER_CONSUMER_FIELD.format(str(power_consumer)), str(total_consumer_power))

#Record in state DB in chassis table
fvs[index + 1] = (CHASSIS_INFO_POWER_SUPPLIER_FIELD.format('PSU'), str(self.total_supplied_power))
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

self.master_status_good = master_status_good

return True

def _set_psu_master_led(self, master_status):
try:
color = platform_chassis.STATUS_LED_COLOR_GREEN if master_status else platform_chassis.STATUS_LED_COLOR_RED
platform_chassis.set_status_master_led(DeviceBase.DEVICE_TYPE_PSU, color)
except NotImplementedError as e:
pass

# PSU status ===================================================================
#

Expand Down Expand Up @@ -216,6 +282,7 @@ class DaemonPsud(daemon_base.DaemonBase):
self.stop = threading.Event()
self.psu_status_dict = {}
self.fan_tbl = None
self.psu_chassis_info = None

# Signal handler
def signal_handler(self, sig, frame):
Expand Down Expand Up @@ -263,6 +330,7 @@ class DaemonPsud(daemon_base.DaemonBase):
fvs = swsscommon.FieldValuePairs([(CHASSIS_INFO_PSU_NUM_FIELD, str(psu_num))])
chassis_tbl.set(CHASSIS_INFO_KEY_TEMPLATE.format(1), fvs)


# Start main loop
self.log_info("Start daemon main loop")

Expand All @@ -271,13 +339,17 @@ class DaemonPsud(daemon_base.DaemonBase):
self.update_psu_data(psu_tbl)
self._update_led_color(psu_tbl)

self.update_psu_chassis_info(chassis_tbl)
mprabhu-nokia marked this conversation as resolved.
Show resolved Hide resolved
self.update_master_led_color(chassis_tbl)

self.log_info("Stop daemon main loop")

# Delete all the information from DB and then exit
for psu_index in range(1, psu_num + 1):
psu_tbl._del(PSU_INFO_KEY_TEMPLATE.format(psu_index))

chassis_tbl._del(CHASSIS_INFO_KEY_TEMPLATE.format(1))
chassis_tbl._del(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1))

self.log_info("Shutting down...")

Expand Down Expand Up @@ -427,6 +499,28 @@ class DaemonPsud(daemon_base.DaemonBase):
])
self.fan_tbl.set(fan_name, fvs)

def update_psu_chassis_info(self, chassis_tbl):
if not platform_chassis:
return

if not self.psu_chassis_info:
self.psu_chassis_info = PsuChassisInfo()

self.psu_chassis_info.run_power_budget(chassis_tbl)

def update_master_led_color(self, chassis_tbl):
if not platform_chassis or not self.psu_chassis_info:
return

psu_chassis_info = self.psu_chassis_info
if psu_chassis_info.update_master_status():
log_on_status_changed(self, psu_chassis_info.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(
psu_chassis_info.total_supplied_power, psu_chassis_info.total_consumed_power)
)
psu_chassis_info._set_psu_master_led(psu_chassis_info.master_status_good)


#
# Main =========================================================================
Expand Down