From 4cb3b72b43c2f94c868ad4257da56a6a63f91f1b Mon Sep 17 00:00:00 2001 From: yozhao101 <56170650+yozhao101@users.noreply.github.com> Date: Sun, 22 Aug 2021 09:54:46 -0700 Subject: [PATCH] [Show] Update the subcommands of Kdump. (#1682) Signed-off-by: Yong Zhao yozhao@microsoft.com What I did This PR fixed the following issues: Initially we need add prefix sudo when ran the show command of Kdump. This is unnecessary. I re-organized the logic of implementing show command and also update the script sonic-kdump-config. How I did it Since the script sonic-kdump-config can only be executed by root user, I moved some functions from this file to the kdump.py such that we do not need run the show command with sudo. How to verify it I verified this change on the DuT str-msn2700-03. --- doc/Command-Reference.md | 116 ++++++++++++++++++ scripts/sonic-kdump-config | 99 --------------- show/kdump.py | 244 ++++++++++++++++++++++++++----------- 3 files changed, 290 insertions(+), 169 deletions(-) diff --git a/doc/Command-Reference.md b/doc/Command-Reference.md index 5582bc9b5629..35d7b28aef79 100644 --- a/doc/Command-Reference.md +++ b/doc/Command-Reference.md @@ -71,6 +71,9 @@ * [Kubernetes](#Kubernetes) * [Kubernetes show commands](#Kubernetes-show-commands) * [Kubernetes config commands](#Kubernetes-config-commands) +* [Linux Kernel Dump](#kdump) + * [Linux Kernel Dump show commands](#kdump-show-commands) + * [Linux Kernel Dump config commands](#kdump-config-commands) * [LLDP](#lldp) * [LLDP show commands](#lldp-show-commands) * [Loading, Reloading And Saving Configuration](#loading-reloading-and-saving-configuration) @@ -4538,6 +4541,119 @@ This command displays the kubernetes server status. ----------- ------ ----------- ------------------- 10.3.157.24 6443 true 2020-11-15 18:25:05 ``` +Go Back To [Beginning of the document](#) or [Beginning of this section](#Kubernetes) + +## Linux Kernel Dump + +This section demonstrates the show commands and configuration commands of Linux kernel dump mechanism in SONiC. + +### Linux Kernel Dump show commands + +**show kdump config** + +This command shows the configuration of Linux kernel dump. + +- Usage: + ``` + show kdump config + ``` + +- Example: + ``` + admin@sonic:$ show kdump config + Kdump administrative mode: Disabled + Kdump operational mode: Unready + Kdump memory researvation: 0M-2G:256M,2G-4G:320M,4G-8G:384M,8G-:448M + Maximum number of Kdump files: 3 + ``` + +**show kdump files** + +This command shows the Linux kernel core dump files and dmesg files which are +generated by kernel dump tool. + +- Usage: + ``` + show kdump files + ``` + +- Example: + ``` + admin@sonic:~$ show kdump files + Kernel core dump files Kernel dmesg files + ------------------------------------------ ------------------------------------------ + /var/crash/202106242344/kdump.202106242344 /var/crash/202106242344/dmesg.202106242344 + /var/crash/202106242337/kdump.202106242337 /var/crash/202106242337/dmesg.202106242337 + ``` + +**show kdump logging ** + +By default, this command will show the last 10 lines of latest dmesg file. +This command can also accept a specific file name and number of lines as arguments. + +- Usage: + ``` + show kdump logging + ``` + +- Example: + ``` + admin@sonic:~$ show kdump logging + [ 157.642053] RSP: 002b:00007fff1beee708 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 + [ 157.732635] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007fc3887d4504 + [ 157.818015] RDX: 0000000000000002 RSI: 000055d388eceb40 RDI: 0000000000000001 + [ 157.903401] RBP: 000055d388eceb40 R08: 000000000000000a R09: 00007fc3888255f0 + [ 157.988784] R10: 000000000000000a R11: 0000000000000246 R12: 00007fc3888a6760 + [ 158.074166] R13: 0000000000000002 R14: 00007fc3888a1760 R15: 0000000000000002 + [ 158.159553] Modules linked in: nft_chain_route_ipv6(E) nft_chain_route_ipv4(E) xt_TCPMSS(E) dummy(E) team_mode_loadbalance(E) team(E) sx_bfd(OE) sx_netdev(OE) psample(E) sx_core(OE) 8021q(E) garp(E) mrp(E) mst_pciconf(OE) mst_pci(OE) xt_hl(E) xt_tcpudp(E) ip6_tables(E) nft_compat(E) nft_chain_nat_ipv4(E) nf_nat_ipv4(E) nft_counter(E) xt_conntrack(E) nf_nat(E) jc42(E) nf_conntrack_netlink(E) nf_conntrack(E) nf_defrag_ipv6(E) nf_defrag_ipv4(E) libcrc32c(E) xfrm_user(E) xfrm_algo(E) mlxsw_minimal(E) mlxsw_i2c(E) i2c_mux_reg(E) i2c_mux(E) i2c_mlxcpld(E) leds_mlxreg(E) mlxreg_io(E) mlxreg_hotplug(E) mei_wdt(E) evdev(E) intel_rapl(E) x86_pkg_temp_thermal(E) intel_powerclamp(E) kvm_intel(E) mlx_platform(E) kvm(E) irqbypass(E) crct10dif_pclmul(E) crc32_pclmul(E) ghash_clmulni_intel(E) intel_cstate(E) intel_uncore(E) + [ 159.016731] intel_rapl_perf(E) pcspkr(E) sg(E) iTCO_wdt(E) iTCO_vendor_support(E) mei_me(E) mei(E) bonding(E) pcc_cpufreq(E) video(E) button(E) ebt_vlan(E) ebtable_broute(E) bridge(E) stp(E) llc(E) ebtable_nat(E) ebtable_filter(E) ebtables(E) nf_tables(E) nfnetlink(E) xdpe12284(E) at24(E) ledtrig_timer(E) tmp102(E) lm75(E) drm(E) coretemp(E) max1363(E) industrialio_triggered_buffer(E) kfifo_buf(E) industrialio(E) tps53679(E) fuse(E) pmbus(E) pmbus_core(E) i2c_dev(E) configfs(E) ip_tables(E) x_tables(E) autofs4(E) loop(E) ext4(E) crc16(E) mbcache(E) jbd2(E) crc32c_generic(E) fscrypto(E) ecb(E) crypto_simd(E) cryptd(E) glue_helper(E) aes_x86_64(E) nvme(E) nvme_core(E) nls_utf8(E) nls_cp437(E) nls_ascii(E) vfat(E) fat(E) overlay(E) squashfs(E) zstd_decompress(E) xxhash(E) sd_mod(E) gpio_ich(E) ahci(E) + [ 159.864532] libahci(E) mlxsw_core(E) devlink(E) ehci_pci(E) ehci_hcd(E) crc32c_intel(E) libata(E) i2c_i801(E) scsi_mod(E) usbcore(E) usb_common(E) lpc_ich(E) mfd_core(E) e1000e(E) fan(E) thermal(E) + [ 160.075846] CR2: 0000000000000000 + ``` +You can specify a file name in order to show its +last 10 lines. + +- Example: + ``` + admin@sonic:~$ show kdump logging dmesg.202106242337 + [ 654.120195] RSP: 002b:00007ffe697690f8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 + [ 654.210778] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007fcfca27b504 + [ 654.296157] RDX: 0000000000000002 RSI: 000055a6e4d1b3f0 RDI: 0000000000000001 + [ 654.381543] RBP: 000055a6e4d1b3f0 R08: 000000000000000a R09: 00007fcfca2cc5f0 + [ 654.466925] R10: 000000000000000a R11: 0000000000000246 R12: 00007fcfca34d760 + [ 654.552310] R13: 0000000000000002 R14: 00007fcfca348760 R15: 0000000000000002 + [ 654.637694] Modules linked in: binfmt_misc(E) nft_chain_route_ipv6(E) nft_chain_route_ipv4(E) xt_TCPMSS(E) dummy(E) team_mode_loadbalance(E) team(E) sx_bfd(OE) sx_netdev(OE) psample(E) sx_core(OE) 8021q(E) garp(E) mrp(E) mst_pciconf(OE) mst_pci(OE) xt_hl(E) xt_tcpudp(E) ip6_tables(E) nft_chain_nat_ipv4(E) nf_nat_ipv4(E) nft_compat(E) nft_counter(E) xt_conntrack(E) nf_nat(E) jc42(E) nf_conntrack_netlink(E) nf_conntrack(E) nf_defrag_ipv6(E) nf_defrag_ipv4(E) libcrc32c(E) xfrm_user(E) xfrm_algo(E) mlxsw_minimal(E) mlxsw_i2c(E) i2c_mux_reg(E) i2c_mux(E) mlxreg_hotplug(E) mlxreg_io(E) i2c_mlxcpld(E) leds_mlxreg(E) mei_wdt(E) evdev(E) intel_rapl(E) x86_pkg_temp_thermal(E) intel_powerclamp(E) kvm_intel(E) kvm(E) mlx_platform(E) irqbypass(E) crct10dif_pclmul(E) crc32_pclmul(E) ghash_clmulni_intel(E) intel_cstate(E) + [ 655.493833] intel_uncore(E) intel_rapl_perf(E) pcspkr(E) sg(E) iTCO_wdt(E) iTCO_vendor_support(E) mei_me(E) mei(E) bonding(E) video(E) button(E) pcc_cpufreq(E) ebt_vlan(E) ebtable_broute(E) bridge(E) stp(E) llc(E) ebtable_nat(E) ebtable_filter(E) ebtables(E) nf_tables(E) nfnetlink(E) xdpe12284(E) at24(E) ledtrig_timer(E) tmp102(E) drm(E) lm75(E) coretemp(E) max1363(E) industrialio_triggered_buffer(E) kfifo_buf(E) industrialio(E) fuse(E) tps53679(E) pmbus(E) pmbus_core(E) i2c_dev(E) configfs(E) ip_tables(E) x_tables(E) autofs4(E) loop(E) ext4(E) crc16(E) mbcache(E) jbd2(E) crc32c_generic(E) fscrypto(E) ecb(E) crypto_simd(E) cryptd(E) glue_helper(E) aes_x86_64(E) nvme(E) nvme_core(E) nls_utf8(E) nls_cp437(E) nls_ascii(E) vfat(E) fat(E) overlay(E) squashfs(E) zstd_decompress(E) xxhash(E) sd_mod(E) + [ 656.337476] gpio_ich(E) ahci(E) mlxsw_core(E) libahci(E) devlink(E) crc32c_intel(E) libata(E) i2c_i801(E) scsi_mod(E) lpc_ich(E) mfd_core(E) ehci_pci(E) ehci_hcd(E) usbcore(E) e1000e(E) usb_common(E) fan(E) thermal(E) + [ 656.569590] CR2: 0000000000000000 + ``` +You can also specify a file name and number of lines in order to show the +last number of lines. + +- Example: + ``` + admin@sonic:~$ show kdump logging dmesg.202106242337 -l 20 + [ 653.525427] __handle_sysrq.cold.9+0x45/0xf2 + [ 653.576487] write_sysrq_trigger+0x2b/0x30 + [ 653.625472] proc_reg_write+0x39/0x60 + [ 653.669252] vfs_write+0xa5/0x1a0 + [ 653.708881] ksys_write+0x57/0xd0 + [ 653.748501] do_syscall_64+0x53/0x110 + [ 653.792287] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + [ 653.852707] RIP: 0033:0x7fcfca27b504 + [ 653.895452] Code: 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b3 0f 1f 80 00 00 00 00 48 8d 05 f9 61 0d 00 8b 00 85 c0 75 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 41 54 49 89 d4 55 48 89 f5 53 + [ 654.120195] RSP: 002b:00007ffe697690f8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 + [ 654.210778] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007fcfca27b504 + [ 654.296157] RDX: 0000000000000002 RSI: 000055a6e4d1b3f0 RDI: 0000000000000001 + [ 654.381543] RBP: 000055a6e4d1b3f0 R08: 000000000000000a R09: 00007fcfca2cc5f0 + [ 654.466925] R10: 000000000000000a R11: 0000000000000246 R12: 00007fcfca34d760 + [ 654.552310] R13: 0000000000000002 R14: 00007fcfca348760 R15: 0000000000000002 + [ 654.637694] Modules linked in: binfmt_misc(E) nft_chain_route_ipv6(E) nft_chain_route_ipv4(E) xt_TCPMSS(E) dummy(E) team_mode_loadbalance(E) team(E) sx_bfd(OE) sx_netdev(OE) psample(E) sx_core(OE) 8021q(E) garp(E) mrp(E) mst_pciconf(OE) mst_pci(OE) xt_hl(E) xt_tcpudp(E) ip6_tables(E) nft_chain_nat_ipv4(E) nf_nat_ipv4(E) nft_compat(E) nft_counter(E) xt_conntrack(E) nf_nat(E) jc42(E) nf_conntrack_netlink(E) nf_conntrack(E) nf_defrag_ipv6(E) nf_defrag_ipv4(E) libcrc32c(E) xfrm_user(E) xfrm_algo(E) mlxsw_minimal(E) mlxsw_i2c(E) i2c_mux_reg(E) i2c_mux(E) mlxreg_hotplug(E) mlxreg_io(E) i2c_mlxcpld(E) leds_mlxreg(E) mei_wdt(E) evdev(E) intel_rapl(E) x86_pkg_temp_thermal(E) intel_powerclamp(E) kvm_intel(E) kvm(E) mlx_platform(E) irqbypass(E) crct10dif_pclmul(E) crc32_pclmul(E) ghash_clmulni_intel(E) intel_cstate(E) + [ 655.493833] intel_uncore(E) intel_rapl_perf(E) pcspkr(E) sg(E) iTCO_wdt(E) iTCO_vendor_support(E) mei_me(E) mei(E) bonding(E) video(E) button(E) pcc_cpufreq(E) ebt_vlan(E) ebtable_broute(E) bridge(E) stp(E) llc(E) ebtable_nat(E) ebtable_filter(E) ebtables(E) nf_tables(E) nfnetlink(E) xdpe12284(E) at24(E) ledtrig_timer(E) tmp102(E) drm(E) lm75(E) coretemp(E) max1363(E) industrialio_triggered_buffer(E) kfifo_buf(E) industrialio(E) fuse(E) tps53679(E) pmbus(E) pmbus_core(E) i2c_dev(E) configfs(E) ip_tables(E) x_tables(E) autofs4(E) loop(E) ext4(E) crc16(E) mbcache(E) jbd2(E) crc32c_generic(E) fscrypto(E) ecb(E) crypto_simd(E) cryptd(E) glue_helper(E) aes_x86_64(E) nvme(E) nvme_core(E) nls_utf8(E) nls_cp437(E) nls_ascii(E) vfat(E) fat(E) overlay(E) squashfs(E) zstd_decompress(E) xxhash(E) sd_mod(E) + [ 656.337476] gpio_ich(E) ahci(E) mlxsw_core(E) libahci(E) devlink(E) crc32c_intel(E) libata(E) i2c_i801(E) scsi_mod(E) lpc_ich(E) mfd_core(E) ehci_pci(E) ehci_hcd(E) usbcore(E) e1000e(E) usb_common(E) fan(E) thermal(E) + [ 656.569590] CR2: 0000000000000000 + ``` +Go Back To [Beginning of the document](#) or [Beginning of this section](#kdump) ## LLDP diff --git a/scripts/sonic-kdump-config b/scripts/sonic-kdump-config index 8dc1a553b17b..26fa652dc2b7 100755 --- a/scripts/sonic-kdump-config +++ b/scripts/sonic-kdump-config @@ -607,86 +607,6 @@ def cmd_kdump_num_dumps(verbose, num_dumps): kdump_memory = get_kdump_memory() save_config(kdump_enabled, kdump_memory, num_dumps) -## Command: Display kdump status -def cmd_kdump_status(): - print('Kdump Administrative Mode: ', end='') - kdump_enabled = get_kdump_administrative_mode() - if kdump_enabled: - print('Enabled') - else: - print('Disabled') - - print('Kdump Operational State: ', end='') - (rc, lines, err_str) = run_command("/usr/sbin/kdump-config status", use_shell=False); - if len(lines) >= 1 and ": ready to kdump" in lines[0]: - use_kdump_in_cfg = read_use_kdump() - if use_kdump_in_cfg: - print('Ready') - else: - print('Not Ready') - elif not kdump_enabled: - print('Disabled') - else: - print('Ready after Reboot') - -## Get the current number of kernel dump files stored -# -# @param The number of kdump files stored in /var/crash -def get_nb_dumps_in_var_crash(): - (rc, lines, err_str) = run_command("find /var/crash/ -name 'kdump.*'", use_shell=False); - if rc == 0: - return len(lines) - return 0 - -## Command: Display kdump files -def cmd_kdump_files(): - nb_dumps = get_nb_dumps_in_var_crash() - if nb_dumps == 0: - print("No kernel core dump files") - else: - (rc1, lines1, err_str) = run_command("find /var/crash/ -name 'dmesg.*'", use_shell=False); - lines1.sort(reverse=True) - (rc2, lines2, err_str) = run_command("find /var/crash/ -name 'kdump.*'", use_shell=False); - lines2.sort(reverse=True) - print("Record Key Filename") - print("-------------------------------------------------------------") - for n in range(len(lines1)): - print("%6d %s %s\n %s" % (n+1, lines1[n][11:23], lines1[n], lines2[n])) - -## Command: Display kdump file (kernel log) -# -# @param num_lines Number of last lines displayed -# @param filename Name or index of the kernel log file (dmesg) -def cmd_kdump_file(num_lines, filename): - fname = None - nb_dumps = get_nb_dumps_in_var_crash() - if nb_dumps == 0: - print("Kernel crash log not found") - else: - (rc, lines, err_str) = run_command("find /var/crash/ -name 'dmesg.*'", use_shell=False); - if rc == 0 and nb_dumps == len(lines): - if filename.isdigit() and len(filename) <= 2: - num = int(filename) - if num < 1 or num > nb_dumps: - if nb_dumps == 1: - print("Invalid record number - Should be 1") - else: - print("Invalid record number - Should be between 1 and %d" % nb_dumps) - sys.exit(1) - fname = sorted(lines, reverse=True)[num-1] - else: - lines.sort(reverse=True) - for x in lines: - if x.find(filename) != -1: - fname = x - break - if fname is None: - print("Invalid key") - sys.exit(1) - (rc, lines, err_str) = run_command("/usr/bin/tail -n %d %s" % (num_lines, fname), use_shell=False); - if rc == 0: - print('File: %s' % fname) - print('\n'.join(lines)) def main(): @@ -714,10 +634,6 @@ def main(): parser.add_argument('--disable', action='store_true', help='Disable kdump') - # kdump status on Current Image - parser.add_argument('--status', action='store_true', - help='Show kdump status') - # kdump status on Current Image parser.add_argument('--status-json', action='store_true', help='Show kdump status in json format') @@ -726,7 +642,6 @@ def main(): parser.add_argument('--kdump-records-json', action='store_true', help='Show kdump records in json format') - # kdump config on Current Image # kdump config on Current Image parser.add_argument('--config-json', action='store_true', help='Show kdump config in json format') @@ -739,14 +654,6 @@ def main(): parser.add_argument('--memory', nargs='?', type=str, action='store', default=False, help='Amount of memory reserved for the capture kernel') - # Capture kernel files - parser.add_argument('--files', action='store_true', - help='Show stored capture kernel files') - - # Capture kernel file - parser.add_argument('--file', nargs=1, type=str, - help='Show stored capture kernel file') - # Show more information (used for sonic-kdump-config status) parser.add_argument("-v", "--verbose", action='store_true', help='displays detailed kdump status information. Used with status command.') @@ -776,12 +683,6 @@ def main(): cmd_kdump_memory(options.verbose, options.memory) elif options.num_dumps != False: cmd_kdump_num_dumps(options.verbose, options.num_dumps) - elif options.status: - cmd_kdump_status() - elif options.files != False: - cmd_kdump_files() - elif options.file: - cmd_kdump_file(options.lines, options.file[0]) elif options.dump_db: cmd_dump_db() elif options.status_json: diff --git a/show/kdump.py b/show/kdump.py index d846792797e6..c0eb609a1dd7 100644 --- a/show/kdump.py +++ b/show/kdump.py @@ -1,85 +1,189 @@ +import itertools +import os +import sys + import click +from tabulate import tabulate + import utilities_common.cli as clicommon from swsscommon.swsscommon import ConfigDBConnector # -# 'kdump command ("show kdump ...") +# 'kdump' group (show kdump ...) # @click.group(cls=clicommon.AliasedGroup, name="kdump") def kdump(): - """Show kdump configuration, status and information """ + """Show kdump configuration, dump files and dmesg logs""" pass -@kdump.command('enabled') -def enabled(): - """Show if kdump is enabled or disabled""" - kdump_is_enabled = False + +def get_kdump_config(field_name): + """Fetches the configuration of Kdump from `CONFIG_DB`. + + Args: + field_name: A string contains the field name in the sub-table of 'config'. + + Returns: + field_value: If field name was found, then returns the corresponding value. + Otherwise, returns "Unknown". + """ + field_value = "Unknown" config_db = ConfigDBConnector() - if config_db is not None: - config_db.connect() - table_data = config_db.get_table('KDUMP') - if table_data is not None: - config_data = table_data.get('config') - if config_data is not None: - if config_data.get('enabled').lower() == 'true': - kdump_is_enabled = True - if kdump_is_enabled: - click.echo("kdump is enabled") + config_db.connect() + kdump_table = config_db.get_table("KDUMP") + if kdump_table and "config" in kdump_table and field_name in kdump_table["config"]: + field_value = kdump_table["config"][field_name] + + return field_value + + +def get_kdump_oper_mode(): + """Fetches the operational mode of Kdump from the execution result of command + `/usr/sbin/kdump-config status`. + + Args: + None. + + Returns: + admin_mode: If Kdump is ready, returns "Ready"; If Kdump is not ready, + returns "Not Ready"; + """ + oper_mode = "Not Ready" + command_stdout = clicommon.run_command("/usr/sbin/kdump-config status", return_cmd=True) + + for line in command_stdout.splitlines(): + if ": ready to kdump" in line: + oper_mode = "Ready" + break + + return oper_mode + + +# +# 'config' subcommand (show kdump config) +# +@kdump.command(name="config", short_help="Show the configuration of Linux kernel dump") +def config(): + admin_mode = "Disabled" + admin_enabled = get_kdump_config("enabled") + if admin_enabled == "true": + admin_mode = "Enabled" + + oper_mode = get_kdump_oper_mode() + + click.echo("Kdump administrative mode: {}".format(admin_mode)) + if admin_mode == "Enabled" and oper_mode == "Not Ready": + click.echo("Kdump operational mode: Ready after reboot") else: - click.echo("kdump is disabled") - -@kdump.command('status') -def status(): - """Show kdump status""" - clicommon.run_command("sonic-kdump-config --status") - clicommon.run_command("sonic-kdump-config --memory") - clicommon.run_command("sonic-kdump-config --num_dumps") - clicommon.run_command("sonic-kdump-config --files") - -@kdump.command('memory') -def memory(): - """Show kdump memory information""" - kdump_memory = "0M-2G:256M,2G-4G:320M,4G-8G:384M,8G-:448M" - config_db = ConfigDBConnector() - if config_db is not None: - config_db.connect() - table_data = config_db.get_table('KDUMP') - if table_data is not None: - config_data = table_data.get('config') - if config_data is not None: - kdump_memory_from_db = config_data.get('memory') - if kdump_memory_from_db is not None: - kdump_memory = kdump_memory_from_db - click.echo("Memory Reserved: {}".format(kdump_memory)) - -@kdump.command('num_dumps') -def num_dumps(): - """Show kdump max number of dump files""" - kdump_num_dumps = "3" - config_db = ConfigDBConnector() - if config_db is not None: - config_db.connect() - table_data = config_db.get_table('KDUMP') - if table_data is not None: - config_data = table_data.get('config') - if config_data is not None: - kdump_num_dumps_from_db = config_data.get('num_dumps') - if kdump_num_dumps_from_db is not None: - kdump_num_dumps = kdump_num_dumps_from_db - click.echo("Maximum number of Kernel Core files Stored: {}".format(kdump_num_dumps)) - -@kdump.command('files') + click.echo("Kdump operational mode: {}".format(oper_mode)) + + mem_config = get_kdump_config("memory") + click.echo("Kdump memory researvation: {}".format(mem_config)) + + num_files_config = get_kdump_config("num_dumps") + click.echo("Maximum number of Kdump files: {}".format(num_files_config)) + + +def get_kdump_core_files(): + """Retrieves the kernel core dump files from directory '/var/crash/'. + + Args: + None. + + Returns: + cmd_message: A string contains the information showing the execution result + of 'find' command. + dump_file_list: A list contains kernel core dump files. + """ + find_core_dump_files = "find /var/crash -name 'kdump.*'" + dump_file_list = [] + cmd_message = None + + command_stdout = clicommon.run_command(find_core_dump_files, return_cmd=True) + + dump_file_list = command_stdout.splitlines() + if not dump_file_list: + cmd_message = "No kernel core dump file available!" + + return cmd_message, dump_file_list + + +def get_kdump_dmesg_files(): + """Retrieves the kernel dmesg files from directory '/var/crash/'. + + Args: + None. + + Returns: + cmd_message: A string contains the information showing the execution result + of 'find' command. + dmesg_file_list: A list contains kernel dmesg files. + """ + find_dmesg_files = "find /var/crash -name 'dmesg.*'" + dmesg_file_list = [] + cmd_message = None + + command_stdout = clicommon.run_command(find_dmesg_files, return_cmd=True) + + dmesg_file_list = command_stdout.splitlines() + if not dmesg_file_list: + cmd_message = "No kernel dmesg file available!" + + return cmd_message, dmesg_file_list + + +# +# 'files' subcommand (show kdump files) +# +@kdump.command(name="files", short_help="Show kernel core dump and dmesg files") def files(): - """Show kdump kernel core dump files""" - clicommon.run_command("sonic-kdump-config --files") - -@kdump.command() -@click.argument('record', required=True) -@click.argument('lines', metavar='', required=False) -def log(record, lines): - """Show kdump kernel core dump file kernel log""" - cmd = "sonic-kdump-config --file {}".format(record) - if lines is not None: - cmd += " --lines {}".format(lines) + core_file_result = [] + dmesg_file_result = [] + body = [] + + cmd_message, core_file_result = get_kdump_core_files() + if not core_file_result: + core_file_result.append(cmd_message) + + cmd_message, dmesg_file_result = get_kdump_dmesg_files() + if not dmesg_file_result: + dmesg_file_result.append(cmd_message) + + core_file_result.sort(reverse=True) + dmesg_file_result.sort(reverse=True) + + header = ["Kernel core dump files", "Kernel dmesg files"] + + for (core_file, dmesg_file) in itertools.zip_longest(core_file_result, dmesg_file_result, fillvalue=""): + body.append([core_file, dmesg_file]) + + click.echo(tabulate(body, header, stralign="center")) + + +# +# 'logging' subcommand (show kdump logging) +# +@kdump.command(name="logging", short_help="Show last 10 lines of lastest kernel dmesg file") +@click.argument('filename', required=False) +@click.option('-l', '--lines', default=10, show_default=True) +def logging(filename, lines): + cmd = "sudo tail -{}".format(lines) + + if filename: + timestamp = filename.strip().split(".")[-1] + file_path = "/var/crash/{}/{}".format(timestamp, filename) + if os.path.isfile(file_path): + cmd += " {}".format(file_path) + else: + click.echo("Invalid filename: '{}'!".format(filename)) + sys.exit(1) + else: + cmd_message, dmesg_file_result = get_kdump_dmesg_files() + if len(dmesg_file_result) == 0: + click.echo(cmd_message) + sys.exit(2) + + dmesg_file_result.sort(reverse=True) + cmd += " {}".format(dmesg_file_result[0]) clicommon.run_command(cmd)