Skip to content

Commit

Permalink
Fixes dropstat multi-asic behaviour by using multi-asic helpers
Browse files Browse the repository at this point in the history
and ensuring that dropstat iterates through correct namespaces
when 'show' command is run.
  • Loading branch information
bktsim-arista authored and arista-nwolfe committed Mar 25, 2024
1 parent e35452b commit 913220a
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 6 deletions.
25 changes: 20 additions & 5 deletions scripts/dropstat
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import sys
from collections import OrderedDict
from natsort import natsorted
from tabulate import tabulate
from sonic_py_common import multi_asic
from utilities_common.general import load_db_config

# mock the redis for unit test purposes #
try:
Expand All @@ -28,9 +30,12 @@ try:
test_path = os.path.join(modules_path, "tests")
sys.path.insert(0, modules_path)
sys.path.insert(0, test_path)
import mock_tables.dbconnector
from tests.mock_tables import dbconnector
socket.gethostname = lambda: 'sonic_drops_test'
os.getuid = lambda: 27
if os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] == "multi_asic":
import tests.mock_tables.mock_multi_asic
dbconnector.load_namespace_config()
except KeyError:
pass

Expand Down Expand Up @@ -85,11 +90,11 @@ def get_dropstat_dir():


class DropStat(object):
def __init__(self):
self.config_db = ConfigDBConnector()
def __init__(self, namespace):
self.config_db = ConfigDBConnector(namespace=namespace, use_unix_socket_path=True if namespace else False)
self.config_db.connect()

self.db = SonicV2Connector(use_unix_socket_path=False)
self.db = SonicV2Connector(namespace=namespace, use_unix_socket_path=True if namespace else False)
self.db.connect(self.db.COUNTERS_DB)
self.db.connect(self.db.ASIC_DB)
self.db.connect(self.db.APPL_DB)
Expand Down Expand Up @@ -403,15 +408,25 @@ Examples:
# Variables
parser.add_argument('-g', '--group', type=str, help='The group of the target drop counter', default=None)
parser.add_argument('-t', '--type', type=str, help='The type of the target drop counter', default=None)
parser.add_argument('-n', '--namespace', type=str, help='Namespace name', default=None)

args = parser.parse_args()

command = args.command

group = args.group
counter_type = args.type
namespace = args.namespace

dcstat = DropStat()
load_db_config()
namespaces = multi_asic.get_namespace_list()
if namespace and namespace not in namespaces:
raise Exception("Input arguments error. Namespaces must be one of", *namespaces)

if multi_asic.is_multi_asic() and not namespace:
raise Exception("Input arguments error. Namespace must be specified for multi-asic devices.")

dcstat = DropStat(namespace)
if command == 'clear':
dcstat.clear_drop_counts()
elif command == 'show':
Expand Down
7 changes: 6 additions & 1 deletion show/dropcounters.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import click
import utilities_common.cli as clicommon
import utilities_common.multi_asic as multi_asic_util


#
Expand Down Expand Up @@ -41,7 +42,8 @@ def capabilities(verbose):
@click.option('-g', '--group', required=False)
@click.option('-t', '--counter_type', required=False)
@click.option('--verbose', is_flag=True, help="Enable verbose output")
def counts(group, counter_type, verbose):
@multi_asic_util.multi_asic_click_option_namespace
def counts(group, counter_type, verbose, namespace):
"""Show drop counts"""
cmd = ['dropstat', '-c', 'show']

Expand All @@ -50,5 +52,8 @@ def counts(group, counter_type, verbose):

if counter_type:
cmd += ['-t', str(counter_type)]

if namespace:
cmd += ['-n', str(namespace)]

clicommon.run_command(cmd, display_cmd=verbose)
59 changes: 59 additions & 0 deletions tests/multi_asic_dropstat_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import os
import sys
import shutil
from utils import get_result_and_return_code

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)

dropstat_path = "/tmp/dropstat-27"

dropstat_masic_result="""\
IFACE STATE RX_ERR RX_DROPS TX_ERR TX_DROPS DEBUG_0 DEBUG_2
------------ ------- -------- ---------- -------- ---------- --------- ---------
Ethernet0 U 0 0 0 0 0 0
Ethernet4 U 0 0 0 0 0 0
Ethernet-BP0 U 0 1000 0 0 800 100
Ethernet-BP4 U 0 1000 0 0 800 100
DEVICE DEBUG_1
---------------- ---------
sonic_drops_test 1000
"""

class TestMultiAsicDropstat(object):
@classmethod
def setup_class(cls):
if os.path.exists(dropstat_path):
shutil.rmtree(dropstat_path)
os.environ["PATH"] += os.pathsep + scripts_path
os.environ["UTILITIES_UNIT_TESTING"] = "1"
os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = "multi_asic"
print("SETUP")

def test_show_pg_drop_masic(self):
return_code, result = get_result_and_return_code([
'dropstat', '-c', 'show', '-n', 'asic0'
])
print("return_code: {}".format(return_code))
print("result = {}".format(result))
assert return_code == 0
assert result == dropstat_masic_result

def test_show_pg_drop_masic_invalid_ns(self):
return_code, result = get_result_and_return_code([
'dropstat', '-c', 'show', '-n', 'asic5'
])
print("return_code: {}".format(return_code))
print("result = {}".format(result))
assert return_code == 1

@classmethod
def teardown_class(cls):
os.environ["PATH"] = os.pathsep.join(os.environ["PATH"].split(os.pathsep)[:-1])
os.environ['UTILITIES_UNIT_TESTING'] = "0"
os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = ""
print("TEARDOWN")

0 comments on commit 913220a

Please sign in to comment.