Skip to content

Commit 15e2934

Browse files
authored
Merge branch 'sonic-net:master' into pfc_testcase_fixes
2 parents 68e85b9 + 1fa9b46 commit 15e2934

File tree

7 files changed

+141
-40
lines changed

7 files changed

+141
-40
lines changed

tests/common/plugins/conditional_mark/tests_mark_conditions.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2506,7 +2506,7 @@ generic_config_updater/test_ecn_config_update.py::test_ecn_config_updates:
25062506
reason: "This test is not run on this asic type, topology, or version currently"
25072507
conditions_logical_operator: "OR"
25082508
conditions:
2509-
- "asic_type in ['cisco-8000']"
2509+
- "hwsku in ['Cisco-8800-LC-48H-C48']"
25102510
- "topo_type in ['m0', 'mx', 'm1']"
25112511
- "release in ['202211']"
25122512

tests/generic_config_updater/test_ecn_config_update.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,16 @@ def get_asic_db_values(duthost, fields, cli_namespace_prefix):
6060
asic_db_values = {}
6161
for wred_object in wred_objects:
6262
oid = wred_object[wred_object.rfind(':') + 1:]
63-
asic_db_values[oid] = {}
6463
wred_data = duthost.shell('sonic-db-cli {} ASIC_DB hgetall {}'
6564
.format(cli_namespace_prefix, wred_object))["stdout"]
6665
if "NULL" in wred_data:
6766
continue
6867
wred_data = ast.literal_eval(wred_data)
68+
values = {}
6969
for field in fields:
70-
value = int(wred_data[WRED_MAPPING[field]])
71-
asic_db_values[oid][field] = value
70+
values[field] = int(wred_data[WRED_MAPPING[field]])
71+
if values:
72+
asic_db_values[oid] = values
7273
return asic_db_values
7374

7475

@@ -137,8 +138,7 @@ def validate_wred_objects_in_asic_db():
137138
def get_wred_profiles(duthost, cli_namespace_prefix):
138139
wred_profiles = duthost.shell(f"sonic-db-cli {cli_namespace_prefix} CONFIG_DB keys \
139140
'WRED_PROFILE|*' | cut -d '|' -f 2")["stdout"]
140-
wred_profiles = wred_profiles.split('\n')
141-
return wred_profiles
141+
return [w for w in wred_profiles.split('\n') if w]
142142

143143

144144
@pytest.mark.parametrize("configdb_field", ["green_min_threshold", "green_max_threshold", "green_drop_probability",
@@ -168,12 +168,14 @@ def test_ecn_config_updates(duthost, ensure_dut_readiness, configdb_field, opera
168168
for field in fields:
169169
value = int(ecn_data[field])
170170
if "probability" in field:
171-
if 0 <= value <= 99:
171+
if 0 <= value < 99:
172172
value += 1
173-
elif value == 100:
173+
elif value >= 99:
174174
value -= 1
175175
else:
176176
raise ValueError("Invalid probability value: {}".format(value))
177+
elif "min" in field:
178+
value -= 1
177179
else:
178180
value += 1
179181
new_values[wred_profile][field] = value

tests/generic_config_updater/test_pfcwd_status.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,11 @@ def extract_pfcwd_config(duthost, start_pfcwd):
153153
pfcwd_config: dict of dicts with interface as the 1st level key and 'action', 'detect_time',
154154
'restore_time' as the 2nd level keys
155155
"""
156-
output = duthost.command('show pfcwd config')
156+
# Add flag to show all internal interfaces (for multi-asic systems)
157+
cmd = 'show pfcwd config'
158+
if duthost.is_multi_asic:
159+
cmd += ' -d all'
160+
output = duthost.command(cmd)
157161
pytest_assert('Ethernet' in output['stdout'], 'No ports found in the pfcwd config')
158162

159163
pfcwd_config = defaultdict()

tests/gnmi/grpc_utils.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import sys
22
import os
3+
import grpc
4+
import logging
5+
6+
from tests.common.helpers.gnmi_utils import GNMIEnvironment
37

48

59
def get_gnoi_system_stubs():
@@ -16,3 +20,52 @@ def get_gnoi_system_stubs():
1620
sys.path.append(os.path.abspath(PROTO_ROOT))
1721
from gnoi.system import system_pb2_grpc, system_pb2
1822
return system_pb2_grpc, system_pb2
23+
24+
25+
def create_grpc_channel(duthost):
26+
"""
27+
Create a gRPC channel with secure credentials.
28+
29+
This function replaces the grpc_channel fixture to avoid SSL state sharing
30+
issues between forked processes during shell operations.
31+
32+
Args:
33+
duthost: DUT host object
34+
35+
Returns:
36+
grpc.Channel: Configured gRPC channel
37+
"""
38+
# Get DUT gRPC server address and port
39+
ip = duthost.mgmt_ip
40+
env = GNMIEnvironment(duthost, GNMIEnvironment.GNMI_MODE)
41+
port = env.gnmi_port
42+
target = f"{ip}:{port}"
43+
44+
# Load the TLS certificates
45+
with open("gnmiCA.pem", "rb") as f:
46+
root_certificates = f.read()
47+
with open("gnmiclient.crt", "rb") as f:
48+
client_certificate = f.read()
49+
with open("gnmiclient.key", "rb") as f:
50+
client_key = f.read()
51+
52+
# Create SSL credentials
53+
credentials = grpc.ssl_channel_credentials(
54+
root_certificates=root_certificates,
55+
private_key=client_key,
56+
certificate_chain=client_certificate,
57+
)
58+
59+
# Create gRPC channel
60+
logging.info("Creating gRPC secure channel to %s", target)
61+
channel = grpc.secure_channel(target, credentials)
62+
63+
try:
64+
grpc.channel_ready_future(channel).result(timeout=10)
65+
logging.info("gRPC channel is ready")
66+
except grpc.FutureTimeoutError as e:
67+
logging.error("Error: gRPC channel not ready: %s", e)
68+
channel.close()
69+
raise Exception("Failed to connect to gRPC server") from e
70+
71+
return channel
Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import pytest
22
import logging
3-
import time
43

5-
from tests.gnmi.grpc_utils import get_gnoi_system_stubs
4+
from tests.gnmi.grpc_utils import get_gnoi_system_stubs, create_grpc_channel
65

76
pytestmark = [
87
pytest.mark.topology("any"),
@@ -18,24 +17,40 @@
1817
system_pb2_grpc, system_pb2 = get_gnoi_system_stubs()
1918

2019

21-
def test_gnoi_system_time(grpc_channel):
20+
def test_gnoi_system_time(duthosts, rand_one_dut_hostname):
2221
"""
23-
Verify the gNOI System Time API returns the current system time in valid JSON format.
22+
Verify the gNOI System Time API returns the current system time.
2423
"""
25-
# Use the shared gRPC channel
26-
stub = system_pb2_grpc.SystemStub(grpc_channel)
27-
28-
# Create and send request
29-
request = system_pb2.TimeRequest()
30-
response = stub.Time(request)
31-
32-
# Log the response
33-
logging.info("Received response: %s", response)
34-
35-
# Assert the time falls into a reasonable interval
36-
current_time_ns = int(time.time() * 1e9)
37-
reasonable_interval_ns = 60 * 1e9 # 60 seconds in nanoseconds
38-
39-
assert (
40-
abs(response.time - current_time_ns) < reasonable_interval_ns
41-
), f"System time {response.time} is not within the reasonable interval of current time {current_time_ns}"
24+
duthost = duthosts[rand_one_dut_hostname]
25+
26+
# Get device time in seconds first (before gRPC operations)
27+
device_time_result = duthost.shell("date +%s", module_ignore_errors=True)
28+
device_time_s = int(device_time_result["stdout"].strip())
29+
device_time_ns = device_time_s * int(1e9)
30+
31+
# Create gRPC channel (no longer a fixture to avoid SSL state sharing)
32+
channel = create_grpc_channel(duthost)
33+
34+
try:
35+
# Create gRPC stub
36+
stub = system_pb2_grpc.SystemStub(channel)
37+
38+
# Create and send request
39+
request = system_pb2.TimeRequest()
40+
response = stub.Time(request)
41+
42+
# Log the response
43+
logging.info("Received response: %s", response)
44+
logging.info("Device time from shell: %d", device_time_ns)
45+
46+
# Assert the gNOI time is close to device shell time
47+
reasonable_interval_ns = 60 * 1e9 # 60 seconds in nanoseconds
48+
49+
time_diff = abs(response.time - device_time_ns)
50+
assert time_diff < reasonable_interval_ns, (
51+
f"gNOI time {response.time} differs from device time "
52+
f"{device_time_ns} by {time_diff}ns (max: {reasonable_interval_ns}ns)"
53+
)
54+
finally:
55+
# Always close the channel to avoid resource leaks
56+
channel.close()

tests/upgrade_path/test_upgrade_path.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from tests.common.helpers.upgrade_helpers import install_sonic, upgrade_test_helper
44
from tests.common.helpers.upgrade_helpers import restore_image # noqa: F401
55
from tests.common.helpers.multi_thread_utils import SafeThreadPoolExecutor
6-
from tests.upgrade_path.utilities import cleanup_prev_images, boot_into_base_image
6+
from tests.upgrade_path.utilities import cleanup_prev_images, boot_into_base_image, boot_into_base_image_t2
77
from tests.common.fixtures.advanced_reboot import get_advanced_reboot # noqa: F401
88
from tests.common.fixtures.consistency_checker.consistency_checker import consistency_checker_provider # noqa: F401
99
from tests.common.platform.device_utils import verify_dut_health, verify_testbed_health # noqa: F401
@@ -49,9 +49,10 @@ def upgrade_path_lists(request):
4949
def setup_upgrade_test(duthost, localhost, from_image, to_image, tbinfo,
5050
upgrade_type, modify_reboot_script=None, allow_fail=False):
5151
logger.info("Test upgrade path from {} to {}".format(from_image, to_image))
52-
cleanup_prev_images(duthost)
53-
# Install base image
54-
boot_into_base_image(duthost, localhost, from_image, tbinfo)
52+
if tbinfo['topo']['type'] != 't2': # We do this all at once seperately for T2
53+
cleanup_prev_images(duthost)
54+
# Install base image
55+
boot_into_base_image(duthost, localhost, from_image, tbinfo)
5556

5657
# Install target image
5758
logger.info("Upgrading to {}".format(to_image))
@@ -113,6 +114,10 @@ def test_upgrade_path_t2(localhost, duthosts, ptfhost, upgrade_path_lists,
113114
upgrade_type = REBOOT_TYPE_COLD
114115
logger.info("Test upgrade path from {} to {}".format(from_image, to_image))
115116

117+
for duthost in duthosts:
118+
cleanup_prev_images(duthost)
119+
boot_into_base_image_t2(duthosts, localhost, from_image, tbinfo)
120+
116121
def upgrade_path_preboot_setup(dut):
117122
setup_upgrade_test(dut, localhost, from_image, to_image, tbinfo, upgrade_type)
118123

tests/upgrade_path/utilities.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,38 @@
11
import logging
22
import re
33
from tests.common.errors import RunAnsibleModuleFail
4+
from tests.common.helpers.multi_thread_utils import SafeThreadPoolExecutor
45
from tests.common.helpers.upgrade_helpers import install_sonic, reboot, check_sonic_version
56

67
logger = logging.getLogger(__name__)
78

89

910
def boot_into_base_image(duthost, localhost, base_image, tbinfo):
11+
target_version = _install_base_image(duthost, base_image, tbinfo)
12+
# Perform a cold reboot
13+
logger.info("Cold reboot the DUT to make the base image as current")
14+
# for 6100 devices, sometimes cold downgrade will not work, use soft-reboot here
15+
reboot_type = 'soft' if "s6100" in duthost.facts["platform"] else 'cold'
16+
reboot(duthost, localhost, reboot_type=reboot_type, safe_reboot=True)
17+
check_sonic_version(duthost, target_version)
18+
19+
20+
def boot_into_base_image_t2(duthosts, localhost, base_image, tbinfo):
21+
target_vers = {}
22+
with SafeThreadPoolExecutor(max_workers=8) as executor:
23+
for duthost in duthosts:
24+
future = executor.submit(_install_base_image, duthost, base_image, tbinfo)
25+
target_vers[duthost] = future.get() # Should all be the same, but following best practice
26+
27+
# Rebooting the supervisor host will reboot all T2 DUTs
28+
suphost = duthosts.supervisor_nodes[0]
29+
reboot(suphost, localhost, reboot_type='cold', safe_reboot=True)
30+
31+
for duthost in duthosts:
32+
check_sonic_version(duthost, target_vers[duthost])
33+
34+
35+
def _install_base_image(duthost, base_image, tbinfo):
1036
logger.info("Installing {}".format(base_image))
1137
try:
1238
target_version = install_sonic(duthost, base_image, tbinfo)
@@ -26,12 +52,8 @@ def boot_into_base_image(duthost, localhost, base_image, tbinfo):
2652
if duthost.shell("ls /host/old_config/minigraph.xml", module_ignore_errors=True)['rc'] == 0:
2753
duthost.shell("rm -f /host/old_config/config_db.json")
2854
duthost.shell("rm -f /host/old_config/golden_config_db.json")
29-
# Perform a cold reboot
30-
logger.info("Cold reboot the DUT to make the base image as current")
31-
# for 6100 devices, sometimes cold downgrade will not work, use soft-reboot here
32-
reboot_type = 'soft' if "s6100" in duthost.facts["platform"] else 'cold'
33-
reboot(duthost, localhost, reboot_type=reboot_type, safe_reboot=True)
34-
check_sonic_version(duthost, target_version)
55+
56+
return target_version
3557

3658

3759
def cleanup_prev_images(duthost):

0 commit comments

Comments
 (0)