From d5f538200b3abfb108e385c91d6b7c93746611ca Mon Sep 17 00:00:00 2001 From: Mahesh Maddikayala <10645050+smaheshm@users.noreply.github.com> Date: Fri, 16 Apr 2021 10:41:33 -0700 Subject: [PATCH] [CLI][queue counters] add JSON output option for queue counters (#1505) + added tests for 'show queue counters' CLI --- scripts/queuestat | 125 +++- show/main.py | 6 +- tests/mock_tables/counters_db.json | 434 ++++++++++++- tests/queue_counter_test.py | 960 +++++++++++++++++++++++++++++ utilities_common/cli.py | 12 +- 5 files changed, 1508 insertions(+), 29 deletions(-) create mode 100644 tests/queue_counter_test.py diff --git a/scripts/queuestat b/scripts/queuestat index 24369c82a53e..b7f4f1d3821c 100755 --- a/scripts/queuestat +++ b/scripts/queuestat @@ -2,7 +2,7 @@ ##################################################################### # -# queuestat is a tool for summarizing queue statistics of all ports. +# queuestat is a tool for summarizing queue statistics of all ports. # ##################################################################### @@ -10,13 +10,25 @@ import _pickle as pickle import argparse import datetime import os.path -from swsscommon.swsscommon import SonicV2Connector import sys from collections import namedtuple, OrderedDict from natsort import natsorted from tabulate import tabulate +# mock the redis for unit test purposes # +try: + if os.environ["UTILITIES_UNIT_TESTING"] == "2": + modules_path = os.path.join(os.path.dirname(__file__), "..") + tests_path = os.path.join(modules_path, "tests") + sys.path.insert(0, modules_path) + sys.path.insert(0, tests_path) + import mock_tables.dbconnector # lgtm [py/unused-import] + +except KeyError: + pass + +from swsscommon.swsscommon import SonicV2Connector QueueStats = namedtuple("QueueStats", "queueindex, queuetype, totalpacket, totalbytes, droppacket, dropbytes") header = ['Port', 'TxQ', 'Counter/pkts', 'Counter/bytes', 'Drop/pkts', 'Drop/bytes'] @@ -28,6 +40,7 @@ counter_bucket_dict = { 'SAI_QUEUE_STAT_DROPPED_BYTES': 5, } +from utilities_common.cli import json_dump from utilities_common.netstat import ns_diff, STATUS_NA QUEUE_TYPE_MC = 'MC' @@ -47,6 +60,24 @@ COUNTERS_QUEUE_PORT_MAP = "COUNTERS_QUEUE_PORT_MAP" cnstat_dir = 'N/A' cnstat_fqn_file = 'N/A' + +def build_json(port, cnstat): + def ports_stats(k): + p = {} + p[k[1]] = { + "totalpacket": k[2], + "totalbytes": k[3], + "droppacket": k[4], + "dropbytes": k[5] + } + return p + + out = {} + for k in cnstat: + out.update(ports_stats(k)) + return out + + class Queuestat(object): def __init__(self): self.db = SonicV2Connector(use_unix_socket_path=False) @@ -134,33 +165,45 @@ class Queuestat(object): if queue_map is None: return cnstat_dict for queue in natsorted(queue_map): - cnstat_dict[queue] = get_counters(queue_map[queue]) + cnstat_dict[queue] = get_counters(queue_map[queue]) return cnstat_dict - def cnstat_print(self, port, cnstat_dict): + def cnstat_print(self, port, cnstat_dict, json_opt): """ - Print the cnstat. + Print the cnstat. If JSON option is True, return data in + JSON format. """ table = [] + json_output = {port: {}} for key, data in cnstat_dict.items(): if key == 'time': + if json_opt: + json_output[port][key] = data continue table.append((port, data.queuetype + str(data.queueindex), data.totalpacket, data.totalbytes, data.droppacket, data.dropbytes)) - print(tabulate(table, header, tablefmt='simple', stralign='right')) - print() + if json_opt: + json_output[port].update(build_json(port, table)) + return json_output + else: + print(tabulate(table, header, tablefmt='simple', stralign='right')) + print() - def cnstat_diff_print(self, port, cnstat_new_dict, cnstat_old_dict): + def cnstat_diff_print(self, port, cnstat_new_dict, cnstat_old_dict, json_opt): """ - Print the difference between two cnstat results. + Print the difference between two cnstat results. If JSON + option is True, return data in JSON format. """ table = [] + json_output = {port: {}} for key, cntr in cnstat_new_dict.items(): if key == 'time': + if json_opt: + json_output[port][key] = cntr continue old_cntr = None if key in cnstat_old_dict: @@ -177,26 +220,50 @@ class Queuestat(object): cntr.totalpacket, cntr.totalbytes, cntr.droppacket, cntr.dropbytes)) - print(tabulate(table, header, tablefmt='simple', stralign='right')) - print() + if json_opt: + json_output[port].update(build_json(port, table)) + return json_output + else: + print(tabulate(table, header, tablefmt='simple', stralign='right')) + print() - def get_print_all_stat(self): - # Get stat for each port + def get_print_all_stat(self, json_opt): + """ + Get stat for each port + If JSON option is True, collect data for each port and + print data in JSON format for all ports + """ + json_output = {} for port in natsorted(self.counter_port_name_map): + json_output[port] = {} cnstat_dict = self.get_cnstat(self.port_queues_map[port]) cnstat_fqn_file_name = cnstat_fqn_file + port if os.path.isfile(cnstat_fqn_file_name): try: cnstat_cached_dict = pickle.load(open(cnstat_fqn_file_name, 'rb')) - print(port + " Last cached time was " + str(cnstat_cached_dict.get('time'))) - self.cnstat_diff_print(port, cnstat_dict, cnstat_cached_dict) + if json_opt: + json_output[port].update({"cached_time":cnstat_cached_dict.get('time')}) + json_output.update(self.cnstat_diff_print(port, cnstat_dict, cnstat_cached_dict, json_opt)) + else: + print(port + " Last cached time was " + str(cnstat_cached_dict.get('time'))) + self.cnstat_diff_print(port, cnstat_dict, cnstat_cached_dict, json_opt) except IOError as e: print(e.errno, e) else: - self.cnstat_print(port, cnstat_dict) + if json_opt: + json_output.update(self.cnstat_print(port, cnstat_dict, json_opt)) + else: + self.cnstat_print(port, cnstat_dict, json_opt) - def get_print_port_stat(self, port): + if json_opt: + print(json_dump(json_output)) + + def get_print_port_stat(self, port, json_opt): + """ + Get stat for the port + If JSON option is True print data in JSON format + """ if not port in self.port_queues_map: print("Port doesn't exist!", port) sys.exit(1) @@ -204,15 +271,27 @@ class Queuestat(object): # Get stat for the port queried cnstat_dict = self.get_cnstat(self.port_queues_map[port]) cnstat_fqn_file_name = cnstat_fqn_file + port + json_output = {} + json_output[port] = {} if os.path.isfile(cnstat_fqn_file_name): try: cnstat_cached_dict = pickle.load(open(cnstat_fqn_file_name, 'rb')) - print("Last cached time was " + str(cnstat_cached_dict.get('time'))) - self.cnstat_diff_print(port, cnstat_dict, cnstat_cached_dict) + if json_opt: + json_output[port].update({"cached_time":cnstat_cached_dict.get('time')}) + json_output.update(self.cnstat_diff_print(port, cnstat_dict, cnstat_cached_dict, json_opt)) + else: + print("Last cached time was " + str(cnstat_cached_dict.get('time'))) + self.cnstat_diff_print(port, cnstat_dict, cnstat_cached_dict, json_opt) except IOError as e: print(e.errno, e) else: - self.cnstat_print(port, cnstat_dict) + if json_opt: + json_output.update(self.cnstat_print(port, cnstat_dict, json_opt)) + else: + self.cnstat_print(port, cnstat_dict, json_opt) + + if json_opt: + print(json_dump(json_output)) def save_fresh_stats(self): if not os.path.exists(cnstat_dir): @@ -251,10 +330,12 @@ Examples: parser.add_argument('-c', '--clear', action='store_true', help='Clear previous stats and save new ones') parser.add_argument('-d', '--delete', action='store_true', help='Delete saved stats') parser.add_argument('-v', '--version', action='version', version='%(prog)s 1.0') + parser.add_argument('-j', '--json_opt', action='store_true', help='Print in JSON format') args = parser.parse_args() save_fresh_stats = args.clear delete_all_stats = args.delete + json_opt = args.json_opt port_to_show_stats = args.port @@ -282,9 +363,9 @@ Examples: sys.exit(0) if port_to_show_stats!=None: - queuestat.get_print_port_stat(port_to_show_stats) + queuestat.get_print_port_stat(port_to_show_stats, json_opt) else: - queuestat.get_print_all_stat() + queuestat.get_print_all_stat(json_opt) sys.exit(0) diff --git a/show/main.py b/show/main.py index 8dbe740e716e..16f5d8cec72f 100755 --- a/show/main.py +++ b/show/main.py @@ -520,7 +520,8 @@ def queue(): @queue.command() @click.argument('interfacename', required=False) @click.option('--verbose', is_flag=True, help="Enable verbose output") -def counters(interfacename, verbose): +@click.option('--json', is_flag=True, help="JSON output") +def counters(interfacename, verbose, json): """Show queue counters""" cmd = "queuestat" @@ -532,6 +533,9 @@ def counters(interfacename, verbose): if interfacename is not None: cmd += " -p {}".format(interfacename) + if json: + cmd += " -j" + run_command(cmd, display_cmd=verbose) # diff --git a/tests/mock_tables/counters_db.json b/tests/mock_tables/counters_db.json index 3d9164e1d8ac..4765556f4595 100644 --- a/tests/mock_tables/counters_db.json +++ b/tests/mock_tables/counters_db.json @@ -1,4 +1,403 @@ { + "COUNTERS:oid:0x15000000000357": { + "SAI_QUEUE_STAT_BYTES": "30", + "SAI_QUEUE_STAT_DROPPED_BYTES": "74", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "56", + "SAI_QUEUE_STAT_PACKETS": "68", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "61" + }, + "COUNTERS:oid:0x15000000000358": { + "SAI_QUEUE_STAT_BYTES": "43", + "SAI_QUEUE_STAT_DROPPED_BYTES": "1", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "39", + "SAI_QUEUE_STAT_PACKETS": "60", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "88" + }, + "COUNTERS:oid:0x15000000000359": { + "SAI_QUEUE_STAT_BYTES": "7", + "SAI_QUEUE_STAT_DROPPED_BYTES": "21", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "39", + "SAI_QUEUE_STAT_PACKETS": "82", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "4" + }, + "COUNTERS:oid:0x1500000000035b": { + "SAI_QUEUE_STAT_BYTES": "59", + "SAI_QUEUE_STAT_DROPPED_BYTES": "94", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "12", + "SAI_QUEUE_STAT_PACKETS": "11", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "15" + }, + "COUNTERS:oid:0x1500000000035c": { + "SAI_QUEUE_STAT_BYTES": "62", + "SAI_QUEUE_STAT_DROPPED_BYTES": "40", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "35", + "SAI_QUEUE_STAT_PACKETS": "36", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "18" + }, + "COUNTERS:oid:0x1500000000035d": { + "SAI_QUEUE_STAT_BYTES": "91", + "SAI_QUEUE_STAT_DROPPED_BYTES": "88", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "2", + "SAI_QUEUE_STAT_PACKETS": "49", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "73" + }, + "COUNTERS:oid:0x1500000000035e": { + "SAI_QUEUE_STAT_BYTES": "17", + "SAI_QUEUE_STAT_DROPPED_BYTES": "74", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "94", + "SAI_QUEUE_STAT_PACKETS": "33", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "98" + }, + "COUNTERS:oid:0x1500000000035f": { + "SAI_QUEUE_STAT_BYTES": "71", + "SAI_QUEUE_STAT_DROPPED_BYTES": "33", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "95", + "SAI_QUEUE_STAT_PACKETS": "40", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "81" + }, + "COUNTERS:oid:0x15000000000360": { + "SAI_QUEUE_STAT_BYTES": "8", + "SAI_QUEUE_STAT_DROPPED_BYTES": "78", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "93", + "SAI_QUEUE_STAT_PACKETS": "54", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "59" + }, + "COUNTERS:oid:0x15000000000363": { + "SAI_QUEUE_STAT_BYTES": "96", + "SAI_QUEUE_STAT_DROPPED_BYTES": "9", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "74", + "SAI_QUEUE_STAT_PACKETS": "83", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "12" + }, + "COUNTERS:oid:0x15000000000364": { + "SAI_QUEUE_STAT_BYTES": "60", + "SAI_QUEUE_STAT_DROPPED_BYTES": "31", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "61", + "SAI_QUEUE_STAT_PACKETS": "15", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "0" + }, + "COUNTERS:oid:0x15000000000365": { + "SAI_QUEUE_STAT_BYTES": "52", + "SAI_QUEUE_STAT_DROPPED_BYTES": "94", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "82", + "SAI_QUEUE_STAT_PACKETS": "45", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "68" + }, + "COUNTERS:oid:0x15000000000366": { + "SAI_QUEUE_STAT_BYTES": "88", + "SAI_QUEUE_STAT_DROPPED_BYTES": "52", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "89", + "SAI_QUEUE_STAT_PACKETS": "55", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "18" + }, + "COUNTERS:oid:0x15000000000367": { + "SAI_QUEUE_STAT_BYTES": "70", + "SAI_QUEUE_STAT_DROPPED_BYTES": "79", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "95", + "SAI_QUEUE_STAT_PACKETS": "14", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "21" + }, + "COUNTERS:oid:0x15000000000368": { + "SAI_QUEUE_STAT_BYTES": "60", + "SAI_QUEUE_STAT_DROPPED_BYTES": "81", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "66", + "SAI_QUEUE_STAT_PACKETS": "68", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "98" + }, + "COUNTERS:oid:0x15000000000369": { + "SAI_QUEUE_STAT_BYTES": "4", + "SAI_QUEUE_STAT_DROPPED_BYTES": "76", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "48", + "SAI_QUEUE_STAT_PACKETS": "63", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "93" + }, + "COUNTERS:oid:0x1500000000036a": { + "SAI_QUEUE_STAT_BYTES": "73", + "SAI_QUEUE_STAT_DROPPED_BYTES": "74", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "77", + "SAI_QUEUE_STAT_PACKETS": "41", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "50" + }, + "COUNTERS:oid:0x1500000000036b": { + "SAI_QUEUE_STAT_BYTES": "21", + "SAI_QUEUE_STAT_DROPPED_BYTES": "54", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "56", + "SAI_QUEUE_STAT_PACKETS": "60", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "30" + }, + "COUNTERS:oid:0x1500000000036c": { + "SAI_QUEUE_STAT_BYTES": "31", + "SAI_QUEUE_STAT_DROPPED_BYTES": "39", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "12", + "SAI_QUEUE_STAT_PACKETS": "57", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "20" + }, + "COUNTERS:oid:0x1500000000037f": { + "SAI_QUEUE_STAT_BYTES": "96", + "SAI_QUEUE_STAT_DROPPED_BYTES": "98", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "70", + "SAI_QUEUE_STAT_PACKETS": "41", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "46" + }, + "COUNTERS:oid:0x15000000000380": { + "SAI_QUEUE_STAT_BYTES": "49", + "SAI_QUEUE_STAT_DROPPED_BYTES": "36", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "63", + "SAI_QUEUE_STAT_PACKETS": "18", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "18" + }, + "COUNTERS:oid:0x15000000000381": { + "SAI_QUEUE_STAT_BYTES": "90", + "SAI_QUEUE_STAT_DROPPED_BYTES": "15", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "3", + "SAI_QUEUE_STAT_PACKETS": "99", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "15" + }, + "COUNTERS:oid:0x15000000000383": { + "SAI_QUEUE_STAT_BYTES": "84", + "SAI_QUEUE_STAT_DROPPED_BYTES": "94", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "82", + "SAI_QUEUE_STAT_PACKETS": "8", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "17" + }, + "COUNTERS:oid:0x15000000000384": { + "SAI_QUEUE_STAT_BYTES": "15", + "SAI_QUEUE_STAT_DROPPED_BYTES": "92", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "75", + "SAI_QUEUE_STAT_PACKETS": "83", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "42" + }, + "COUNTERS:oid:0x15000000000385": { + "SAI_QUEUE_STAT_BYTES": "26", + "SAI_QUEUE_STAT_DROPPED_BYTES": "71", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "50", + "SAI_QUEUE_STAT_PACKETS": "84", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "31" + }, + "COUNTERS:oid:0x15000000000386": { + "SAI_QUEUE_STAT_BYTES": "19", + "SAI_QUEUE_STAT_DROPPED_BYTES": "80", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "49", + "SAI_QUEUE_STAT_PACKETS": "27", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "4" + }, + "COUNTERS:oid:0x15000000000387": { + "SAI_QUEUE_STAT_BYTES": "89", + "SAI_QUEUE_STAT_DROPPED_BYTES": "33", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "13", + "SAI_QUEUE_STAT_PACKETS": "13", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "45" + }, + "COUNTERS:oid:0x15000000000388": { + "SAI_QUEUE_STAT_BYTES": "48", + "SAI_QUEUE_STAT_DROPPED_BYTES": "31", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "86", + "SAI_QUEUE_STAT_PACKETS": "43", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "6" + }, + "COUNTERS:oid:0x1500000000038b": { + "SAI_QUEUE_STAT_BYTES": "1", + "SAI_QUEUE_STAT_DROPPED_BYTES": "82", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "57", + "SAI_QUEUE_STAT_PACKETS": "50", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "5" + }, + "COUNTERS:oid:0x1500000000038c": { + "SAI_QUEUE_STAT_BYTES": "99", + "SAI_QUEUE_STAT_DROPPED_BYTES": "59", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "84", + "SAI_QUEUE_STAT_PACKETS": "67", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "32" + }, + "COUNTERS:oid:0x1500000000038d": { + "SAI_QUEUE_STAT_BYTES": "58", + "SAI_QUEUE_STAT_DROPPED_BYTES": "5", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "27", + "SAI_QUEUE_STAT_PACKETS": "4", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "17" + }, + "COUNTERS:oid:0x1500000000038e": { + "SAI_QUEUE_STAT_BYTES": "5", + "SAI_QUEUE_STAT_DROPPED_BYTES": "39", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "57", + "SAI_QUEUE_STAT_PACKETS": "74", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "99" + }, + "COUNTERS:oid:0x1500000000038f": { + "SAI_QUEUE_STAT_BYTES": "59", + "SAI_QUEUE_STAT_DROPPED_BYTES": "14", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "4", + "SAI_QUEUE_STAT_PACKETS": "21", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "71" + }, + "COUNTERS:oid:0x15000000000390": { + "SAI_QUEUE_STAT_BYTES": "61", + "SAI_QUEUE_STAT_DROPPED_BYTES": "53", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "19", + "SAI_QUEUE_STAT_PACKETS": "24", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "56" + }, + "COUNTERS:oid:0x15000000000391": { + "SAI_QUEUE_STAT_BYTES": "15", + "SAI_QUEUE_STAT_DROPPED_BYTES": "32", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "15", + "SAI_QUEUE_STAT_PACKETS": "51", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "50" + }, + "COUNTERS:oid:0x15000000000392": { + "SAI_QUEUE_STAT_BYTES": "18", + "SAI_QUEUE_STAT_DROPPED_BYTES": "15", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "23", + "SAI_QUEUE_STAT_PACKETS": "98", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "4" + }, + "COUNTERS:oid:0x15000000000393": { + "SAI_QUEUE_STAT_BYTES": "34", + "SAI_QUEUE_STAT_DROPPED_BYTES": "57", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "9", + "SAI_QUEUE_STAT_PACKETS": "41", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "61" + }, + "COUNTERS:oid:0x15000000000394": { + "SAI_QUEUE_STAT_BYTES": "7", + "SAI_QUEUE_STAT_DROPPED_BYTES": "99", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "18", + "SAI_QUEUE_STAT_PACKETS": "57", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "49" + }, + "COUNTERS:oid:0x150000000003a7": { + "SAI_QUEUE_STAT_BYTES": "5", + "SAI_QUEUE_STAT_DROPPED_BYTES": "56", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "36", + "SAI_QUEUE_STAT_PACKETS": "19", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "65" + }, + "COUNTERS:oid:0x150000000003a8": { + "SAI_QUEUE_STAT_BYTES": "17", + "SAI_QUEUE_STAT_DROPPED_BYTES": "91", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "68", + "SAI_QUEUE_STAT_PACKETS": "38", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "94" + }, + "COUNTERS:oid:0x150000000003a9": { + "SAI_QUEUE_STAT_BYTES": "65", + "SAI_QUEUE_STAT_DROPPED_BYTES": "51", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "79", + "SAI_QUEUE_STAT_PACKETS": "16", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "71" + }, + "COUNTERS:oid:0x150000000003aa": { + "SAI_QUEUE_STAT_BYTES": "97", + "SAI_QUEUE_STAT_DROPPED_BYTES": "72", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "63", + "SAI_QUEUE_STAT_PACKETS": "11", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "51" + }, + "COUNTERS:oid:0x150000000003ac": { + "SAI_QUEUE_STAT_BYTES": "84", + "SAI_QUEUE_STAT_DROPPED_BYTES": "59", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "30", + "SAI_QUEUE_STAT_PACKETS": "13", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "47" + }, + "COUNTERS:oid:0x150000000003ad": { + "SAI_QUEUE_STAT_BYTES": "67", + "SAI_QUEUE_STAT_DROPPED_BYTES": "85", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "99", + "SAI_QUEUE_STAT_PACKETS": "49", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "86" + }, + "COUNTERS:oid:0x150000000003ae": { + "SAI_QUEUE_STAT_BYTES": "63", + "SAI_QUEUE_STAT_DROPPED_BYTES": "88", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "38", + "SAI_QUEUE_STAT_PACKETS": "2", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "98" + }, + "COUNTERS:oid:0x150000000003af": { + "SAI_QUEUE_STAT_BYTES": "82", + "SAI_QUEUE_STAT_DROPPED_BYTES": "43", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "93", + "SAI_QUEUE_STAT_PACKETS": "0", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "50" + }, + "COUNTERS:oid:0x150000000003b0": { + "SAI_QUEUE_STAT_BYTES": "17", + "SAI_QUEUE_STAT_DROPPED_BYTES": "61", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "91", + "SAI_QUEUE_STAT_PACKETS": "80", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "91" + }, + "COUNTERS:oid:0x150000000003b3": { + "SAI_QUEUE_STAT_BYTES": "63", + "SAI_QUEUE_STAT_DROPPED_BYTES": "73", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "76", + "SAI_QUEUE_STAT_PACKETS": "81", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "12" + }, + "COUNTERS:oid:0x150000000003b4": { + "SAI_QUEUE_STAT_BYTES": "16", + "SAI_QUEUE_STAT_DROPPED_BYTES": "66", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "29", + "SAI_QUEUE_STAT_PACKETS": "29", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "32" + }, + "COUNTERS:oid:0x150000000003b5": { + "SAI_QUEUE_STAT_BYTES": "12", + "SAI_QUEUE_STAT_DROPPED_BYTES": "35", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "61", + "SAI_QUEUE_STAT_PACKETS": "32", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "89" + }, + "COUNTERS:oid:0x150000000003b6": { + "SAI_QUEUE_STAT_BYTES": "17", + "SAI_QUEUE_STAT_DROPPED_BYTES": "93", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "72", + "SAI_QUEUE_STAT_PACKETS": "79", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "49" + }, + "COUNTERS:oid:0x150000000003b7": { + "SAI_QUEUE_STAT_BYTES": "21", + "SAI_QUEUE_STAT_DROPPED_BYTES": "50", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "67", + "SAI_QUEUE_STAT_PACKETS": "23", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "4" + }, + "COUNTERS:oid:0x150000000003b8": { + "SAI_QUEUE_STAT_BYTES": "10", + "SAI_QUEUE_STAT_DROPPED_BYTES": "14", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "97", + "SAI_QUEUE_STAT_PACKETS": "37", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "32" + }, + "COUNTERS:oid:0x150000000003b9": { + "SAI_QUEUE_STAT_BYTES": "17", + "SAI_QUEUE_STAT_DROPPED_BYTES": "43", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "74", + "SAI_QUEUE_STAT_PACKETS": "30", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "42" + }, + "COUNTERS:oid:0x150000000003ba": { + "SAI_QUEUE_STAT_BYTES": "63", + "SAI_QUEUE_STAT_DROPPED_BYTES": "84", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "54", + "SAI_QUEUE_STAT_PACKETS": "0", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "43" + }, + "COUNTERS:oid:0x150000000003bb": { + "SAI_QUEUE_STAT_BYTES": "88", + "SAI_QUEUE_STAT_DROPPED_BYTES": "79", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "24", + "SAI_QUEUE_STAT_PACKETS": "69", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "62" + }, + "COUNTERS:oid:0x150000000003bc": { + "SAI_QUEUE_STAT_BYTES": "12", + "SAI_QUEUE_STAT_DROPPED_BYTES": "3", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "84", + "SAI_QUEUE_STAT_PACKETS": "20", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "81" + }, "COUNTERS:oid:0x60000000005a3": { "SAI_ROUTER_INTERFACE_STAT_IN_ERROR_OCTETS": "0", "SAI_ROUTER_INTERFACE_STAT_IN_ERROR_PACKETS": "0", @@ -7,7 +406,12 @@ "SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_OCTETS": "0", "SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS": "0", "SAI_ROUTER_INTERFACE_STAT_OUT_OCTETS": "0", - "SAI_ROUTER_INTERFACE_STAT_OUT_PACKETS": "0" + "SAI_ROUTER_INTERFACE_STAT_OUT_PACKETS": "0", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "0", + "SAI_QUEUE_STAT_DROPPED_BYTES": "0", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "0", + "SAI_QUEUE_STAT_BYTES": "0", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "0" }, "COUNTERS:oid:0x60000000005a1": { "SAI_ROUTER_INTERFACE_STAT_IN_ERROR_OCTETS": "0", @@ -17,7 +421,12 @@ "SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_OCTETS": "0", "SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS": "0", "SAI_ROUTER_INTERFACE_STAT_OUT_OCTETS": "0", - "SAI_ROUTER_INTERFACE_STAT_OUT_PACKETS": "0" + "SAI_ROUTER_INTERFACE_STAT_OUT_PACKETS": "0", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "0", + "SAI_QUEUE_STAT_DROPPED_BYTES": "0", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "0", + "SAI_QUEUE_STAT_BYTES": "0", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "0" }, "COUNTERS:oid:0x600000000065f": { "SAI_ROUTER_INTERFACE_STAT_IN_ERROR_OCTETS": "1128", @@ -854,7 +1263,12 @@ "PFC_WD_QUEUE_STATS_TX_PACKETS_LAST": "0", "PFC_WD_RESTORATION_TIME": "600000", "PFC_WD_RESTORATION_TIME_LEFT": "600000", - "PFC_WD_STATUS": "stormed" + "PFC_WD_STATUS": "stormed", + "SAI_QUEUE_STAT_BYTES": "70", + "SAI_QUEUE_STAT_DROPPED_BYTES": "76", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "19", + "SAI_QUEUE_STAT_PACKETS": "52", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "60" }, "COUNTERS:oid:0x15000000000382": { "PFC_WD_ACTION": "drop", @@ -872,7 +1286,12 @@ "PFC_WD_QUEUE_STATS_TX_PACKETS_LAST": "0", "PFC_WD_RESTORATION_TIME": "600000", "PFC_WD_RESTORATION_TIME_LEFT": "600000", - "PFC_WD_STATUS": "operational" + "PFC_WD_STATUS": "operational", + "SAI_QUEUE_STAT_BYTES": "89", + "SAI_QUEUE_STAT_DROPPED_BYTES": "41", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "48", + "SAI_QUEUE_STAT_PACKETS": "60", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "99" }, "COUNTERS:oid:0x150000000003ab": { "PFC_WD_ACTION": "drop", @@ -890,7 +1309,12 @@ "PFC_WD_QUEUE_STATS_TX_PACKETS_LAST": "0", "PFC_WD_RESTORATION_TIME": "600000", "PFC_WD_RESTORATION_TIME_LEFT": "600000", - "PFC_WD_STATUS": "stormed" + "PFC_WD_STATUS": "stormed", + "SAI_QUEUE_STAT_BYTES": "89", + "SAI_QUEUE_STAT_DROPPED_BYTES": "62", + "SAI_QUEUE_STAT_DROPPED_PACKETS": "62", + "SAI_QUEUE_STAT_PACKETS": "54", + "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "97" }, "USER_WATERMARKS:oid:0x1a00000000034f": { "SAI_INGRESS_PRIORITY_GROUP_STAT_SHARED_WATERMARK_BYTES": "100", diff --git a/tests/queue_counter_test.py b/tests/queue_counter_test.py new file mode 100644 index 000000000000..66dfc828ed5c --- /dev/null +++ b/tests/queue_counter_test.py @@ -0,0 +1,960 @@ +import imp +import json +import os +import sys + +from click.testing import CliRunner +from unittest import TestCase +from swsscommon.swsscommon import ConfigDBConnector + +from .mock_tables import dbconnector + +import show.main as show +from utilities_common.cli import json_dump +from utilities_common.db import Db + +test_path = os.path.dirname(os.path.abspath(__file__)) +modules_path = os.path.dirname(test_path) +scripts_path = os.path.join(modules_path, "scripts") +sys.path.insert(0, test_path) +sys.path.insert(0, modules_path) + + +show_queue_counters = """\ + Port TxQ Counter/pkts Counter/bytes Drop/pkts Drop/bytes +--------- ----- -------------- --------------- ----------- ------------ +Ethernet0 UC0 68 30 56 74 +Ethernet0 UC1 60 43 39 1 +Ethernet0 UC2 82 7 39 21 +Ethernet0 UC3 52 70 19 76 +Ethernet0 UC4 11 59 12 94 +Ethernet0 UC5 36 62 35 40 +Ethernet0 UC6 49 91 2 88 +Ethernet0 UC7 33 17 94 74 +Ethernet0 UC8 40 71 95 33 +Ethernet0 UC9 54 8 93 78 +Ethernet0 MC10 83 96 74 9 +Ethernet0 MC11 15 60 61 31 +Ethernet0 MC12 45 52 82 94 +Ethernet0 MC13 55 88 89 52 +Ethernet0 MC14 14 70 95 79 +Ethernet0 MC15 68 60 66 81 +Ethernet0 MC16 63 4 48 76 +Ethernet0 MC17 41 73 77 74 +Ethernet0 MC18 60 21 56 54 +Ethernet0 MC19 57 31 12 39 +Ethernet0 ALL20 N/A N/A N/A N/A +Ethernet0 ALL21 N/A N/A N/A N/A +Ethernet0 ALL22 N/A N/A N/A N/A +Ethernet0 ALL23 N/A N/A N/A N/A +Ethernet0 ALL24 N/A N/A N/A N/A +Ethernet0 ALL25 N/A N/A N/A N/A +Ethernet0 ALL26 N/A N/A N/A N/A +Ethernet0 ALL27 N/A N/A N/A N/A +Ethernet0 ALL28 N/A N/A N/A N/A +Ethernet0 ALL29 N/A N/A N/A N/A + + Port TxQ Counter/pkts Counter/bytes Drop/pkts Drop/bytes +--------- ----- -------------- --------------- ----------- ------------ +Ethernet4 UC0 41 96 70 98 +Ethernet4 UC1 18 49 63 36 +Ethernet4 UC2 99 90 3 15 +Ethernet4 UC3 60 89 48 41 +Ethernet4 UC4 8 84 82 94 +Ethernet4 UC5 83 15 75 92 +Ethernet4 UC6 84 26 50 71 +Ethernet4 UC7 27 19 49 80 +Ethernet4 UC8 13 89 13 33 +Ethernet4 UC9 43 48 86 31 +Ethernet4 MC10 50 1 57 82 +Ethernet4 MC11 67 99 84 59 +Ethernet4 MC12 4 58 27 5 +Ethernet4 MC13 74 5 57 39 +Ethernet4 MC14 21 59 4 14 +Ethernet4 MC15 24 61 19 53 +Ethernet4 MC16 51 15 15 32 +Ethernet4 MC17 98 18 23 15 +Ethernet4 MC18 41 34 9 57 +Ethernet4 MC19 57 7 18 99 +Ethernet4 ALL20 N/A N/A N/A N/A +Ethernet4 ALL21 N/A N/A N/A N/A +Ethernet4 ALL22 N/A N/A N/A N/A +Ethernet4 ALL23 N/A N/A N/A N/A +Ethernet4 ALL24 N/A N/A N/A N/A +Ethernet4 ALL25 N/A N/A N/A N/A +Ethernet4 ALL26 N/A N/A N/A N/A +Ethernet4 ALL27 N/A N/A N/A N/A +Ethernet4 ALL28 N/A N/A N/A N/A +Ethernet4 ALL29 N/A N/A N/A N/A + + Port TxQ Counter/pkts Counter/bytes Drop/pkts Drop/bytes +--------- ----- -------------- --------------- ----------- ------------ +Ethernet8 UC0 19 5 36 56 +Ethernet8 UC1 38 17 68 91 +Ethernet8 UC2 16 65 79 51 +Ethernet8 UC3 11 97 63 72 +Ethernet8 UC4 54 89 62 62 +Ethernet8 UC5 13 84 30 59 +Ethernet8 UC6 49 67 99 85 +Ethernet8 UC7 2 63 38 88 +Ethernet8 UC8 0 82 93 43 +Ethernet8 UC9 80 17 91 61 +Ethernet8 MC10 81 63 76 73 +Ethernet8 MC11 29 16 29 66 +Ethernet8 MC12 32 12 61 35 +Ethernet8 MC13 79 17 72 93 +Ethernet8 MC14 23 21 67 50 +Ethernet8 MC15 37 10 97 14 +Ethernet8 MC16 30 17 74 43 +Ethernet8 MC17 0 63 54 84 +Ethernet8 MC18 69 88 24 79 +Ethernet8 MC19 20 12 84 3 +Ethernet8 ALL20 N/A N/A N/A N/A +Ethernet8 ALL21 N/A N/A N/A N/A +Ethernet8 ALL22 N/A N/A N/A N/A +Ethernet8 ALL23 N/A N/A N/A N/A +Ethernet8 ALL24 N/A N/A N/A N/A +Ethernet8 ALL25 N/A N/A N/A N/A +Ethernet8 ALL26 N/A N/A N/A N/A +Ethernet8 ALL27 N/A N/A N/A N/A +Ethernet8 ALL28 N/A N/A N/A N/A +Ethernet8 ALL29 N/A N/A N/A N/A + +""" + + +show_queue_counters_port = """\ + Port TxQ Counter/pkts Counter/bytes Drop/pkts Drop/bytes +--------- ----- -------------- --------------- ----------- ------------ +Ethernet8 UC0 19 5 36 56 +Ethernet8 UC1 38 17 68 91 +Ethernet8 UC2 16 65 79 51 +Ethernet8 UC3 11 97 63 72 +Ethernet8 UC4 54 89 62 62 +Ethernet8 UC5 13 84 30 59 +Ethernet8 UC6 49 67 99 85 +Ethernet8 UC7 2 63 38 88 +Ethernet8 UC8 0 82 93 43 +Ethernet8 UC9 80 17 91 61 +Ethernet8 MC10 81 63 76 73 +Ethernet8 MC11 29 16 29 66 +Ethernet8 MC12 32 12 61 35 +Ethernet8 MC13 79 17 72 93 +Ethernet8 MC14 23 21 67 50 +Ethernet8 MC15 37 10 97 14 +Ethernet8 MC16 30 17 74 43 +Ethernet8 MC17 0 63 54 84 +Ethernet8 MC18 69 88 24 79 +Ethernet8 MC19 20 12 84 3 +Ethernet8 ALL20 N/A N/A N/A N/A +Ethernet8 ALL21 N/A N/A N/A N/A +Ethernet8 ALL22 N/A N/A N/A N/A +Ethernet8 ALL23 N/A N/A N/A N/A +Ethernet8 ALL24 N/A N/A N/A N/A +Ethernet8 ALL25 N/A N/A N/A N/A +Ethernet8 ALL26 N/A N/A N/A N/A +Ethernet8 ALL27 N/A N/A N/A N/A +Ethernet8 ALL28 N/A N/A N/A N/A +Ethernet8 ALL29 N/A N/A N/A N/A + +""" + +show_queue_counters_json = """\ +{ + "Ethernet0": { + "ALL20": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL21": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL22": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL23": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL24": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL25": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL26": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL27": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL28": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL29": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "MC10": { + "dropbytes": "9", + "droppacket": "74", + "totalbytes": "96", + "totalpacket": "83" + }, + "MC11": { + "dropbytes": "31", + "droppacket": "61", + "totalbytes": "60", + "totalpacket": "15" + }, + "MC12": { + "dropbytes": "94", + "droppacket": "82", + "totalbytes": "52", + "totalpacket": "45" + }, + "MC13": { + "dropbytes": "52", + "droppacket": "89", + "totalbytes": "88", + "totalpacket": "55" + }, + "MC14": { + "dropbytes": "79", + "droppacket": "95", + "totalbytes": "70", + "totalpacket": "14" + }, + "MC15": { + "dropbytes": "81", + "droppacket": "66", + "totalbytes": "60", + "totalpacket": "68" + }, + "MC16": { + "dropbytes": "76", + "droppacket": "48", + "totalbytes": "4", + "totalpacket": "63" + }, + "MC17": { + "dropbytes": "74", + "droppacket": "77", + "totalbytes": "73", + "totalpacket": "41" + }, + "MC18": { + "dropbytes": "54", + "droppacket": "56", + "totalbytes": "21", + "totalpacket": "60" + }, + "MC19": { + "dropbytes": "39", + "droppacket": "12", + "totalbytes": "31", + "totalpacket": "57" + }, + "UC0": { + "dropbytes": "74", + "droppacket": "56", + "totalbytes": "30", + "totalpacket": "68" + }, + "UC1": { + "dropbytes": "1", + "droppacket": "39", + "totalbytes": "43", + "totalpacket": "60" + }, + "UC2": { + "dropbytes": "21", + "droppacket": "39", + "totalbytes": "7", + "totalpacket": "82" + }, + "UC3": { + "dropbytes": "76", + "droppacket": "19", + "totalbytes": "70", + "totalpacket": "52" + }, + "UC4": { + "dropbytes": "94", + "droppacket": "12", + "totalbytes": "59", + "totalpacket": "11" + }, + "UC5": { + "dropbytes": "40", + "droppacket": "35", + "totalbytes": "62", + "totalpacket": "36" + }, + "UC6": { + "dropbytes": "88", + "droppacket": "2", + "totalbytes": "91", + "totalpacket": "49" + }, + "UC7": { + "dropbytes": "74", + "droppacket": "94", + "totalbytes": "17", + "totalpacket": "33" + }, + "UC8": { + "dropbytes": "33", + "droppacket": "95", + "totalbytes": "71", + "totalpacket": "40" + }, + "UC9": { + "dropbytes": "78", + "droppacket": "93", + "totalbytes": "8", + "totalpacket": "54" + } + }, + "Ethernet4": { + "ALL20": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL21": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL22": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL23": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL24": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL25": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL26": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL27": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL28": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL29": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "MC10": { + "dropbytes": "82", + "droppacket": "57", + "totalbytes": "1", + "totalpacket": "50" + }, + "MC11": { + "dropbytes": "59", + "droppacket": "84", + "totalbytes": "99", + "totalpacket": "67" + }, + "MC12": { + "dropbytes": "5", + "droppacket": "27", + "totalbytes": "58", + "totalpacket": "4" + }, + "MC13": { + "dropbytes": "39", + "droppacket": "57", + "totalbytes": "5", + "totalpacket": "74" + }, + "MC14": { + "dropbytes": "14", + "droppacket": "4", + "totalbytes": "59", + "totalpacket": "21" + }, + "MC15": { + "dropbytes": "53", + "droppacket": "19", + "totalbytes": "61", + "totalpacket": "24" + }, + "MC16": { + "dropbytes": "32", + "droppacket": "15", + "totalbytes": "15", + "totalpacket": "51" + }, + "MC17": { + "dropbytes": "15", + "droppacket": "23", + "totalbytes": "18", + "totalpacket": "98" + }, + "MC18": { + "dropbytes": "57", + "droppacket": "9", + "totalbytes": "34", + "totalpacket": "41" + }, + "MC19": { + "dropbytes": "99", + "droppacket": "18", + "totalbytes": "7", + "totalpacket": "57" + }, + "UC0": { + "dropbytes": "98", + "droppacket": "70", + "totalbytes": "96", + "totalpacket": "41" + }, + "UC1": { + "dropbytes": "36", + "droppacket": "63", + "totalbytes": "49", + "totalpacket": "18" + }, + "UC2": { + "dropbytes": "15", + "droppacket": "3", + "totalbytes": "90", + "totalpacket": "99" + }, + "UC3": { + "dropbytes": "41", + "droppacket": "48", + "totalbytes": "89", + "totalpacket": "60" + }, + "UC4": { + "dropbytes": "94", + "droppacket": "82", + "totalbytes": "84", + "totalpacket": "8" + }, + "UC5": { + "dropbytes": "92", + "droppacket": "75", + "totalbytes": "15", + "totalpacket": "83" + }, + "UC6": { + "dropbytes": "71", + "droppacket": "50", + "totalbytes": "26", + "totalpacket": "84" + }, + "UC7": { + "dropbytes": "80", + "droppacket": "49", + "totalbytes": "19", + "totalpacket": "27" + }, + "UC8": { + "dropbytes": "33", + "droppacket": "13", + "totalbytes": "89", + "totalpacket": "13" + }, + "UC9": { + "dropbytes": "31", + "droppacket": "86", + "totalbytes": "48", + "totalpacket": "43" + } + }, + "Ethernet8": { + "ALL20": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL21": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL22": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL23": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL24": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL25": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL26": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL27": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL28": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL29": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "MC10": { + "dropbytes": "73", + "droppacket": "76", + "totalbytes": "63", + "totalpacket": "81" + }, + "MC11": { + "dropbytes": "66", + "droppacket": "29", + "totalbytes": "16", + "totalpacket": "29" + }, + "MC12": { + "dropbytes": "35", + "droppacket": "61", + "totalbytes": "12", + "totalpacket": "32" + }, + "MC13": { + "dropbytes": "93", + "droppacket": "72", + "totalbytes": "17", + "totalpacket": "79" + }, + "MC14": { + "dropbytes": "50", + "droppacket": "67", + "totalbytes": "21", + "totalpacket": "23" + }, + "MC15": { + "dropbytes": "14", + "droppacket": "97", + "totalbytes": "10", + "totalpacket": "37" + }, + "MC16": { + "dropbytes": "43", + "droppacket": "74", + "totalbytes": "17", + "totalpacket": "30" + }, + "MC17": { + "dropbytes": "84", + "droppacket": "54", + "totalbytes": "63", + "totalpacket": "0" + }, + "MC18": { + "dropbytes": "79", + "droppacket": "24", + "totalbytes": "88", + "totalpacket": "69" + }, + "MC19": { + "dropbytes": "3", + "droppacket": "84", + "totalbytes": "12", + "totalpacket": "20" + }, + "UC0": { + "dropbytes": "56", + "droppacket": "36", + "totalbytes": "5", + "totalpacket": "19" + }, + "UC1": { + "dropbytes": "91", + "droppacket": "68", + "totalbytes": "17", + "totalpacket": "38" + }, + "UC2": { + "dropbytes": "51", + "droppacket": "79", + "totalbytes": "65", + "totalpacket": "16" + }, + "UC3": { + "dropbytes": "72", + "droppacket": "63", + "totalbytes": "97", + "totalpacket": "11" + }, + "UC4": { + "dropbytes": "62", + "droppacket": "62", + "totalbytes": "89", + "totalpacket": "54" + }, + "UC5": { + "dropbytes": "59", + "droppacket": "30", + "totalbytes": "84", + "totalpacket": "13" + }, + "UC6": { + "dropbytes": "85", + "droppacket": "99", + "totalbytes": "67", + "totalpacket": "49" + }, + "UC7": { + "dropbytes": "88", + "droppacket": "38", + "totalbytes": "63", + "totalpacket": "2" + }, + "UC8": { + "dropbytes": "43", + "droppacket": "93", + "totalbytes": "82", + "totalpacket": "0" + }, + "UC9": { + "dropbytes": "61", + "droppacket": "91", + "totalbytes": "17", + "totalpacket": "80" + } + } +}""" + +show_queue_counters_port_json = """\ +{ + "Ethernet8": { + "ALL20": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL21": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL22": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL23": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL24": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL25": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL26": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL27": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL28": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "ALL29": { + "dropbytes": "N/A", + "droppacket": "N/A", + "totalbytes": "N/A", + "totalpacket": "N/A" + }, + "MC10": { + "dropbytes": "73", + "droppacket": "76", + "totalbytes": "63", + "totalpacket": "81" + }, + "MC11": { + "dropbytes": "66", + "droppacket": "29", + "totalbytes": "16", + "totalpacket": "29" + }, + "MC12": { + "dropbytes": "35", + "droppacket": "61", + "totalbytes": "12", + "totalpacket": "32" + }, + "MC13": { + "dropbytes": "93", + "droppacket": "72", + "totalbytes": "17", + "totalpacket": "79" + }, + "MC14": { + "dropbytes": "50", + "droppacket": "67", + "totalbytes": "21", + "totalpacket": "23" + }, + "MC15": { + "dropbytes": "14", + "droppacket": "97", + "totalbytes": "10", + "totalpacket": "37" + }, + "MC16": { + "dropbytes": "43", + "droppacket": "74", + "totalbytes": "17", + "totalpacket": "30" + }, + "MC17": { + "dropbytes": "84", + "droppacket": "54", + "totalbytes": "63", + "totalpacket": "0" + }, + "MC18": { + "dropbytes": "79", + "droppacket": "24", + "totalbytes": "88", + "totalpacket": "69" + }, + "MC19": { + "dropbytes": "3", + "droppacket": "84", + "totalbytes": "12", + "totalpacket": "20" + }, + "UC0": { + "dropbytes": "56", + "droppacket": "36", + "totalbytes": "5", + "totalpacket": "19" + }, + "UC1": { + "dropbytes": "91", + "droppacket": "68", + "totalbytes": "17", + "totalpacket": "38" + }, + "UC2": { + "dropbytes": "51", + "droppacket": "79", + "totalbytes": "65", + "totalpacket": "16" + }, + "UC3": { + "dropbytes": "72", + "droppacket": "63", + "totalbytes": "97", + "totalpacket": "11" + }, + "UC4": { + "dropbytes": "62", + "droppacket": "62", + "totalbytes": "89", + "totalpacket": "54" + }, + "UC5": { + "dropbytes": "59", + "droppacket": "30", + "totalbytes": "84", + "totalpacket": "13" + }, + "UC6": { + "dropbytes": "85", + "droppacket": "99", + "totalbytes": "67", + "totalpacket": "49" + }, + "UC7": { + "dropbytes": "88", + "droppacket": "38", + "totalbytes": "63", + "totalpacket": "2" + }, + "UC8": { + "dropbytes": "43", + "droppacket": "93", + "totalbytes": "82", + "totalpacket": "0" + }, + "UC9": { + "dropbytes": "61", + "droppacket": "91", + "totalbytes": "17", + "totalpacket": "80" + } + } +}""" + + +class TestQueue(object): + @classmethod + def setup_class(cls): + os.environ["PATH"] += os.pathsep + scripts_path + os.environ['UTILITIES_UNIT_TESTING'] = "2" + print("SETUP") + + def test_queue_counters(self): + runner = CliRunner() + result = runner.invoke( + show.cli.commands["queue"].commands["counters"], + [] + ) + print(result.output) + assert result.exit_code == 0 + assert result.output == show_queue_counters + + def test_queue_counters_port(self): + runner = CliRunner() + result = runner.invoke( + show.cli.commands["queue"].commands["counters"], + ["Ethernet8"] + ) + print(result.output) + assert result.exit_code == 0 + assert result.output == show_queue_counters_port + + def test_queue_counters_json(self): + runner = CliRunner() + result = runner.invoke( + show.cli.commands["queue"].commands["counters"], + ["--json"] + ) + assert result.exit_code == 0 + print(result.output) + json_output = json.loads(result.output) + + # remove "time" from the output + for _, v in json_output.items(): + del v["time"] + assert json_dump(json_output) == show_queue_counters_json + + def test_queue_counters_port_json(self): + runner = CliRunner() + result = runner.invoke( + show.cli.commands["queue"].commands["counters"], + ["Ethernet8 --json"] + ) + assert result.exit_code == 0 + print(result.output) + json_output = json.loads(result.output) + + # remove "time" from the output + for _, v in json_output.items(): + del v["time"] + assert json_dump(json_output) == show_queue_counters_port_json + + @classmethod + def teardown_class(cls): + os.environ["PATH"] = os.pathsep.join(os.environ["PATH"].split(os.pathsep)[:-1]) + os.environ['UTILITIES_UNIT_TESTING'] = "0" + print("TEARDOWN") diff --git a/utilities_common/cli.py b/utilities_common/cli.py index ed103649e4c5..afa42dc3b3c8 100644 --- a/utilities_common/cli.py +++ b/utilities_common/cli.py @@ -1,4 +1,5 @@ import configparser +import datetime import os import re import subprocess @@ -546,13 +547,22 @@ def run_command(command, display_cmd=False, ignore_error=False, return_cmd=False sys.exit(rc) +def json_serial(obj): + """JSON serializer for objects not serializable by default""" + + if isinstance(obj, (datetime.datetime, datetime.date)): + return obj.isoformat() + raise TypeError("Type %s not serializable" % type(obj)) + + def json_dump(data): """ Dump data in JSON format """ return json.dumps( - data, sort_keys=True, indent=2, ensure_ascii=False + data, sort_keys=True, indent=2, ensure_ascii=False, default=json_serial ) + def interface_is_untagged_member(db, interface_name): """ Check if interface is already untagged member"""