From ff143fb8ef1b63155b0dfbf1e02a7989d4641bd2 Mon Sep 17 00:00:00 2001 From: Anil Sadineni Date: Mon, 26 Aug 2019 08:49:44 -0700 Subject: [PATCH] Utility functions and scripts for Debug Framework These changes go along with https://github.com/Azure/sonic-swss-common/pull/300 --- config/main.py | 19 ++++++ scripts/dumpinfo | 136 +++++++++++++++++++++++++++++++++++++ scripts/generate_debugdump | 17 +++++ setup.py | 4 +- show/main.py | 58 ++++++++++++++++ 5 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 scripts/dumpinfo create mode 100644 scripts/generate_debugdump diff --git a/config/main.py b/config/main.py index bc14ecd3d0..939eb8eee2 100755 --- a/config/main.py +++ b/config/main.py @@ -1355,6 +1355,25 @@ def naming_mode_alias(): """Set CLI interface naming mode to ALIAS (Vendor port alias)""" set_interface_naming_mode('alias') +# +# 'assert' group ('config assert ...') +# +@config.group() +def custom_assert(): + """Configuration action on assert""" + pass + +@custom_assert.command() +@click.argument('action', metavar='', default='ABORT', required=False, + type=click.Choice(['SYSLOG', 'BTRACE', 'DUMP', 'ABORT'])) +def action(action): + """ Configure the action to execute when assert condition is false""" + config_db = ConfigDBConnector() + config_db.connect() + table = "DEBUGFM_CONFIG_TABLE" + key = "ASSERTACT" + config_db.set_entry(table, key, {"ASSERTACT": action}) + # # 'syslog' group ('config syslog ...') # diff --git a/scripts/dumpinfo b/scripts/dumpinfo new file mode 100644 index 0000000000..601ce21a88 --- /dev/null +++ b/scripts/dumpinfo @@ -0,0 +1,136 @@ +#!/usr/bin/python +from swsscommon import swsscommon +import argparse +""" +using debugdump to display internal debug information of SONiC components + +usage: debugdump [-h] [-u] [-c] [-s] [-l] [-o] + +Dump Debug Information of SONiC components + +optional arguments: + -h, --help show this help message and exit + -u, --action post action upload default is compress + -c, --component dump info for specified component + -s, --detail short summary default is full + -l, --location target location syslog + -o, --optargs optional additional arguments to components + +""" + +class DebugDump(object): + + def __init__(self): + self.target = "file" + self.component = "all" + self.detail = "full" + self.post_action = "compress" + self.argList = "" + + def set_dump_target(self, location): + """ + Set the target location for the dump syslog|file file is /var/log/_dump.log + :param location: target + :return: + """ + self.target = location + + def set_dump_component(self, component_name): + """ + Set the component_name which need to dump the debug info + :param component_name: component + :return: + """ + self.component = component_name + + def set_detail_level(self, level): + """ + Set the level of detail to dump short or full + :param level: detail + :return: + """ + self.detail = level + + def set_post_action(self, action): + """ + Set the action after collecting the dump + :param action: post_action + :return: + """ + self.post_action = action + + def add_args_for_component(self, field, value): + """ + append to the list of the arguments for the component interpretation + :param field: argType + :param value: argVal + :return: + """ + if len(self.argList): + self.argList += ";" + + self.argList += "{}:{}".format(field, value) + + def invoke_dump_trigger(self, componentName, optargList): + """ + invoke the trigger to framework and components to collect debug info + """ + args = ""; + if (self.target == "file"): + args += "TARGET:SWSS_FILE" + else: + args += "TARGET:SWSS_SYSLOG" + + if (self.detail == "full"): + args += ";DETAIL:FULL" + else: + args += ";DETAIL:SHORT" + + if (self.post_action == "compress"): + args += ";ACTION:COMPRESS;" + else: + args += ";ACTION:UPLOAD;" + + args += self.argList + args += optargList + + if (self.component == "all"): + swsscommon.Debugframework_invokeTrigger("all", args) + else: + swsscommon.Debugframework_invokeTrigger(self.component, args) + + return + +def main(): + parser = argparse.ArgumentParser(description='Dump internal debug information of SONiC components', + formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument('-u', '--upload', action='store_true', help='specify action as upload') + parser.add_argument('-c', '--component', type=str, help='specified component') + parser.add_argument('-s', '--detail', action='store_true', help='dump only short detail') + parser.add_argument('-l', '--location', action='store_true', help='dump to syslog') + parser.add_argument('-o', '--optargs', type=str, help='comma seperated args') + args = parser.parse_args() + + try: + dump = DebugDump() + if args.upload: + dump.set_post_action("upload") + if args.component: + dump.set_dump_component(args.component) + if args.detail: + dump.set_detail_level("short") + if args.location: + dump.set_dump_target("syslog") + + if args.optargs: + dump.invoke_dump_trigger(dump.component, args.optargs) + else: + dump.invoke_dump_trigger(dump.component, "") + + except Exception as e: + print(e.message) + sys.exit(1) + +if __name__ == "__main__": + main() + diff --git a/scripts/generate_debugdump b/scripts/generate_debugdump new file mode 100644 index 0000000000..e63557f46c --- /dev/null +++ b/scripts/generate_debugdump @@ -0,0 +1,17 @@ +#!/bin/bash +# +# Generate debugging information +# + +set -u + +#Copy the python dumpinfo script to swss container +sudo docker cp /usr/bin/dumpinfo swss:/usr/bin/dumpinfo + +#execute the dumpinfo python script in docker +sudo docker exec -i swss python /usr/bin/dumpinfo $@ + +#Copy the log files to host system /var/log/ +#sudo docker exec -i swss touch /var/log/fdborch_debug.log +#sudo docker cp swss:/var/log/fdborch_debug.log /var/log/fdborch_debug.log + diff --git a/setup.py b/setup.py index d12d9880b8..62a499f34c 100644 --- a/setup.py +++ b/setup.py @@ -83,7 +83,9 @@ 'scripts/teamshow', 'scripts/warm-reboot', 'scripts/watermarkstat', - 'scripts/watermarkcfg' + 'scripts/watermarkcfg', + 'scripts/generate_debugdump', + 'scripts/dumpinfo' ], data_files=[ ('/etc/bash_completion.d', glob.glob('data/etc/bash_completion.d/*')), diff --git a/show/main.py b/show/main.py index 7fb47310e1..4e2e481e17 100755 --- a/show/main.py +++ b/show/main.py @@ -1391,6 +1391,64 @@ def techsupport(since, verbose): cmd += " -s {}".format(since) run_command(cmd, display_cmd=verbose) +# +# 'debug' group ("show debug") +# + +@cli.group(cls=AliasedGroup, default_if_no_args=False) +def debug(): + """Collect debugging information from components""" + pass + +# 'all' subcommand ("show debug all") +@debug.command() +@click.option('--verbose', is_flag=True, help="Enable verbose output") +def all(verbose): + """Collect debugging information from all components""" + cmd = "sudo generate_debugdump" + run_command(cmd, display_cmd=verbose) + +# 'component' subcommand ("show debug component ") +@debug.command() +@click.argument('componentname', required=True) +@click.option('--verbose', is_flag=True, help="Enable verbose output") +def component(componentname, verbose): + """Collect debugging information from component""" + cmd = "sudo generate_debugdump -c " + + if componentname is not None: + cmd += format(componentname) + + run_command(cmd, display_cmd=verbose) + +# +# 'tosyslog' group ### +# +@debug.group(cls=AliasedGroup, default_if_no_args=False) +def tosyslog(): + """Write the logs to syslog""" + pass + +# 'all' subcommand ("show debug tosyslog all") +@tosyslog.command() +@click.option('--verbose', is_flag=True, help="Enable verbose output") +def all(verbose): + """Collect debugging information from all components and write in syslog""" + cmd = "sudo generate_debugdump -l " + run_command(cmd, display_cmd=verbose) + +# 'component' subcommand ("show debug tosyslog component ") +@tosyslog.command() +@click.argument('componentname', required=True) +@click.option('--verbose', is_flag=True, help="Enable verbose output") +def component(componentname, verbose): + """Collect debugging information from component and write in syslog""" + cmd = "sudo generate_debugdump -l -c " + + if componentname is not None: + cmd += format(componentname) + + run_command(cmd, display_cmd=verbose) # # 'runningconfiguration' group ("show runningconfiguration")