Skip to content

Commit

Permalink
[pfcwd][gcu] Add GCU testcases for pfcwd enable/disable scenario (son…
Browse files Browse the repository at this point in the history
…ic-net#8488)

Signed-off-by: Neetha John <[email protected]>

What is the motivation for this PR?
Added GCU testcase for pfcwd enable scenario (pfcwd start on single and all ports)
Enhanced existing pfcwd disable scenario to include all ports and moved it to this new file

How did you verify/test it?
Ran the testcase on 202205 branch and it passed

nejo@d1ee8b2d31c4:/var/nejo/tests$ ./run_tests.sh -n vms2-4-t0-2700 -i ../ansible/str,../ansible/veos -e "--skip_sanity --disable_loganalyzer" -t t0,any -c generic_config_updater/test_pfcwd_status.py -u
=== Running tests in groups ===
Running: pytest generic_config_updater/test_pfcwd_status.py --inventory ../ansible/str,../ansible/veos --host-pattern str-msn2700-22 --testbed vms2-4-t0-2700 --testbed_file /var/nejo/ansible/testbed.yaml --log-cli-level warning --log-file-level debug --kube_master unset --showlocals --assert plain --show-capture no -rav --allow_recover --ignore=ptftests --ignore=acstests --ignore=saitests --ignore=scripts --ignore=k8s --ignore=sai_qualify --junit-xml=logs/tr.xml --log-file=logs/test.log --topology t0,any --skip_sanity --disable_loganalyzer
/usr/local/lib/python2.7/dist-packages/ansible/parsing/vault/__init__.py:44: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in the next release.
  from cryptography.exceptions import InvalidSignature
========================================================================================================== test session starts ==========================================================================================================
platform linux2 -- Python 2.7.18, pytest-4.6.11, py-1.11.0, pluggy-0.13.1
ansible: 2.8.12
rootdir: /var/nejo/tests, inifile: pytest.ini
plugins: forked-1.3.0, metadata-1.11.0, ansible-2.2.4, celery-4.4.7, xdist-1.28.0, html-1.22.1, allure-pytest-2.8.22, repeat-0.9.1
collecting ... 
  from cryptography.exceptions import InvalidSignature
collected 4 items                                                                                                                                                                                                                       

generic_config_updater/test_pfcwd_status.py::test_stop_pfcwd[single] PASSED                                                                                                                                                       [ 25%]
generic_config_updater/test_pfcwd_status.py::test_stop_pfcwd[all] PASSED                                                                                                                                                          [ 50%]
generic_config_updater/test_pfcwd_status.py::test_start_pfcwd[single] PASSED                                                                                                                                                      [ 75%]
generic_config_updater/test_pfcwd_status.py::test_start_pfcwd[all] PASSED                                                                                                                                                         [100%]

-------------------------------------------------------------------------------------------- generated xml file: /var/nejo/tests/logs/tr.xml --------------------------------------------------------------------------------------------
====================================================================================================== 4 passed in 549.11 seconds =======================================================================================================
  • Loading branch information
neethajohn authored and parmarkj committed Oct 3, 2023
1 parent ba2a970 commit d354b82
Show file tree
Hide file tree
Showing 2 changed files with 241 additions and 44 deletions.
44 changes: 0 additions & 44 deletions tests/generic_config_updater/test_pfcwd_interval.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,50 +139,6 @@ def get_new_interval(duthost, is_valid):
return min(detection_time, restoration_time) + 10


def test_stop_pfcwd(duthost, ensure_dut_readiness):
pfcwd_config = duthost.shell("show pfcwd config")
pytest_assert(not pfcwd_config['rc'], "Unable to read pfcwd config")

for line in pfcwd_config['stdout_lines']:
if line.startswith('Ethernet'):
interface = line.split()[0]
break
else:
pytest_assert(False, "No interface found running pfcwd - unable to run test")

json_patch = [
{
"op": "remove",
"path": "/PFC_WD/{}/detection_time".format(interface),
},
{
"op": "remove",
"path": "/PFC_WD/{}/restoration_time".format(interface),
},
{
"op": "remove",
"path": "/PFC_WD/{}/action".format(interface)
}
]
try:
tmpfile = generate_tmpfile(duthost)
output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile)
if is_valid_platform_and_version(duthost, "PFC_WD", "PFCWD enable/disable"):
expect_op_success(duthost, output)
pfcwd_updated_config = duthost.shell("show pfcwd config")
pytest_assert(not pfcwd_config['rc'], "Unable to read updated pfcwd config")
pytest_assert(interface not in pfcwd_updated_config['stdout'].split(),
"pfcwd unexpectedly still running on interface {}".format(interface))
else:
expect_op_failure(output)
finally:
delete_tmpfile(duthost, tmpfile)
# Restore default config
duthost.shell('config pfcwd stop')
start_pfcwd = duthost.shell('config pfcwd start_default')
pytest_assert(not start_pfcwd['rc'], "Failed to start default pfcwd config")


@pytest.mark.parametrize("operation", ["add", "replace"])
@pytest.mark.parametrize("field_pre_status", ["existing", "nonexistent"])
@pytest.mark.parametrize("is_valid_config_update", [True, False])
Expand Down
241 changes: 241 additions & 0 deletions tests/generic_config_updater/test_pfcwd_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
import json
import logging
import pytest

from collections import defaultdict

from tests.common.helpers.assertions import pytest_assert
from tests.common.utilities import wait_until
from tests.common.helpers.dut_utils import verify_orchagent_running_or_assert
from tests.generic_config_updater.gu_utils import apply_patch, expect_op_success, expect_op_failure
from tests.generic_config_updater.gu_utils import generate_tmpfile, delete_tmpfile
from tests.generic_config_updater.gu_utils import create_checkpoint, delete_checkpoint, rollback_or_reload
from tests.generic_config_updater.gu_utils import is_valid_platform_and_version

pytestmark = [
pytest.mark.topology('any'),
]

logger = logging.getLogger(__name__)

READ_FLEXDB_TIMEOUT = 20
READ_FLEXDB_INTERVAL = 5


@pytest.fixture(scope="module", autouse=True)
def set_default_pfcwd_config(duthost):
"""
Enable pfcwd config before all test runs and disable at the end of all test runs
Args:
duthost: DUT host object
"""
res = duthost.shell('sonic-db-dump -n CONFIG_DB -y -k \"DEVICE_METADATA|localhost\"')
meta_data = json.loads(res["stdout"])
pfc_status = meta_data["DEVICE_METADATA|localhost"]["value"].get("default_pfcwd_status", "")
if pfc_status == 'disable':
duthost.shell('sonic-db-cli CONFIG_DB hset \"DEVICE_METADATA|localhost\" default_pfcwd_status enable')

yield

# Restore default config
duthost.shell('config pfcwd stop')
if pfc_status == 'disable':
duthost.shell('sonic-db-cli CONFIG_DB hset \"DEVICE_METADATA|localhost\" default_pfcwd_status disable')
else:
start_pfcwd = duthost.shell('config pfcwd start_default')
pytest_assert(not start_pfcwd['rc'], "Failed to start default pfcwd config")


@pytest.fixture
def ensure_dut_readiness(duthost):
"""
Verify dut health/create and rollback checkpoint
Args:
duthost: DUT host object
"""
verify_orchagent_running_or_assert(duthost)
create_checkpoint(duthost)

yield

try:
verify_orchagent_running_or_assert(duthost)
logger.info("Rolled back to original checkpoint")
rollback_or_reload(duthost)
finally:
delete_checkpoint(duthost)


@pytest.fixture
def stop_pfcwd(duthost):
"""
Stop pfcwd on all ports on the dut
Args:
duthost: DUT host object
"""
duthost.shell('config pfcwd stop')
yield


@pytest.fixture
def start_pfcwd(duthost):
"""
Start pfcwd on all ports on the dut
Args:
duthost: DUT host object
"""
duthost.shell('config pfcwd start_default')
yield


@pytest.fixture
def extract_pfcwd_config(duthost, start_pfcwd):
"""
Extract pfcwd info from running config
Args:
duthost: DUT host object
Yields:
pfcwd_config: dict of dicts with interface as the 1st level key and 'action', 'detect_time',
'restore_time' as the 2nd level keys
"""
output = duthost.command('show pfcwd config')
pytest_assert('Ethernet' in output['stdout'], 'No ports found in the pfcwd config')

pfcwd_config = defaultdict()
for line in output['stdout_lines']:
if line.strip().startswith('Ethernet'):
port, action, detect, restore = line.split()
pfcwd_config.update({port: {'action': action,
'detect_time': detect,
'restore_time': restore}})

yield pfcwd_config


def get_flex_db_count(duthost):
"""
Get the count of the number of pfcwd entries seen in flex db
For every port, there will be 3 entries - 1 for the port, 1 for queue 3 and 1 for queue 4
Args:
duthost: DUT host object
Returns:
Number of PFCWD related flex db entries
"""
db_entries = duthost.shell('sonic-db-cli FLEX_COUNTER_DB keys *FLEX_COUNTER_TABLE:PFC_WD*')["stdout"]
if db_entries == '':
return 0
else:
return len(db_entries.split('\n'))


def check_config_update(duthost, expected_count):
"""
Ensures application of the JSON patch config update
Args:
duthost: DUT host object
expected_count: number of pfcwd entries expected in the updated config
"""
def _confirm_value_in_flex_db(duthost, expected_count):
pfcwd_entries_count = get_flex_db_count(duthost)
logger.info("Actual number of entries: {}".format(pfcwd_entries_count))
return pfcwd_entries_count == expected_count

logger.info("Validating in FLEX COUNTER DB...")
pytest_assert(
wait_until(READ_FLEXDB_TIMEOUT, READ_FLEXDB_INTERVAL, 0, _confirm_value_in_flex_db, duthost, expected_count),
"FLEX DB does not properly reflect Pfcwd status: Expected number of entries {}"
.format(expected_count)
)


@pytest.mark.parametrize('port', ['single', 'all'])
def test_stop_pfcwd(duthost, extract_pfcwd_config, ensure_dut_readiness, port):
"""
Tests GCU config for pfcwd stop scenario
1. Covers the case for stopping pfcwd on single port and all ports
2. Verifies that the config is as expected in CONFIG DB
3. Validates the number of PFC_WD related entries in FLEX DB is as expected
4. Validates that orchagent is running fine pre and post test
"""
pfcwd_config = extract_pfcwd_config

if port == 'single':
expected_count = get_flex_db_count(duthost) - 3
else:
expected_count = 0
json_patch = list()
exp_str = 'Ethernet'
for interface in pfcwd_config:
json_patch.extend([
{
'op': 'remove',
'path': '/PFC_WD/{}'.format(interface)
}])
if port == 'single':
exp_str = interface
break

try:
tmpfile = generate_tmpfile(duthost)
output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile)
expect_op_success(duthost, output)
pfcwd_updated_config = duthost.shell("show pfcwd config")
pytest_assert(not pfcwd_updated_config['rc'], "Unable to read updated pfcwd config")
pytest_assert(exp_str not in pfcwd_updated_config['stdout'].split(),
"pfcwd unexpectedly still running")
check_config_update(duthost, expected_count)
finally:
delete_tmpfile(duthost, tmpfile)


@pytest.mark.parametrize('port', ['single', 'all'])
def test_start_pfcwd(duthost, extract_pfcwd_config, ensure_dut_readiness, stop_pfcwd, port):
"""
Tests GCU config for pfcwd start scenario
1. Covers the case for starting pfcwd on single port and all ports
2. Verifies that the config is as expected in CONFIG DB
3. Validates the number of PFC_WD related entries in FLEX DB is as expected
4. Validates that orchagent is running fine pre and post test
"""
pfcwd_config = extract_pfcwd_config

if port == 'single':
expected_count = 3
else:
expected_count = len(pfcwd_config) * 3
json_patch = list()
exp_str = 'Ethernet'
for interface, value in pfcwd_config.items():
json_patch.extend([
{
'op': 'add',
'path': '/PFC_WD/{}'.format(interface),
'value': {'action': value['action'],
'detection_time': value['detect_time'],
'restoration_time': value['restore_time']}}])
if port == 'single':
exp_str = interface
break

try:
tmpfile = generate_tmpfile(duthost)
output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile)
if is_valid_platform_and_version(duthost, "PFC_WD", "PFCWD enable/disable"):
expect_op_success(duthost, output)
pfcwd_updated_config = duthost.shell("show pfcwd config")
pytest_assert(not pfcwd_updated_config['rc'], "Unable to read updated pfcwd config")
pytest_assert(exp_str in pfcwd_updated_config['stdout'],
"pfcwd not started - unexpected")
check_config_update(duthost, expected_count)
else:
expect_op_failure(output)
finally:
delete_tmpfile(duthost, tmpfile)

0 comments on commit d354b82

Please sign in to comment.