-
Notifications
You must be signed in to change notification settings - Fork 650
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
show reboot-cause history
cli (#1210)
What I did To make the reboot cause history information available for telemetry service, during processing the reboot-cause on boot, the information is saved in state-db. The cli command show reboot-cause is changed to support the new file format and file name. New command show reboot-cause history is added to display the reboot-cause information which is stored in state-db. How I did it Add the 'show reboot-cause history' command to read up to the10 previous reboot-cause information from state-db and display them. Read the last reboot-cause from the new file "previous-reboot-cause.json" and process the data to display for show reboot-cause New command output (if the output of a command-line utility has changed) admin@sonic:~$ show reboot-cause history name cause time user comment ------------------- ----------- ---------------------------- ------ --------- 2020_10_09_04_53_58 warm-reboot Fri Oct 9 04:51:47 UTC 2020 admin 2020_10_09_02_33_06 reboot Fri Oct 9 02:29:44 UTC 2020 admin 2020_10_09_02_00_53 fast-reboot Fri Oct 9 01:58:04 UTC 2020 admin 2020_10_09_01_56_59 reboot Fri Oct 9 01:53:49 UTC 2020 admin
- Loading branch information
1 parent
6fabbed
commit dcd6743
Showing
5 changed files
with
175 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import json | ||
import os | ||
import sys | ||
|
||
import click | ||
from tabulate import tabulate | ||
from swsssdk import SonicV2Connector | ||
import utilities_common.cli as clicommon | ||
|
||
|
||
PREVIOUS_REBOOT_CAUSE_FILE = "/host/reboot-cause/previous-reboot-cause.json" | ||
USER_ISSUED_REBOOT_CAUSE_REGEX ="User issued \'{}\' command [User: {}, Time: {}]" | ||
|
||
def read_reboot_cause_file(): | ||
result = "" | ||
if os.path.exists(PREVIOUS_REBOOT_CAUSE_FILE): | ||
with open(PREVIOUS_REBOOT_CAUSE_FILE) as f: | ||
result = json.load(f) | ||
return result | ||
|
||
# | ||
# 'reboot-cause' group ("show reboot-cause") | ||
# | ||
@click.group(cls=clicommon.AliasedGroup, invoke_without_command=True) | ||
@click.pass_context | ||
def reboot_cause(ctx): | ||
"""Show cause of most recent reboot""" | ||
if ctx.invoked_subcommand is None: | ||
reboot_cause = "" | ||
# Read the previous reboot cause | ||
data = read_reboot_cause_file() | ||
if data['user'] == "N/A": | ||
reboot_cause = "{}".format(data['cause']) | ||
else: | ||
reboot_cause = USER_ISSUED_REBOOT_CAUSE_REGEX.format(data['cause'], data['user'], data['time']) | ||
|
||
click.echo(reboot_cause) | ||
|
||
# 'history' subcommand ("show reboot-cause history") | ||
@reboot_cause.command() | ||
def history(): | ||
"""Show history of reboot-cause""" | ||
REBOOT_CAUSE_TABLE_NAME = "REBOOT_CAUSE" | ||
TABLE_NAME_SEPARATOR = '|' | ||
db = SonicV2Connector(host='127.0.0.1') | ||
db.connect(db.STATE_DB, False) # Make one attempt only | ||
prefix = REBOOT_CAUSE_TABLE_NAME + TABLE_NAME_SEPARATOR | ||
_hash = '{}{}'.format(prefix, '*') | ||
table_keys = db.keys(db.STATE_DB, _hash) | ||
if table_keys is not None: | ||
table_keys.sort(reverse=True) | ||
|
||
table = [] | ||
for tk in table_keys: | ||
entry = db.get_all(db.STATE_DB, tk) | ||
r = [] | ||
r.append(tk.replace(prefix,"")) | ||
r.append(entry['cause'] if 'cause' in entry else "") | ||
r.append(entry['time'] if 'time' in entry else "") | ||
r.append(entry['user'] if 'user' in entry else "") | ||
r.append(entry['comment'] if 'comment' in entry else "") | ||
table.append(r) | ||
|
||
header = ['Name', 'Cause', 'Time', 'User', 'Comment'] | ||
click.echo(tabulate(table, header, numalign="left")) | ||
else: | ||
click.echo("Reboot-cause history is not yet available in StateDB") | ||
sys.exit(1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import os | ||
import sys | ||
import textwrap | ||
import mock | ||
from click.testing import CliRunner | ||
from .mock_tables import dbconnector | ||
|
||
test_path = os.path.dirname(os.path.abspath(__file__)) | ||
modules_path = os.path.dirname(test_path) | ||
sys.path.insert(0, modules_path) | ||
|
||
|
||
import show.main as show | ||
|
||
""" | ||
Note: The following 'show reboot-cause' commands simply call other SONiC | ||
CLI utilities, so the unit tests for the other utilities are expected | ||
to cover testing their functionality: | ||
show reboot-cause | ||
show reboot-cause history | ||
""" | ||
|
||
class TestShowRebootCause(object): | ||
@classmethod | ||
def setup_class(cls): | ||
print("SETUP") | ||
os.environ["UTILITIES_UNIT_TESTING"] = "1" | ||
|
||
# Test 'show reboot-cause' without previous-reboot-cause.json | ||
def test_reboot_cause_no_history_file(self): | ||
expected_output = "" | ||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["reboot-cause"], []) | ||
assert result.output == expected_output | ||
|
||
# Test 'show reboot-cause' with user issued reboot | ||
def test_reboot_cause_user(self): | ||
expected_output = "User issued 'reboot' command [User: admin, Time: Thu Oct 22 03:11:08 UTC 2020]\n" | ||
|
||
with mock.patch("show.reboot_cause.read_reboot_cause_file", return_value={"comment": "", "gen_time": "2020_10_22_03_14_07", "cause": "reboot", "user": "admin", "time": "Thu Oct 22 03:11:08 UTC 2020"}): | ||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["reboot-cause"], []) | ||
assert result.output == expected_output | ||
|
||
|
||
# Test 'show reboot-cause' with non-user issue reboot (hardware reboot-cause or unknown reboot-cause) | ||
def test_reboot_cause_non_user(self): | ||
expected_output = "Watchdog\n" | ||
|
||
with mock.patch("show.reboot_cause.read_reboot_cause_file", return_value={"comment": "N/A", "gen_time": "2020_10_22_03_15_08", "cause": "Watchdog", "user": "N/A", "time": "N/A"}): | ||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["reboot-cause"], []) | ||
assert result.output == expected_output | ||
|
||
# Test 'show reboot-cause history' | ||
def test_reboot_cause_history(self): | ||
expected_output = """\ | ||
Name Cause Time User Comment | ||
------------------- ----------- ---------------------------- ------ --------- | ||
2020_10_09_04_53_58 warm-reboot Fri Oct 9 04:51:47 UTC 2020 admin N/A | ||
2020_10_09_02_33_06 reboot Fri Oct 9 02:29:44 UTC 2020 admin N/A | ||
""" | ||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["reboot-cause"].commands["history"], []) | ||
print(result.output) | ||
assert result.output == expected_output | ||
|
||
@classmethod | ||
def teardown_class(cls): | ||
print("TEARDOWN") | ||
os.environ["PATH"] = os.pathsep.join(os.environ["PATH"].split(os.pathsep)[:-1]) | ||
os.environ["UTILITIES_UNIT_TESTING"] = "0" |