Skip to content

Commit

Permalink
Merge branch 'sonic-net:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Azarack authored Oct 10, 2024
2 parents 26ec947 + 9ad8d8e commit f09db6e
Show file tree
Hide file tree
Showing 279 changed files with 11,173 additions and 5,467 deletions.
12 changes: 9 additions & 3 deletions .azure-pipelines/pr_test_scripts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ t0:
- bgp/test_bgp_speaker.py
- bgp/test_bgp_update_timer.py
- bgp/test_bgpmon.py
- bgp/test_bgp_stress_link_flap.py
- bgp/test_bgp_session.py
- cacl/test_cacl_application.py
- cacl/test_cacl_function.py
Expand All @@ -34,6 +35,7 @@ t0:
- decap/test_decap.py
- dhcp_relay/test_dhcp_pkt_recv.py
- dhcp_relay/test_dhcp_relay.py
- dhcp_relay/test_dhcp_relay_stress.py
- dhcp_relay/test_dhcpv6_relay.py
- disk/test_disk_exhaustion.py
- dns/static_dns/test_static_dns.py
Expand Down Expand Up @@ -216,9 +218,12 @@ t0:
- platform_tests/test_idle_driver.py
- wol/test_wol.py
- dhcp_relay/test_dhcp_pkt_fwd.py
- telemetry/test_telemetry.py
- platform_tests/test_cont_warm_reboot.py

t0-2vlans:
- dhcp_relay/test_dhcp_relay.py
- dhcp_relay/test_dhcp_relay_stress.py
- dhcp_relay/test_dhcpv6_relay.py
- vlan/test_host_vlan.py
- vlan/test_vlan_ping.py
Expand Down Expand Up @@ -262,6 +267,7 @@ t1-lag:
- bgp/test_bgp_multipath_relax.py
- bgp/test_bgp_update_timer.py
- bgp/test_bgpmon.py
- bgp/test_bgp_stress_link_flap.py
- bgp/test_bgp_session.py
- bgp/test_traffic_shift.py
- configlet/test_add_rack.py
Expand Down Expand Up @@ -415,6 +421,7 @@ t1-lag:
- platform_tests/test_link_down.py
- gnmi/test_gnmi_countersdb.py
- generic_config_updater/test_cacl.py
- telemetry/test_telemetry.py

multi-asic-t1-lag:
- bgp/test_bgp_bbr.py
Expand Down Expand Up @@ -444,20 +451,19 @@ dpu:
- dash/test_dash_vnet.py

onboarding_t0:
- bgp/test_bgp_stress_link_flap.py
# We will add a batch of T0 control plane cases and fix the failed cases later
- pfcwd/test_pfcwd_all_port_storm.py
- pfcwd/test_pfcwd_function.py
- pfcwd/test_pfcwd_timer_accuracy.py
- pfcwd/test_pfcwd_warm_reboot.py
# - platform_tests/test_advanced_reboot.py
- platform_tests/test_cont_warm_reboot.py
- snmp/test_snmp_link_local.py
- lldp/test_lldp_syncd.py


onboarding_t1:
- bgp/test_bgp_stress_link_flap.py
- snmp/test_snmp_link_local.py
- lldp/test_lldp_syncd.py

onboarding_dualtor:
- dualtor_mgmt/test_dualtor_bgp_update_delay.py
Expand Down
2 changes: 1 addition & 1 deletion .azure-pipelines/recover_testbed/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ def check_sonic_installer(sonichost, sonic_username, sonic_password, sonic_ip, i
client.expect("admin@{}'s password:".format(sonic_ip))
client.sendline(sonic_password)
client.expect(["admin@sonic", "admin@{}".format(sonichost.hostname)])
client.sendline("sudo sonic-installer install {}"
client.sendline("sudo sonic_installer install {}"
.format(image_url))
client.expect("New image will be installed")
client.close()
5 changes: 5 additions & 0 deletions .azure-pipelines/run-test-elastictest-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ parameters:
type: string
default: ""

- name: PTF_IMAGE_TAG
type: string
default: ""

- name: IMAGE_URL
type: string
default: ""
Expand Down Expand Up @@ -204,6 +208,7 @@ steps:
--deploy-mg-extra-params="${{ parameters.DEPLOY_MG_EXTRA_PARAMS }}" \
--common-extra-params="${{ parameters.COMMON_EXTRA_PARAMS }}" \
--vm-type ${{ parameters.VM_TYPE }} --num-asic ${{ parameters.NUM_ASIC }} \
--ptf_image_tag ${{ parameters.PTF_IMAGE_TAG }} \
--image_url ${{ parameters.IMAGE_URL }} \
--upgrade-image-param="${{ parameters.UPGRADE_IMAGE_PARAM }}" \
--hwsku ${{ parameters.HWSKU }} \
Expand Down
13 changes: 13 additions & 0 deletions .azure-pipelines/test_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ def create(self, topology, test_plan_name="my_test_plan", deploy_mg_extra_params
features = parse_list_from_str(kwargs.get("features", None))
scripts_exclude = parse_list_from_str(kwargs.get("scripts_exclude", None))
features_exclude = parse_list_from_str(kwargs.get("features_exclude", None))
ptf_image_tag = kwargs.get("ptf_image_tag", None)

print("Creating test plan, topology: {}, name: {}, build info:{} {} {}".format(topology, test_plan_name,
repo_name, pr_id, build_id))
Expand Down Expand Up @@ -288,6 +289,7 @@ def create(self, topology, test_plan_name="my_test_plan", deploy_mg_extra_params
"features_exclude": features_exclude,
"scripts_exclude": scripts_exclude
},
"ptf_image_tag": ptf_image_tag,
"image": {
"url": image_url,
"upgrade_image_param": kwargs.get("upgrade_image_param", None),
Expand Down Expand Up @@ -655,6 +657,16 @@ def poll(self, test_plan_id, interval=60, timeout=-1, expected_state="", expecte
required=False,
help="Testbed name, Split by ',', like: 'testbed1, testbed2'"
)
parser_create.add_argument(
"--ptf_image_tag",
type=str,
dest="ptf_image_tag",
nargs='?',
const=None,
default=None,
required=False,
help="PTF image tag"
)
parser_create.add_argument(
"--image_url",
type=str,
Expand Down Expand Up @@ -972,6 +984,7 @@ def poll(self, test_plan_id, interval=60, timeout=-1, expected_state="", expecte
affinity=args.affinity,
vm_type=args.vm_type,
testbed_name=args.testbed_name,
ptf_image_tag=args.ptf_image_tag,
image_url=args.image_url,
upgrade_image_param=args.upgrade_image_param,
hwsku=args.hwsku,
Expand Down
1 change: 1 addition & 0 deletions .azure-pipelines/testscripts_analyse/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"t1-lag": "t1",
"multi-asic-t1-lag": "t1",
"t2": "t2",
"wan-pub": "wan",
"dpu": "dpu",
"tgen": "tgen",
"multidut-tgen": "tgen",
Expand Down
6 changes: 5 additions & 1 deletion ansible/TestbedProcessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ def makeTestbed(data, outfile):


def makeSonicLabLinks(data, outfile):
csv_columns = "StartDevice,StartPort,EndDevice,EndPort,BandWidth,VlanID,VlanMode,SlotId"
csv_columns = "StartDevice,StartPort,EndDevice,EndPort,BandWidth,VlanID,VlanMode,AutoNeg,SlotId"
topology = data
csv_file = outfile

Expand All @@ -331,6 +331,7 @@ def makeSonicLabLinks(data, outfile):
bandWidth = element.get("Bandwidth")
vlanID = element.get("VlanID")
vlanMode = element.get("VlanMode")
AutoNeg = element.get("AutoNeg")
slotId = element.get("SlotId")

# catch empty values
Expand All @@ -346,10 +347,13 @@ def makeSonicLabLinks(data, outfile):
vlanMode = ""
if not slotId:
slotId = ""
if not AutoNeg:
AutoNeg = ""

row = startDevice + "," + startPort + "," + endDevice + "," + \
endPort + "," + str(bandWidth) + \
"," + str(vlanID) + "," + vlanMode + \
"," + str(AutoNeg) + \
"," + str(slotId)
f.write(row + "\n")
except IOError:
Expand Down
2 changes: 1 addition & 1 deletion ansible/config_sonic_basedon_testbed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@

- name: gather hwsku that supports ComputeAI deployment
set_fact:
hwsku_list_compute_ai: "['Cisco-8111-O64', 'Cisco-8122-O64', 'Cisco-8122-O128']"
hwsku_list_compute_ai: "['Cisco-8111-O64', 'Cisco-8111-O32', 'Cisco-8122-O64', 'Cisco-8122-O128']"

- name: enable ComputeAI deployment
set_fact:
Expand Down
30 changes: 30 additions & 0 deletions ansible/devutil/device_inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ def __init__(
self.device_type = device_type
self.protocol = protocol
self.os = os
self.console_device = None
self.console_port = 0

@staticmethod
def from_csv_row(row: List[str]) -> "DeviceInfo":
Expand Down Expand Up @@ -63,6 +65,9 @@ def from_device_files(device_file_pattern: str) -> "List[DeviceInventory]":
inv: List[DeviceInventory] = []
for file_path in glob.glob(device_file_pattern):
device_inventory = DeviceInventory.from_device_file(file_path)
console_links_file_path = file_path.replace("_devices", "_console_links")
if os.path.exists(console_links_file_path):
device_inventory.load_console_links_info(console_links_file_path)
inv.append(device_inventory)

return inv
Expand All @@ -89,5 +94,30 @@ def from_device_file(file_path: str) -> "DeviceInventory":

return DeviceInventory(inv_name, file_path, devices)

def load_console_links_info(self, file_path: str):
print(f"Loading console links inventory: {file_path}")

with open(file_path, newline="") as file:
reader = csv.reader(file)

# Skip the header line
next(reader)

for row in reader:
if row:
console_hostname = row[0]
console_port = int(row[1])
device_hostname = row[2]
console_device_info = self.get_device(console_hostname)
device_info = self.get_device(device_hostname)
if not console_device_info:
print(f"Unknown console hostname {console_hostname}, skipping")
continue
if not device_info:
print(f"Unknown device hostname {device_hostname}, skipping")
continue
device_info.console_device = console_device_info
device_info.console_port = console_port

def get_device(self, hostname: str) -> Optional[DeviceInfo]:
return self.devices.get(hostname)
2 changes: 2 additions & 0 deletions ansible/devutil/inv_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ def get_host_vars(self, hostname):
@return: A dict of hostvars
"""
host = self._inv_mgr.get_host(hostname)
if not host:
raise Exception("Host not found in inventory files")
vars = self._var_mgr.get_vars(host=host)
vars['creds'] = self.get_host_creds(hostname)
vars.update(host.vars)
Expand Down
88 changes: 45 additions & 43 deletions ansible/devutil/ssh_session_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ def _load_template(self, template_file):
"""
raise NotImplementedError

def generate(self, session_path, ssh_ip, ssh_ipv6, ssh_user, ssh_pass):
def generate(self, session_path, ssh_ip, ssh_ipv6, ssh_user, ssh_pass,
console_ssh_ip, console_ssh_port, console_ssh_user, console_ssh_pass):
"""Generate SSH session for a node.
This is a virtual method that should be implemented by child class.
Expand Down Expand Up @@ -102,47 +103,30 @@ def _load_template(self, template_file):

return template

def generate(self, session_path, ssh_ip, ssh_ipv6, ssh_user, ssh_pass):
def generate(self, session_path, ssh_ip, ssh_ipv6, ssh_user, ssh_pass,
console_ssh_ip, console_ssh_port, console_ssh_user, console_ssh_pass):
"""Generate SSH session for a testbed node."""
if ssh_ip:
ssh_session_name = session_path

# In SecureCRT, every SSH session is stored in a ini file separately,
# hence we add .ini extension to the session path in order to generate individual SSH session file.
ssh_session_file_path = os.path.join(self.target, ssh_session_name + ".ini")

# Recursively create SSH session file directory
ssh_session_folder = os.path.dirname(ssh_session_file_path)
self._create_ssh_session_folder(ssh_session_folder)

# Generate SSH session file
ssh_session_file_content = self._generate_ssh_session_file_content(
ssh_session_name, ssh_ip, ssh_user, ssh_pass
)
with open(ssh_session_file_path, "w") as ssh_session_file:
ssh_session_file.write(ssh_session_file_content)

# Add newly created session file into current folder data
ssh_session_folder_data = SecureCRTRepoFolderData.from_folder(
ssh_session_folder, create_if_not_exist=True
)
ssh_session_folder_data.add_session(ssh_session_name)
ssh_session_folder_data.save()
session_file_matrix = [
(session_path, ssh_ip, ssh_user, ssh_pass),
(session_path + "-v6", ssh_ipv6, ssh_user, ssh_pass),
(session_path + "-console", console_ssh_ip, f"{console_ssh_user}:{console_ssh_port}", console_ssh_pass),
]

if ssh_ipv6:
ssh_session_name = session_path + "-v6"
for (session_name, ip, user, password) in session_file_matrix:
if not ip or not user:
continue

# In SecureCRT, every SSH session is stored in a ini file separately,
# hence we add .ini extension to the session path in order to generate individual SSH session file.
ssh_session_file_path = os.path.join(self.target, ssh_session_name + ".ini")
ssh_session_file_path = os.path.join(self.target, session_name + ".ini")

# Recursively create SSH session file directory
ssh_session_folder = os.path.dirname(ssh_session_file_path)
self._create_ssh_session_folder(ssh_session_folder)

# Generate SSH session file
ssh_session_file_content = self._generate_ssh_session_file_content(
ssh_session_name, ssh_ip, ssh_user, ssh_pass
session_name, ip, user, password
)
with open(ssh_session_file_path, "w") as ssh_session_file:
ssh_session_file.write(ssh_session_file_content)
Expand All @@ -151,7 +135,7 @@ def generate(self, session_path, ssh_ip, ssh_ipv6, ssh_user, ssh_pass):
ssh_session_folder_data = SecureCRTRepoFolderData.from_folder(
ssh_session_folder, create_if_not_exist=True
)
ssh_session_folder_data.add_session(ssh_session_name)
ssh_session_folder_data.add_session(session_name)
ssh_session_folder_data.save()

def _create_ssh_session_folder(self, ssh_session_file_dir):
Expand Down Expand Up @@ -353,7 +337,7 @@ class SshConfigSshSessionRepoGenerator(SshSessionRepoGenerator):
It derives from SshSessionRepoGenerator and implements the generate method.
"""

def __init__(self, target, ssh_config_params):
def __init__(self, target, ssh_config_params, console_ssh_config_params):
super().__init__(target, "")

# Load SSH config file from target file path
Expand All @@ -365,6 +349,7 @@ def __init__(self, target, ssh_config_params):

# Add SSH config parameters
self.ssh_config_params = ssh_config_params
self.console_ssh_config_params = console_ssh_config_params

def _load_template(self, template_file):
"""Load SSH session template file.
Expand All @@ -373,24 +358,41 @@ def _load_template(self, template_file):
"""
pass

def generate(self, session_path, ssh_ip, ssh_ipv6, ssh_user, ssh_pass):
def generate(self, session_path, ssh_ip, ssh_ipv6, ssh_user, ssh_pass,
console_ssh_ip, console_ssh_port, console_ssh_user, console_ssh_pass):
"""Generate SSH session for a testbed node."""
ssh_session_name = os.path.basename(session_path)

# Remove existing host config if it exists
try:
self.ssh_config.remove(ssh_session_name)
self.ssh_config.remove(ssh_session_name + "-v6")
except ValueError:
pass
current_hosts = self.ssh_config.hosts()
ssh_config = {}
if ssh_user:
ssh_config["User"] = ssh_user

# Add new host config
if ssh_ip:
self.ssh_config.add(ssh_session_name, Hostname=ssh_ip, User=ssh_user,
PasswordAuthentication="yes", **self.ssh_config_params)
session_name = ssh_session_name
ssh_config["Hostname"] = ssh_ip
if session_name in current_hosts:
self.ssh_config.set(session_name, **ssh_config, **self.ssh_config_params)
else:
self.ssh_config.add(session_name, **ssh_config, **self.ssh_config_params)
if ssh_ipv6:
self.ssh_config.add(ssh_session_name + "-v6", Hostname=ssh_ipv6, User=ssh_user,
PasswordAuthentication="yes", **self.ssh_config_params)
session_name = ssh_session_name + "-v6"
ssh_config["Hostname"] = ssh_ipv6
if session_name in current_hosts:
self.ssh_config.set(session_name, **ssh_config, **self.ssh_config_params)
else:
self.ssh_config.add(session_name, **ssh_config, **self.ssh_config_params)
if console_ssh_ip:
session_name = ssh_session_name + "-console"
ssh_config["User"] = f"{console_ssh_user}:{console_ssh_port}"
ssh_config["Hostname"] = console_ssh_ip
if session_name in current_hosts:
self.ssh_config.set(session_name, **ssh_config, **self.ssh_config_params,
**self.console_ssh_config_params)
else:
self.ssh_config.add(session_name, **ssh_config, **self.ssh_config_params,
**self.console_ssh_config_params)

def finish(self):
"""Finish SSH session generation."""
Expand Down
Loading

0 comments on commit f09db6e

Please sign in to comment.