-
Notifications
You must be signed in to change notification settings - Fork 655
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
CLI support for SmartSwitch PMON #3271
base: master
Are you sure you want to change the base?
Changes from 39 commits
11cc04d
02df0ea
e0e4700
0a8fc5a
6d61faa
8d95dae
5c1b666
fe4a8cf
f896438
9d6c093
0904515
ccc380b
a8fa81d
1cf96a0
64fd559
d202e1c
b8c92ae
9986f7b
0dc52f6
93df26d
7a2aaf4
26f9b8a
3a592f8
71472a8
fd8bd6b
5b15bc4
b35c987
ee10649
27546a6
883e35c
713ffa2
62fc3d0
ecb2ecc
e2eb660
ef87cb5
53c2277
fb989e4
8ea7960
76de68a
a08e0cb
766b303
c474940
1910163
851dc78
cb54b73
4dfb5f8
6941baf
f3c8e36
6d7d539
433bc50
3ddcc9c
95da5c0
627dd5e
934e6ef
64d06ec
4870a86
fed3f67
68b6416
d229307
78e71c5
d7fbe9d
313a9d2
0ea1227
f5f88bb
62817ea
9fb005d
7c8c5d7
b5b068b
25259cb
808e7b4
7eb8304
44bed5c
d7fd0ce
b0e51f8
ed742fc
11f48f3
402887d
8db11f3
2ab48b5
e843fff
9ba21d2
738634d
c491687
ee3f927
d47a431
04c520e
c5abc01
6ab7742
4299ac3
d30ead7
a07e8c0
a2cece6
e2b65af
53909f0
9849436
02152e3
a75a4d3
f8a1f57
29000c3
e273a16
d720cf6
c6040b3
864c96c
8580f76
f4942b7
3e44844
e7355b0
b132f90
781270a
2e8813b
6cba5ed
5db0bc2
807529f
885b168
b6efa8c
4c26a25
ed3d24b
68a9efe
d09d58f
c217c18
df87438
2dfc2b5
c261b0c
ab200bc
5e36792
4a43780
8b2c9cb
155ba3f
e8c8b42
9601177
9713bf7
fdf8569
4b30138
e725add
d2e7590
3e1fc12
51dce03
a016ead
041fad6
5c85cf4
1b3fabb
9a0225b
8f191d6
523a42c
a90b878
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import json | ||
import os | ||
import sys | ||
import redis | ||
|
||
import click | ||
from tabulate import tabulate | ||
|
@@ -9,7 +10,8 @@ | |
|
||
|
||
PREVIOUS_REBOOT_CAUSE_FILE_PATH = "/host/reboot-cause/previous-reboot-cause.json" | ||
|
||
STATE_DB = 6 | ||
rameshraghupathy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
CHASSIS_STATE_DB = 13 | ||
|
||
vvolam marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def read_reboot_cause_file(): | ||
reboot_cause_dict = {} | ||
|
@@ -24,6 +26,98 @@ def read_reboot_cause_file(): | |
return reboot_cause_dict | ||
|
||
|
||
# Function to fetch reboot cause data from database | ||
def fetch_data_from_db(module_name, fetch_history=False, use_chassis_db=False): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @rameshraghupathy how are these functions prevented from executing on non-smartswitch platforms? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The KEY has unique identifier "DPUx" which will prevent the other platforms. |
||
prefix = 'REBOOT_CAUSE|' | ||
if use_chassis_db: | ||
try: | ||
rdb = redis.Redis(host='redis_chassis.server', port=6380, decode_responses=True, db=CHASSIS_STATE_DB) | ||
rameshraghupathy marked this conversation as resolved.
Show resolved
Hide resolved
rameshraghupathy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
table_keys = rdb.keys(prefix+'*') | ||
except Exception: | ||
return [] | ||
else: | ||
rdb = SonicV2Connector(host='127.0.0.1') | ||
rdb.connect(rdb.STATE_DB, False) # Make one attempt only | ||
table_keys = rdb.keys(rdb.STATE_DB, prefix+'*') | ||
|
||
if table_keys is not None: | ||
table_keys.sort(reverse=True) | ||
|
||
table = [] | ||
d = [] | ||
for tk in table_keys: | ||
rameshraghupathy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
r = [] | ||
append = False | ||
if use_chassis_db: | ||
entry = rdb.hgetall(tk) | ||
else: | ||
entry = rdb.get_all(rdb.STATE_DB, tk) | ||
|
||
if module_name is not None: | ||
if 'device' in entry: | ||
if module_name != entry['device'] and module_name != "all": | ||
continue | ||
if entry['device'] in d and not history: | ||
append = False | ||
continue | ||
elif not entry['device'] in d or entry['device'] in d and history: | ||
append = True | ||
if not entry['device'] in d: | ||
d.append(entry['device']) | ||
r.append(entry['device'] if 'device' in entry else "SWITCH") | ||
suffix = "" | ||
if append and "DPU" in entry['device']: | ||
suffix = entry['device'] + '|' | ||
r.append(tk.replace(prefix, "").replace(suffix, "")) | ||
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 "") | ||
if append and not fetch_history: | ||
table.append(r) | ||
elif fetch_history: | ||
r.append(entry['comment'] if 'comment' in entry else "") | ||
if module_name is None or module_name == 'all' or module_name.startswith('SWITCH') or \ | ||
'device' in entry and module_name == entry['device']: | ||
table.append(r) | ||
|
||
return table | ||
|
||
|
||
# Wrapper-function to fetch reboot cause data from database | ||
def fetch_reboot_cause_from_db(module_name): | ||
table = [] | ||
r = [] | ||
|
||
# Read the previous reboot cause | ||
reboot_cause_dict = read_reboot_cause_file() | ||
reboot_gen_time = reboot_cause_dict.get("gen_time", "N/A") | ||
reboot_cause = reboot_cause_dict.get("cause", "Unknown") | ||
reboot_time = reboot_cause_dict.get("time", "N/A") | ||
reboot_user = reboot_cause_dict.get("user", "N/A") | ||
|
||
r.append("SWITCH") | ||
r.append(reboot_gen_time if reboot_gen_time else "") | ||
r.append(reboot_cause if reboot_cause else "") | ||
r.append(reboot_time if reboot_time else "") | ||
r.append(reboot_user if reboot_user else "") | ||
table.append(r) | ||
|
||
table += fetch_data_from_db(module_name, fetch_history=False, use_chassis_db=True) | ||
return table | ||
|
||
|
||
# Function to fetch reboot cause history data from database | ||
def fetch_reboot_cause_history_from_db(module_name): | ||
if module_name == "all": | ||
# Combine data from both Redis containers for "all" modules | ||
data_switch = fetch_data_from_db(module_name, fetch_history=True, use_chassis_db=False) | ||
data_dpu = fetch_data_from_db(module_name, fetch_history=True, use_chassis_db=True) | ||
return data_switch + data_dpu | ||
elif module_name is None or module_name == "SWITCH": | ||
return fetch_data_from_db(module_name, fetch_history=True, use_chassis_db=False) | ||
else: | ||
return fetch_data_from_db(module_name, fetch_history=True, use_chassis_db=True) | ||
|
||
# | ||
# 'reboot-cause' group ("show reboot-cause") | ||
# | ||
|
@@ -62,33 +156,24 @@ def reboot_cause(ctx): | |
click.echo(reboot_cause_str) | ||
|
||
|
||
# 'history' subcommand ("show reboot-cause history") | ||
# 'all' command within 'reboot-cause' | ||
@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) | ||
def all(): | ||
"""Show cause of most recent reboot""" | ||
reboot_cause_data = fetch_reboot_cause_from_db("all") | ||
header = ['Device', 'Name', 'Cause', 'Time', 'User'] | ||
click.echo(tabulate(reboot_cause_data, header, numalign="left")) | ||
|
||
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")) | ||
# 'history' command within 'reboot-cause' | ||
@reboot_cause.command() | ||
@click.argument('module_name', required=False) | ||
def history(module_name): | ||
"""Show history of reboot-cause""" | ||
reboot_cause_history = fetch_reboot_cause_history_from_db(module_name) | ||
if module_name is not None: | ||
header = ['Device', 'Name', 'Cause', 'Time', 'User', 'Comment'] | ||
click.echo(tabulate(reboot_cause_history, header, numalign="left")) | ||
else: | ||
click.echo("Reboot-cause history is not yet available in StateDB") | ||
sys.exit(1) | ||
header = ['Name', 'Cause', 'Time', 'User', 'Comment'] | ||
click.echo(tabulate(reboot_cause_history, header, numalign="left")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @rameshraghupathy please test this CLI on non-smartswitch There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done and UT log is attached |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to perform additional validation to check if the chassis_module_name is actually present (or is an actual valid module name) or not, if user executes
config chassis modules startup DPU5
on a system which does not have DPU5, this will cause crash in chassisd for theSmartSwitchConfigManagerTask
in chassisd preventing further startup or shutdown calls (even though output of the command would beStarting up chassis module DPU1
orShutting down chassis module DPU1
the only operation which is performed is addition/removal from the CONFIG_DB )