Skip to content

Commit

Permalink
[psushow & psuutil] Support PSU power threshold checking (#2326)
Browse files Browse the repository at this point in the history
* Support PSU power exceed warning
  • Loading branch information
stephenxs authored Nov 21, 2022
1 parent dfdc92e commit 72b9cf9
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 8 deletions.
1 change: 1 addition & 0 deletions doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,7 @@ This command displays the status of the device's power supply units
PSU Model Serial HW Rev Voltage (V) Current (A) Power (W) Status LED
----- ------------- ------------ -------- ------------- ------------- ----------- -------- -----
PSU 1 MTEF-PSF-AC-A MT1621X15246 A3 11.97 4.56 54.56 OK green
PSU 2 MTEF-PSF-AC-A MT1621X15247 A3 11.97 4.56 54.56 WARNING green
```

**show platform fan**
Expand Down
24 changes: 22 additions & 2 deletions psuutil/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def numpsus():
@click.option('-i', '--index', default=-1, type=int, help='Index of the PSU')
def status(index):
"""Display PSU status"""
header = ['PSU', 'Model', 'Serial', 'Voltage (V)', 'Current (A)', 'Power (W)', 'Status', 'LED']
header = ['PSU', 'Model', 'Serial', 'HW Rev', 'Voltage (V)', 'Current (A)', 'Power (W)', 'Power Warn-supp Thres (W)', 'Power Crit Thres (W)', 'Status', 'LED']
status_table = []

psu_list = platform_chassis.get_all_psus()
Expand All @@ -94,14 +94,29 @@ def status(index):
status = 'NOT PRESENT'
model = 'N/A'
serial = 'N/A'
revision = 'N/A'
voltage = 'N/A'
current = 'N/A'
power = 'N/A'
led_color = 'N/A'
power_critical_threshold = 'N/A'
power_warning_suppress_threshold = 'N/A'

if psu.get_presence():
try:
status = 'OK' if psu.get_powergood_status() else 'NOT OK'
if psu.get_powergood_status():
power = psu.get_power()
try:
power_critical_threshold = psu.get_psu_power_critical_threshold()
power_warning_suppress_threshold = psu.get_psu_power_warning_suppress_threshold()
except NotImplementedError:
pass
if power_critical_threshold is None:
power_critical_threshold = 'N/A'
if power_warning_suppress_threshold is None:
power_warning_suppress_threshold = 'N/A'
status = 'OK'
except NotImplementedError:
status = 'UNKNOWN'

Expand All @@ -115,6 +130,11 @@ def status(index):
except NotImplementedError:
pass

try:
revision = psu.get_revision()
except NotImplementedError:
pass

try:
voltage = psu.get_voltage()
except NotImplementedError:
Expand All @@ -135,7 +155,7 @@ def status(index):
except NotImplementedError:
pass

status_table.append([psu_name, model, serial, voltage, current, power, status, led_color])
status_table.append([psu_name, model, serial, revision, voltage, current, power, power_warning_suppress_threshold, power_critical_threshold, status, led_color])

if status_table:
click.echo(tabulate(status_table, header, tablefmt='simple', floatfmt='.2f'))
Expand Down
6 changes: 5 additions & 1 deletion scripts/psushow
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ def get_psu_status_list():

if presence == 'true':
oper_status = db.get(db.STATE_DB, 'PSU_INFO|{}'.format(psu_name), 'status')
status = 'OK' if oper_status == 'true' else "NOT OK"
if oper_status == 'true':
power_overload = db.get(db.STATE_DB, 'PSU_INFO|{}'.format(psu_name), 'power_overload')
status = 'WARNING' if power_overload == 'True' else 'OK'
else:
status = "NOT OK"
else:
status = 'NOT PRESENT'
psu_status['status'] = status
Expand Down
2 changes: 2 additions & 0 deletions tests/mock_tables/state_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@
"voltage_max_threshold": "None",
"current": "8.37",
"power": "102.7",
"power_overload": "True",
"is_replaceable": "False",
"led_status": "green"
},
Expand All @@ -287,6 +288,7 @@
"voltage_max_threshold": "None",
"current": "10.07",
"power": "122.0",
"power_overload": "False",
"is_replaceable": "False",
"led_status": "green"
},
Expand Down
10 changes: 5 additions & 5 deletions tests/psushow_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def test_get_psu_status_list(self):
'index': '1',
'name': 'PSU 1',
'presence': 'true',
'status': 'OK',
'status': 'WARNING',
'led_status': 'green',
'model': '0J6J4K',
'serial': 'CN-0J6J4K-17972-5AF-0086-A00',
Expand Down Expand Up @@ -61,7 +61,7 @@ def test_status_table(self, capsys):
expected_output = '''\
PSU Model Serial HW Rev Voltage (V) Current (A) Power (W) Status LED
----- ------- ---------------------------- -------- ------------- ------------- ----------- -------- -----
PSU 1 0J6J4K CN-0J6J4K-17972-5AF-0086-A00 1 12.19 8.37 102.70 OK green
PSU 1 0J6J4K CN-0J6J4K-17972-5AF-0086-A00 1 12.19 8.37 102.70 WARNING green
PSU 2 0J6J4K CN-0J6J4K-17972-5AF-008M-A00 A 12.18 10.07 122.00 OK green
'''
for arg in ['-s', '--status']:
Expand All @@ -74,7 +74,7 @@ def test_status_table(self, capsys):
expected_output = '''\
PSU Model Serial HW Rev Voltage (V) Current (A) Power (W) Status LED
----- ------- ---------------------------- -------- ------------- ------------- ----------- -------- -----
PSU 1 0J6J4K CN-0J6J4K-17972-5AF-0086-A00 1 12.19 8.37 102.70 OK green
PSU 1 0J6J4K CN-0J6J4K-17972-5AF-0086-A00 1 12.19 8.37 102.70 WARNING green
'''
for arg in ['-s', '--status']:
with mock.patch('sys.argv', ['psushow', arg, '-i', '1']):
Expand Down Expand Up @@ -114,7 +114,7 @@ def test_status_json(self, capsys):
"index": "1",
"name": "PSU 1",
"presence": "true",
"status": "OK",
"status": "WARNING",
"led_status": "green",
"model": "0J6J4K",
"serial": "CN-0J6J4K-17972-5AF-0086-A00",
Expand Down Expand Up @@ -151,7 +151,7 @@ def test_status_json(self, capsys):
"index": "1",
"name": "PSU 1",
"presence": "true",
"status": "OK",
"status": "WARNING",
"led_status": "green",
"model": "0J6J4K",
"serial": "CN-0J6J4K-17972-5AF-0086-A00",
Expand Down
42 changes: 42 additions & 0 deletions tests/psuutil_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sys
import os
from sonic_platform_base import device_base
from unittest import mock

import pytest
Expand All @@ -12,10 +13,51 @@
sys.modules['sonic_platform'] = mock.MagicMock()
import psuutil.main as psuutil

STATUS_OUTPUT = '''\
PSU Model Serial HW Rev Voltage (V) Current (A) Power (W) Power Warn-supp Thres (W) Power Crit Thres (W) Status LED
----- ----------- -------- -------- ------------- ------------- ----------- --------------------------- ---------------------- -------- -----
PSU 1 SampleModel S001 Rev A 12.00 10.00 120.00 90.00 100.00 OK green
'''

STATUS_OUTPUT_NOT_IMPLEMENT = '''\
PSU Model Serial HW Rev Voltage (V) Current (A) Power (W) Power Warn-supp Thres (W) Power Crit Thres (W) Status LED
----- ----------- -------- -------- ------------- ------------- ----------- --------------------------- ---------------------- -------- -----
PSU 1 SampleModel S001 N/A 12.00 10.00 120.00 N/A N/A OK green
'''

class TestPsuutil(object):

def test_version(self):
runner = CliRunner()
result = runner.invoke(psuutil.cli.commands['version'], [])
assert result.output.rstrip() == 'psuutil version {}'.format(psuutil.VERSION)

@mock.patch('psuutil.main.load_platform_chassis', mock.MagicMock(return_value=True))
@mock.patch('psuutil.main.platform_chassis')
def test_psuutil_status(self, platform_chassis):
psu = mock.MagicMock()
psu.get_name = mock.MagicMock(return_value='PSU 1')
psu.get_presence = mock.MagicMock(return_value=True)
psu.get_powergood_status = mock.MagicMock(return_value=True)
psu.get_psu_power_critical_threshold = mock.MagicMock(return_value=100.0)
psu.get_psu_power_warning_suppress_threshold = mock.MagicMock(return_value=90.0)
psu.get_model = mock.MagicMock(return_value='SampleModel')
psu.get_serial = mock.MagicMock(return_value='S001')
psu.get_revision = mock.MagicMock(return_value='Rev A')
psu.get_voltage = mock.MagicMock(return_value=12.0)
psu.get_current = mock.MagicMock(return_value=10.0)
psu.get_power = mock.MagicMock(return_value=120.0)
psu.get_status_led = mock.MagicMock(return_value='green')

psu_list = [psu]
platform_chassis.get_all_psus = mock.MagicMock(return_value=psu_list)

runner = CliRunner()
result = runner.invoke(psuutil.cli.commands['status'])
assert result.output == STATUS_OUTPUT

psu.get_psu_power_critical_threshold = mock.MagicMock(side_effect=NotImplementedError(''))
psu.get_revision = mock.MagicMock(side_effect=NotImplementedError(''))
runner = CliRunner()
result = runner.invoke(psuutil.cli.commands['status'])
assert result.output == STATUS_OUTPUT_NOT_IMPLEMENT

0 comments on commit 72b9cf9

Please sign in to comment.