From 314aa393136d49d2347384560f19af214ca71c09 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 15 Jan 2021 09:33:46 -0800 Subject: [PATCH] Move tip-cicd-nightly from wlan-lanforge-scripts to wlan-testing This is a copy of that code from commit a99d6c31a983cbf5b763ecd2905dddbd6e59d18d in wlan-testing. Signed-off-by: Ben Greear --- unit_tests/Nightly_Sanity.py | 1694 +++++++++++++++++ unit_tests/README.md | 66 + unit_tests/Throughput_Test.py | 530 ++++++ unit_tests/ap_ssh.py | 117 ++ unit_tests/cloudsdk.py | 267 +++ unit_tests/eap_connect.py | 373 ++++ unit_tests/lab_ap_info.py | 635 ++++++ unit_tests/reports/report_template.php | 622 ++++++ unit_tests/sanity_status.json | 1 + unit_tests/single_client_throughput.py | 1064 +++++++++++ unit_tests/templates/ap_profile_template.json | 1 + .../templates/radius_profile_template.json | 1 + .../templates/ssid_profile_template.json | 1 + unit_tests/testrail_api.py | 187 ++ 14 files changed, 5559 insertions(+) create mode 100755 unit_tests/Nightly_Sanity.py create mode 100644 unit_tests/README.md create mode 100755 unit_tests/Throughput_Test.py create mode 100755 unit_tests/ap_ssh.py create mode 100755 unit_tests/cloudsdk.py create mode 100755 unit_tests/eap_connect.py create mode 100755 unit_tests/lab_ap_info.py create mode 100755 unit_tests/reports/report_template.php create mode 100755 unit_tests/sanity_status.json create mode 100755 unit_tests/single_client_throughput.py create mode 100644 unit_tests/templates/ap_profile_template.json create mode 100644 unit_tests/templates/radius_profile_template.json create mode 100644 unit_tests/templates/ssid_profile_template.json create mode 100644 unit_tests/testrail_api.py diff --git a/unit_tests/Nightly_Sanity.py b/unit_tests/Nightly_Sanity.py new file mode 100755 index 000000000..233a110e1 --- /dev/null +++ b/unit_tests/Nightly_Sanity.py @@ -0,0 +1,1694 @@ +#!/usr/bin/python3 + +import base64 +import urllib.request +from bs4 import BeautifulSoup +import ssl +import subprocess, os +from artifactory import ArtifactoryPath +import tarfile +import paramiko +from paramiko import SSHClient +from scp import SCPClient +import os +import pexpect +from pexpect import pxssh +import sys +import paramiko +from scp import SCPClient +import pprint +from pprint import pprint +from os import listdir +import re +import requests +import json +import testrail_api +import logging +import datetime +import time +from datetime import date +from shutil import copyfile +import argparse + +# For finding files +# https://stackoverflow.com/questions/3207219/how-do-i-list-all-files-of-a-directory +import glob + +# external_results_dir=/var/tmp/lanforge + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) +if 'py-json' not in sys.path: + sys.path.append('../../py-json') + +from LANforge.LFUtils import * + +# if you lack __init__.py in this directory you will not find sta_connect module# + +if 'py-json' not in sys.path: + sys.path.append('../../py-scripts') + +import sta_connect2 +from sta_connect2 import StaConnect2 +import testrail_api +from testrail_api import APIClient +import eap_connect +from eap_connect import EAPConnect +import cloudsdk +from cloudsdk import CloudSDK +import ap_ssh +from ap_ssh import ssh_cli_active_fw +from ap_ssh import iwinfo_status + +##Import info for lab setup and APs under test +import lab_ap_info +from lab_ap_info import equipment_id_dict +from lab_ap_info import profile_info_dict +from lab_ap_info import cloud_sdk_models +from lab_ap_info import equipment_ip_dict +from lab_ap_info import eqiupment_credentials_dict +from lab_ap_info import ap_models +from lab_ap_info import customer_id +from lab_ap_info import cloud_type +from lab_ap_info import test_cases +from lab_ap_info import radius_info + +### Set CloudSDK URL ### +cloudSDK_url = os.getenv('CLOUD_SDK_URL') +### Directories +local_dir = os.getenv('SANITY_LOG_DIR') +report_path = os.getenv('SANITY_REPORT_DIR') +report_template = os.getenv('REPORT_TEMPLATE') + +## TestRail Information +tr_user = os.getenv('TR_USER') +tr_pw = os.getenv('TR_PWD') +milestoneId = os.getenv('MILESTONE') +projectId = os.getenv('PROJECT_ID') +testRunPrefix = os.getenv('TEST_RUN_PREFIX') + +##LANForge Information +lanforge_ip = lab_ap_info.lanforge_ip +lanforge_prefix = lab_ap_info.lanforge_prefix + +##Jfrog credentials +jfrog_user = os.getenv('JFROG_USER') +jfrog_pwd = os.getenv('JFROG_PWD') +##EAP Credentials +identity = os.getenv('EAP_IDENTITY') +ttls_password = os.getenv('EAP_PWD') + +## AP Credentials +ap_username = os.getenv('AP_USER') + +logger = logging.getLogger('Nightly_Sanity') +hdlr = logging.FileHandler(local_dir + "/Nightly_Sanity.log") +formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') +hdlr.setFormatter(formatter) +logger.addHandler(hdlr) +logger.setLevel(logging.INFO) + +testrail_url = os.getenv('TESTRAIL_URL') +client: APIClient = APIClient(testrail_url) +client.user = tr_user +client.password = tr_pw + + +###Class for jfrog Interaction +class GetBuild: + def __init__(self): + self.user = jfrog_user + self.password = jfrog_pwd + ssl._create_default_https_context = ssl._create_unverified_context + + def get_latest_image(self, url, build): + auth = str( + base64.b64encode( + bytes('%s:%s' % (self.user, self.password), 'utf-8') + ), + 'ascii' + ).strip() + headers = {'Authorization': 'Basic ' + auth} + + ''' FIND THE LATEST FILE NAME''' + # print(url) + req = urllib.request.Request(url, headers=headers) + response = urllib.request.urlopen(req) + html = response.read() + soup = BeautifulSoup(html, features="html.parser") + ##find the last pending link on dev + last_link = soup.find_all('a', href=re.compile(build))[-1] + latest_file = last_link['href'] + latest_fw = latest_file.replace('.tar.gz', '') + return latest_fw + + +###Class for Tests +class RunTest: + def Single_Client_Connectivity(self, port, radio, ssid_name, ssid_psk, security, station, test_case, rid): + '''SINGLE CLIENT CONNECTIVITY using test_connect2.py''' + staConnect = StaConnect2(lanforge_ip, 8080, debug_=False) + staConnect.sta_mode = 0 + staConnect.upstream_resource = 1 + staConnect.upstream_port = port + staConnect.radio = radio + staConnect.resource = 1 + staConnect.dut_ssid = ssid_name + staConnect.dut_passwd = ssid_psk + staConnect.dut_security = security + staConnect.station_names = station + staConnect.sta_prefix = lanforge_prefix + staConnect.runtime_secs = 10 + staConnect.bringup_time_sec = 60 + staConnect.cleanup_on_exit = True + # staConnect.cleanup() + staConnect.setup() + staConnect.start() + print("napping %f sec" % staConnect.runtime_secs) + time.sleep(staConnect.runtime_secs) + staConnect.stop() + staConnect.cleanup() + run_results = staConnect.get_result_list() + for result in run_results: + print("test result: " + result) + # result = 'pass' + print("Single Client Connectivity :", staConnect.passes) + if staConnect.passes() == True: + print("Single client connection to", ssid_name, "successful. Test Passed") + client.update_testrail(case_id=test_case, run_id=rid, status_id=1, msg='Client connectivity passed') + logger.info("Client connectivity to " + ssid_name + " Passed") + return ("passed") + else: + client.update_testrail(case_id=test_case, run_id=rid, status_id=5, msg='Client connectivity failed') + print("Single client connection to", ssid_name, "unsuccessful. Test Failed") + logger.warning("Client connectivity to " + ssid_name + " FAILED") + return ("failed") + + def Single_Client_EAP(port, sta_list, ssid_name, radio, security, eap_type, identity, ttls_password, test_case, + rid): + eap_connect = EAPConnect(lanforge_ip, 8080, _debug_on=False) + eap_connect.upstream_resource = 1 + eap_connect.upstream_port = port + eap_connect.security = security + eap_connect.sta_list = sta_list + eap_connect.station_names = sta_list + eap_connect.sta_prefix = lanforge_prefix + eap_connect.ssid = ssid_name + eap_connect.radio = radio + eap_connect.eap = eap_type + eap_connect.identity = identity + eap_connect.ttls_passwd = ttls_password + eap_connect.runtime_secs = 10 + eap_connect.setup() + eap_connect.start() + print("napping %f sec" % eap_connect.runtime_secs) + time.sleep(eap_connect.runtime_secs) + eap_connect.stop() + eap_connect.cleanup() + run_results = eap_connect.get_result_list() + for result in run_results: + print("test result: " + result) + # result = 'pass' + print("Single Client Connectivity :", eap_connect.passes) + if eap_connect.passes() == True: + print("Single client connection to", ssid_name, "successful. Test Passed") + client.update_testrail(case_id=test_case, run_id=rid, status_id=1, msg='Client connectivity passed') + logger.info("Client connectivity to " + ssid_name + " Passed") + return ("passed") + else: + client.update_testrail(case_id=test_case, run_id=rid, status_id=5, msg='Client connectivity failed') + print("Single client connection to", ssid_name, "unsuccessful. Test Failed") + logger.warning("Client connectivity to " + ssid_name + " FAILED") + return ("failed") + + def testrail_retest(self, test_case, rid, ssid_name): + client.update_testrail(case_id=test_case, run_id=rid, status_id=4, + msg='Error in Client Connectivity Test. Needs to be Re-run') + print("Error in test for single client connection to", ssid_name) + logger.warning("ERROR testing Client connectivity to " + ssid_name) + +####Use variables other than defaults for running tests on custom FW etc +build = "pending" +ignore = False +equipment_ids = equipment_id_dict + +parser = argparse.ArgumentParser(description="Sanity Testing on Firmware Build") +parser.add_argument("-b", "--build", type=str, help="FW commit ID (latest pending build on dev is default)") +parser.add_argument("-i", "--ignore", type=bool, help="Ignore current running version on AP and run sanity regardless") +parser.add_argument("-r", "--report", type=str, help="Report directory path other than default - directory must already exist!") +parser.add_argument("-m", "--model", type=str, choices=['ea8300', 'ecw5410', 'ecw5211', 'ec420'], help="AP model to be run") +args = parser.parse_args() + +if args.build is not None: + build = args.build +if args.ignore is not None: + ignore = True +if args.report is not None: + report_path = args.report +if args.model is not None: + model_id = args.model + equipment_ids = { + model_id: equipment_id_dict[model_id] + } + print(equipment_ids) + +print("Start of Sanity Testing...") +print("Testing Latest Build with Tag: "+build) +if ignore == True: + print("Will ignore if AP is already running build under test and run sanity regardless...") +else: + print("Checking for APs requiring upgrade to latest build...") + +######Testrail Project and Run ID Information ############################## + +Test: RunTest = RunTest() + +projId = client.get_project_id(project_name=projectId) +print("TIP WLAN Project ID is:", projId) + +logger.info('Start of Nightly Sanity') + +###Dictionaries +ap_latest_dict = { + "ec420": "Unknown", + "ea8300": "Unknown", + "ecw5211": "unknown", + "ecw5410": "unknown" +} + +# import json file used by throughput test +sanity_status = json.load(open("sanity_status.json")) + + +############################################################################ +#################### Create Report ######################################### +############################################################################ + +# Create Report Folder for Today +today = str(date.today()) +try: + os.mkdir(report_path + today) +except OSError: + print("Creation of the directory %s failed" % report_path) +else: + print("Successfully created the directory %s " % report_path) + +logger.info('Report data can be found here: ' + report_path + today) + +# Copy report template to folder. If template doesn't exist, continue anyway with log +try: + copyfile(report_template, report_path + today + '/report.php') + +except: + print("No report template created. Report data will still be saved. Continuing with tests...") + +##Create report_data dictionary +tc_results = dict.fromkeys(test_cases.values(), "not run") + +report_data = dict() +report_data["cloud_sdk"] = dict.fromkeys(ap_models, "") +for key in report_data["cloud_sdk"]: + report_data["cloud_sdk"][key] = { + "date": "N/A", + "commitId": "N/A", + "projectVersion": "N/A" + } +report_data["fw_available"] = dict.fromkeys(ap_models, "Unknown") +report_data["fw_under_test"] = dict.fromkeys(ap_models, "N/A") +report_data['pass_percent'] = dict.fromkeys(ap_models, "") + +report_data['tests'] = dict.fromkeys(ap_models, "") +for key in ap_models: + report_data['tests'][key] = dict.fromkeys(test_cases.values(), "not run") + +print(report_data) + +# write to report_data contents to json file so it has something in case of unexpected fail +with open(report_path + today + '/report_data.json', 'w') as report_json_file: + json.dump(report_data, report_json_file) + +###Get Cloud Bearer Token +bearer = CloudSDK.get_bearer(cloudSDK_url, cloud_type) + +############################################################################ +#################### Jfrog Firmware Check ################################## +############################################################################ + +for model in ap_models: + apModel = model + cloudModel = cloud_sdk_models[apModel] + # print(cloudModel) + ###Check Latest FW on jFrog + jfrog_url = 'https://tip.jfrog.io/artifactory/tip-wlan-ap-firmware/' + url = jfrog_url + apModel + "/dev/" + Build: GetBuild = GetBuild() + latest_image = Build.get_latest_image(url, build) + print(model, "Latest FW on jFrog:", latest_image) + ap_latest_dict[model] = latest_image + +#################################################################################### +############ Update FW and Run Test Cases on Each AP Variant ####################### +#################################################################################### +#################################################################################### + +for key in equipment_ids: + ##Get Bearer Token to make sure its valid (long tests can require re-auth) + bearer = CloudSDK.get_bearer(cloudSDK_url, cloud_type) + + ###Get Current AP Firmware and upgrade + equipment_id = equipment_id_dict[key] + ap_ip = equipment_ip_dict[key] + ap_username = "root" + ap_password = eqiupment_credentials_dict[key] + print("AP MODEL UNDER TEST IS", key) + try: + ap_cli_info = ssh_cli_active_fw(ap_ip, ap_username, ap_password) + ap_cli_fw = ap_cli_info['active_fw'] + except: + ap_cli_info = "ERROR" + print("Cannot Reach AP CLI, will not test this variant") + continue + + fw_model = ap_cli_fw.partition("-")[0] + print('Current Active AP FW from CLI:', ap_cli_fw) + ###Find Latest FW for Current AP Model and Get FW ID + + ##Compare Latest and Current AP FW and Upgrade + latest_ap_image = ap_latest_dict[fw_model] + if ap_cli_fw == latest_ap_image and ignore != True: + print('FW does not require updating') + report_data['fw_available'][key] = "No" + logger.info(fw_model + " does not require upgrade. Not performing sanity tests for this AP variant") + cloudsdk_cluster_info = { + "date": "N/A", + "commitId": "N/A", + "projectVersion": "N/A" + } + report_data['cloud_sdk'][key] = cloudsdk_cluster_info + + else: + if ap_cli_fw == latest_ap_image and ignore == True: + print('AP is already running FW version under test. Ignored based on ignore flag, updating AP') + else: + print('FW needs updating') + report_data['fw_available'][key] = "Yes" + report_data['fw_under_test'][key] = latest_ap_image + + ###Create Test Run + today = str(date.today()) + case_ids = list(test_cases.values()) + test_run_name = testRunPrefix + fw_model + "_" + today + "_" + latest_ap_image + client.create_testrun(name=test_run_name, case_ids=case_ids, project_id=projId, milestone_id=milestoneId, + description="Automated Nightly Sanity test run for new firmware build") + rid = client.get_run_id(test_run_name= testRunPrefix + fw_model + "_" + today + "_" + latest_ap_image) + print("TIP run ID is:", rid) + + ###GetCloudSDK Version + print("Getting CloudSDK version information...") + try: + cluster_ver = CloudSDK.get_cloudsdk_version(cloudSDK_url, bearer) + print("CloudSDK Version Information:") + print("-------------------------------------------") + print(cluster_ver) + print("-------------------------------------------") + + cloudsdk_cluster_info = {} + cloudsdk_cluster_info['date'] = cluster_ver['commitDate'] + cloudsdk_cluster_info['commitId'] = cluster_ver['commitID'] + cloudsdk_cluster_info['projectVersion'] = cluster_ver['projectVersion'] + report_data['cloud_sdk'][key] = cloudsdk_cluster_info + client.update_testrail(case_id=test_cases["cloud_ver"], run_id=rid, status_id=1, + msg='Read CloudSDK version from API successfully') + report_data['tests'][key][test_cases["cloud_ver"]] = "passed" + + except: + cluster_ver = 'error' + print("ERROR: CloudSDK Version Unavailable") + logger.info('CloudSDK version Unavailable') + cloudsdk_cluster_info = { + "date": "unknown", + "commitId": "unknown", + "projectVersion": "unknown" + } + client.update_testrail(case_id=test_cases["cloud_ver"], run_id=rid, status_id=5, + msg='Could not read CloudSDK version from API') + report_data['cloud_sdk'][key] = cloudsdk_cluster_info + report_data['tests'][key][test_cases["cloud_ver"]] = "failed" + + with open(report_path + today + '/report_data.json', 'w') as report_json_file: + json.dump(report_data, report_json_file) + + ###Test Create Firmware Version + test_id_fw = test_cases["create_fw"] + latest_image = ap_latest_dict[key] + cloudModel = cloud_sdk_models[key] + print(cloudModel) + firmware_list_by_model = CloudSDK.CloudSDK_images(cloudModel, cloudSDK_url, bearer) + print("Available", cloudModel, "Firmware on CloudSDK:", firmware_list_by_model) + + if latest_image in firmware_list_by_model: + print("Latest Firmware", latest_image, "is already on CloudSDK, need to delete to test create FW API") + old_fw_id = CloudSDK.get_firmware_id(latest_image, cloudSDK_url, bearer) + delete_fw = CloudSDK.delete_firmware(str(old_fw_id), cloudSDK_url, bearer) + fw_url = "https://" + jfrog_user + ":" + jfrog_pwd + "@tip.jfrog.io/artifactory/tip-wlan-ap-firmware/" + key + "/dev/" + latest_image + ".tar.gz" + commit = latest_image.split("-")[-1] + try: + fw_upload_status = CloudSDK.firwmare_upload(commit, cloudModel, latest_image, fw_url, cloudSDK_url, + bearer) + fw_id = fw_upload_status['id'] + print("Upload Complete.", latest_image, "FW ID is", fw_id) + client.update_testrail(case_id=test_id_fw, run_id=rid, status_id=1, + msg='Create new FW version by API successful') + report_data['tests'][key][test_id_fw] = "passed" + except: + fw_upload_status = 'error' + print("Unable to upload new FW version. Skipping Sanity on AP Model") + client.update_testrail(case_id=test_id_fw, run_id=rid, status_id=5, + msg='Error creating new FW version by API') + report_data['tests'][key][test_id_fw] = "failed" + continue + else: + print("Latest Firmware is not on CloudSDK! Uploading...") + fw_url = "https://" + jfrog_user + ":" + jfrog_pwd + "@tip.jfrog.io/artifactory/tip-wlan-ap-firmware/" + key + "/dev/" + latest_image + ".tar.gz" + commit = latest_image.split("-")[-1] + try: + fw_upload_status = CloudSDK.firwmare_upload(commit, cloudModel, latest_image, fw_url, cloudSDK_url, + bearer) + fw_id = fw_upload_status['id'] + print("Upload Complete.", latest_image, "FW ID is", fw_id) + client.update_testrail(case_id=test_id_fw, run_id=rid, status_id=1, + msg='Create new FW version by API successful') + report_data['tests'][key][test_id_fw] = "passed" + except: + fw_upload_status = 'error' + print("Unable to upload new FW version. Skipping Sanity on AP Model") + client.update_testrail(case_id=test_id_fw, run_id=rid, status_id=5, + msg='Error creating new FW version by API') + report_data['tests'][key][test_id_fw] = "failed" + continue + + # Upgrade AP firmware + print("Upgrading...firmware ID is: ", fw_id) + upgrade_fw = CloudSDK.update_firmware(equipment_id, str(fw_id), cloudSDK_url, bearer) + logger.info("Lab " + fw_model + " Requires FW update") + print(upgrade_fw) + + if "success" in upgrade_fw: + if upgrade_fw["success"] == True: + print("CloudSDK Upgrade Request Success") + report_data['tests'][key][test_cases["upgrade_api"]] = "passed" + client.update_testrail(case_id=test_cases["upgrade_api"], run_id=rid, status_id=1, msg='Upgrade request using API successful') + logger.info('Firmware upgrade API successfully sent') + else: + print("Cloud SDK Upgrade Request Error!") + # mark upgrade test case as failed with CloudSDK error + client.update_testrail(case_id=test_cases["upgrade_api"], run_id=rid, status_id=5, msg='Error requesting upgrade via API') + report_data['tests'][key][test_cases["upgrade_api"]] = "failed" + logger.warning('Firmware upgrade API failed to send') + continue + else: + print("Cloud SDK Upgrade Request Error!") + # mark upgrade test case as failed with CloudSDK error + client.update_testrail(case_id=test_cases["upgrade_api"], run_id=rid, status_id=5,msg='Error requesting upgrade via API') + report_data['tests'][key][test_cases["upgrade_api"]] = "failed" + logger.warning('Firmware upgrade API failed to send') + continue + + time.sleep(300) + + # Check if upgrade success is displayed on CloudSDK + test_id_cloud = test_cases["cloud_fw"] + cloud_ap_fw = CloudSDK.ap_firmware(customer_id, equipment_id, cloudSDK_url, bearer) + print('Current AP Firmware from CloudSDK:', cloud_ap_fw) + logger.info('AP Firmware from CloudSDK: ' + cloud_ap_fw) + if cloud_ap_fw == "ERROR": + print("AP FW Could not be read from CloudSDK") + + elif cloud_ap_fw == latest_ap_image: + print("CloudSDK status shows upgrade successful!") + + else: + print("AP FW from CloudSDK status is not latest build. Will check AP CLI.") + + # Check if upgrade successful on AP CLI + test_id_cli = test_cases["ap_upgrade"] + try: + ap_cli_info = ssh_cli_active_fw(ap_ip, ap_username, ap_password) + ap_cli_fw = ap_cli_info['active_fw'] + print("CLI reporting AP Active FW as:", ap_cli_fw) + logger.info('Firmware from CLI: ' + ap_cli_fw) + except: + ap_cli_info = "ERROR" + print("Cannot Reach AP CLI to confirm upgrade!") + logger.warning('Cannot Reach AP CLI to confirm upgrade!') + client.update_testrail(case_id=test_id_cli, run_id=rid, status_id=4, + msg='Cannot reach AP after upgrade to check CLI - re-test required') + continue + + if cloud_ap_fw == latest_ap_image and ap_cli_fw == latest_ap_image: + print("CloudSDK and AP CLI both show upgrade success, passing upgrade test case") + client.update_testrail(case_id=test_id_cli, run_id=rid, status_id=1, + msg='Upgrade to ' + latest_ap_image + ' successful') + client.update_testrail(case_id=test_id_cloud, run_id=rid, status_id=1, + msg='CLOUDSDK reporting correct firmware version.') + report_data['tests'][key][test_id_cli] = "passed" + report_data['tests'][key][test_id_cloud] = "passed" + print(report_data['tests'][key]) + + elif cloud_ap_fw != latest_ap_image and ap_cli_fw == latest_ap_image: + print("AP CLI shows upgrade success - CloudSDK reporting error!") + ##Raise CloudSDK error but continue testing + client.update_testrail(case_id=test_id_cli, run_id=rid, status_id=1, + msg='Upgrade to ' + latest_ap_image + ' successful.') + client.update_testrail(case_id=test_id_cloud, run_id=rid, status_id=5, + msg='CLOUDSDK reporting incorrect firmware version.') + report_data['tests'][key][test_id_cli] = "passed" + report_data['tests'][key][test_id_cloud] = "failed" + print(report_data['tests'][key]) + + elif cloud_ap_fw == latest_ap_image and ap_cli_fw != latest_ap_image: + print("AP CLI shows upgrade failed - CloudSDK reporting error!") + # Testrail TC fail + client.update_testrail(case_id=test_id_cli, run_id=rid, status_id=5, + msg='AP failed to download or apply new FW. Upgrade to ' + latest_ap_image + ' Failed') + client.update_testrail(case_id=test_id_cloud, run_id=rid, status_id=5, + msg='CLOUDSDK reporting incorrect firmware version.') + report_data['tests'][key][test_id_cli] = "failed" + report_data['tests'][key][test_id_cloud] = "failed" + print(report_data['tests'][key]) + continue + + elif cloud_ap_fw != latest_ap_image and ap_cli_fw != latest_ap_image: + print("Upgrade Failed! Confirmed on CloudSDK and AP CLI. Upgrade test case failed.") + ##fail TR testcase and exit + client.update_testrail(case_id=test_id_cli, run_id=rid, status_id=5, + msg='AP failed to download or apply new FW. Upgrade to ' + latest_ap_image + ' Failed') + report_data['tests'][key][test_id_cli] = "failed" + print(report_data['tests'][key]) + continue + + else: + print("Unable to determine upgrade status. Skipping AP variant") + # update TR testcase as error + client.update_testrail(case_id=test_id_cli, run_id=rid, status_id=4, + msg='Cannot determine upgrade status - re-test required') + report_data['tests'][key][test_id_cli] = "error" + print(report_data['tests'][key]) + continue + + print(report_data) + + ###Check AP Manager Status + manager_status = ap_cli_info['state'] + + if manager_status != "active": + print("Manager status is " + manager_status + "! Not connected to the cloud.") + print("Waiting 30 seconds and re-checking status") + time.sleep(30) + ap_cli_info = ssh_cli_active_fw(ap_ip, ap_username, ap_password) + manager_status = ap_cli_info['state'] + if manager_status != "active": + print("Manager status is", manager_status, "! Not connected to the cloud.") + print("Manager status fails multiple checks - failing test case.") + ##fail cloud connectivity testcase + client.update_testrail(case_id=test_cases["cloud_connection"], run_id=rid, status_id=5, msg='CloudSDK connectivity failed') + report_data['tests'][key][test_cases["cloud_connection"]] = "failed" + print(report_data['tests'][key]) + continue + else: + print("Manager status is Active. Proceeding to connectivity testing!") + # TC522 pass in Testrail + client.update_testrail(case_id=test_cases["cloud_connection"], run_id=rid, status_id=1, msg='Manager status is Active') + report_data['tests'][key][test_cases["cloud_connection"]] = "passed" + print(report_data['tests'][key]) + else: + print("Manager status is Active. Proceeding to connectivity testing!") + # TC5222 pass in testrail + client.update_testrail(case_id=test_cases["cloud_connection"], run_id=rid, status_id=1, msg='Manager status is Active') + report_data['tests'][key][test_cases["cloud_connection"]] = "passed" + print(report_data['tests'][key]) + # Pass cloud connectivity test case + + ###Update report json + with open(report_path + today + '/report_data.json', 'w') as report_json_file: + json.dump(report_data, report_json_file) + + ### Create RADIUS profile - used for all EAP SSIDs + radius_template = "templates/radius_profile_template.json" + radius_name = radius_info['name'] + subnet_name = radius_info['subnet_name'] + subnet = radius_info['subnet'] + subnet_mask = radius_info['subnet_mask'] + region = radius_info['region'] + server_name = radius_info['server_name'] + server_ip = radius_info['server_ip'] + secret = radius_info['secret'] + auth_port = radius_info['auth_port'] + try: + radius_profile = CloudSDK.create_radius_profile(cloudSDK_url, bearer, radius_template, radius_name, subnet_name, subnet, + subnet_mask, region, server_name, server_ip, secret, auth_port) + print("radius profile Id is", radius_profile) + client.update_testrail(case_id=test_cases["radius_profile"], run_id=rid, status_id=1, + msg='RADIUS profile created successfully') + report_data['tests'][key][test_cases["radius_profile"]] = "passed" + except: + radius_profile = 'error' + print("RADIUS Profile Create Error, will use existing profile for tests") + #Set backup profile ID so test can continue + radius_profile = lab_ap_info.radius_profile + server_name = "Lab-RADIUS" + client.update_testrail(case_id=test_cases["radius_profile"], run_id=rid, status_id=5, + msg='Failed to create RADIUS profile') + report_data['tests'][key][test_cases["radius_profile"]] = "failed" + + ########################################################################### + ############## Bridge Mode Client Connectivity ############################ + ########################################################################### + + ### Create SSID Profiles + ssid_template = "templates/ssid_profile_template.json" + + # 5G SSIDs + try: + fiveG_eap = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, fw_model + '_5G_EAP_' + today, + profile_info_dict[fw_model]["fiveG_WPA2-EAP_SSID"], None, + radius_name, + "wpa2OnlyRadius", "BRIDGE", 1, ["is5GHzU", "is5GHz", "is5GHzL"]) + print("5G EAP SSID created successfully - bridge mode") + client.update_testrail(case_id=test_cases["ssid_5g_eap_bridge"], run_id=rid, status_id=1, msg='5G EAP SSID created successfully - bridge mode') + report_data['tests'][key][test_cases["ssid_5g_eap_bridge"]] = "passed" + + except: + fiveG_eap = "error" + print("5G EAP SSID create failed - bridge mode") + client.update_testrail(case_id=test_cases["ssid_5g_eap_bridge"], run_id=rid, status_id=5, + msg='5G EAP SSID create failed - bridge mode') + report_data['tests'][key][test_cases["ssid_5g_eap_bridge"]] = "failed" + fiveG_eap = profile_info_dict[fw_model]["fiveG_WPA2-EAP_profile"] + + try: + fiveG_wpa2 = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, fw_model + '_5G_WPA2_' + today, + profile_info_dict[fw_model]["fiveG_WPA2_SSID"], + profile_info_dict[fw_model]["fiveG_WPA2_PSK"], + "Radius-Accounting-Profile", "wpa2OnlyPSK", "BRIDGE", 1, + ["is5GHzU", "is5GHz", "is5GHzL"]) + print("5G WPA2 SSID created successfully - bridge mode") + client.update_testrail(case_id=test_cases["ssid_5g_wpa2_bridge"], run_id=rid, status_id=1, msg='5G WPA2 SSID created successfully - bridge mode') + report_data['tests'][key][test_cases["ssid_5g_wpa2_bridge"]] = "passed" + except: + fiveG_wpa2 = "error" + print("5G WPA2 SSID create failed - bridge mode") + client.update_testrail(case_id=test_cases["ssid_5g_wpa2_bridge"], run_id=rid, status_id=5, + msg='5G WPA2 SSID create failed - bridge mode') + report_data['tests'][key][test_cases["ssid_5g_wpa2_bridge"]] = "failed" + fiveG_wpa2 = profile_info_dict[fw_model]["fiveG_WPA2_profile"] + + try: + fiveG_wpa = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, fw_model + '_5G_WPA_' + today, + profile_info_dict[fw_model]["fiveG_WPA_SSID"], + profile_info_dict[fw_model]["fiveG_WPA_PSK"], + "Radius-Accounting-Profile", "wpaPSK", "BRIDGE", 1, + ["is5GHzU", "is5GHz", "is5GHzL"]) + print("5G WPA SSID created successfully - bridge mode") + client.update_testrail(case_id=test_cases["ssid_5g_wpa_bridge"], run_id=rid, status_id=1, + msg='5G WPA SSID created successfully - bridge mode') + report_data['tests'][key][test_cases["ssid_5g_wpa_bridge"]] = "passed" + except: + fiveG_wpa = "error" + print("5G WPA SSID create failed - bridge mode") + client.update_testrail(case_id=test_cases["ssid_5g_wpa_bridge"], run_id=rid, status_id=5, + msg='5G WPA SSID create failed - bridge mode') + report_data['tests'][key][test_cases["ssid_5g_wpa_bridge"]] = "failed" + fiveG_wpa = profile_info_dict[fw_model]["fiveG_WPA_profile"] + + # 2.4G SSIDs + try: + twoFourG_eap = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_2G_EAP_' + today, + profile_info_dict[fw_model]["twoFourG_WPA2-EAP_SSID"], None, + radius_name, "wpa2OnlyRadius", "BRIDGE", 1, ["is2dot4GHz"]) + print("2.4G EAP SSID created successfully - bridge mode") + client.update_testrail(case_id=test_cases["ssid_2g_eap_bridge"], run_id=rid, status_id=1, + msg='2.4G EAP SSID created successfully - bridge mode') + report_data['tests'][key][test_cases["ssid_2g_eap_bridge"]] = "passed" + except: + twoFourG_eap = "error" + print("2.4G EAP SSID create failed - bridge mode") + client.update_testrail(case_id=test_cases["ssid_2g_eap_bridge"], run_id=rid, status_id=5, + msg='2.4G EAP SSID create failed - bridge mode') + report_data['tests'][key][test_cases["ssid_2g_eap_bridge"]] = "failed" + twoFourG_eap = profile_info_dict[fw_model]["twoFourG_WPA2-EAP_SSID"] + + try: + twoFourG_wpa2 = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_2G_WPA2_' + today, + profile_info_dict[fw_model]["twoFourG_WPA2_SSID"], + profile_info_dict[fw_model]["twoFourG_WPA2_PSK"], + "Radius-Accounting-Profile", "wpa2OnlyPSK", "BRIDGE", 1, + ["is2dot4GHz"]) + print("2.4G WPA2 SSID created successfully - bridge mode") + client.update_testrail(case_id=test_cases["ssid_2g_wpa2_bridge"], run_id=rid, status_id=1, + msg='2.4G WPA2 SSID created successfully - bridge mode') + report_data['tests'][key][test_cases["ssid_2g_wpa2_bridge"]] = "passed" + except: + twoFourG_wpa2 = "error" + print("2.4G WPA2 SSID create failed - bridge mode") + client.update_testrail(case_id=test_cases["ssid_2g_wpa2_bridge"], run_id=rid, status_id=5, + msg='2.4G WPA2 SSID create failed - bridge mode') + report_data['tests'][key][test_cases["ssid_2g_wpa2_bridge"]] = "failed" + twoFourG_wpa2 = profile_info_dict[fw_model]["twoFourG_WPA2_SSID"] + + try: + twoFourG_wpa = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_2G_WPA_' + today, + profile_info_dict[fw_model]["twoFourG_WPA_SSID"], + profile_info_dict[fw_model]["twoFourG_WPA_PSK"], + "Radius-Accounting-Profile", "wpaPSK", "BRIDGE", 1, + ["is2dot4GHz"]) + print("2.4G WPA SSID created successfully - bridge mode") + client.update_testrail(case_id=test_cases["ssid_2g_wpa_bridge"], run_id=rid, status_id=1, + msg='2.4G WPA SSID created successfully - bridge mode') + report_data['tests'][key][test_cases["ssid_2g_wpa_bridge"]] = "passed" + except: + twoFourG_wpa = "error" + print("2.4G WPA SSID create failed - bridge mode") + client.update_testrail(case_id=test_cases["ssid_2g_wpa_bridge"], run_id=rid, status_id=5, + msg='2.4G WPA SSID create failed - bridge mode') + report_data['tests'][key][test_cases["ssid_2g_wpa_bridge"]] = "failed" + twoFourG_wpa = profile_info_dict[fw_model]["twoFourG_WPA_SSID"] + + ### Create AP Bridge Profile + rfProfileId = lab_ap_info.rf_profile + radiusProfileId = radius_profile + child_profiles = [fiveG_eap, fiveG_wpa2, fiveG_wpa, twoFourG_eap, twoFourG_wpa2, twoFourG_wpa, rfProfileId, radiusProfileId] + print(child_profiles) + + ap_template = "templates/ap_profile_template.json" + name = "Nightly_Sanity_" + fw_model + "_" + today + "_bridge" + + try: + create_ap_profile = CloudSDK.create_ap_profile(cloudSDK_url, bearer, ap_template, name, child_profiles) + test_profile_id = create_ap_profile + print("Test Profile ID for Test is:",test_profile_id) + client.update_testrail(case_id=test_cases["ap_bridge"], run_id=rid, status_id=1, + msg='AP profile for bridge tests created successfully') + report_data['tests'][key][test_cases["ap_bridge"]] = "passed" + except: + create_ap_profile = "error" + test_profile_id = profile_info_dict[fw_model]["profile_id"] + print("Error creating AP profile for bridge tests. Will use existing AP profile") + client.update_testrail(case_id=test_cases["ap_bridge"], run_id=rid, status_id=5, + msg='AP profile for bridge tests could not be created using API') + report_data['tests'][key][test_cases["ap_bridge"]] = "failed" + + ### Set Proper AP Profile for Bridge SSID Tests + ap_profile = CloudSDK.set_ap_profile(equipment_id, test_profile_id, cloudSDK_url, bearer) + + ### Wait for Profile Push + time.sleep(180) + + ### Check if VIF Config and VIF State reflect AP Profile from CloudSDK + ## VIF Config + try: + ssid_config = profile_info_dict[key]["ssid_list"] + print("SSIDs in AP Profile:", ssid_config) + + ssid_list = ap_ssh.get_vif_config(ap_ip, ap_username, ap_password) + print("SSIDs in AP VIF Config:", ssid_list) + + if set(ssid_list) == set(ssid_config): + print("SSIDs in Wifi_VIF_Config Match AP Profile Config") + client.update_testrail(case_id=test_cases["bridge_vifc"], run_id=rid, status_id=1, + msg='SSIDs in VIF Config matches AP Profile Config') + report_data['tests'][key][test_cases["bridge_vifc"]] = "passed" + else: + print("SSIDs in Wifi_VIF_Config do not match desired AP Profile Config") + client.update_testrail(case_id=test_cases["bridge_vifc"], run_id=rid, status_id=5, + msg='SSIDs in VIF Config do not match AP Profile Config') + report_data['tests'][key][test_cases["bridge_vifc"]] = "failed" + except: + ssid_list = "ERROR" + print("Error accessing VIF Config from AP CLI") + client.update_testrail(case_id=test_cases["bridge_vifc"], run_id=rid, status_id=4, + msg='Cannot determine VIF Config - re-test required') + report_data['tests'][key][test_cases["bridge_vifc"]] = "error" + # VIF State + try: + ssid_state = ap_ssh.get_vif_state(ap_ip, ap_username, ap_password) + print("SSIDs in AP VIF State:", ssid_state) + + if set(ssid_state) == set(ssid_config): + print("SSIDs properly applied on AP") + client.update_testrail(case_id=test_cases["bridge_vifs"], run_id=rid, status_id=1, + msg='SSIDs in VIF Config applied to VIF State') + report_data['tests'][key][test_cases["bridge_vifs"]] = "passed" + else: + print("SSIDs not applied on AP") + client.update_testrail(case_id=test_cases["bridge_vifs"], run_id=rid, status_id=5, + msg='SSIDs in VIF Config not applied to VIF State') + report_data['tests'][key][test_cases["bridge_vifs"]] = "failed" + except: + ssid_list = "ERROR" + print("Error accessing VIF State from AP CLI") + print("Error accessing VIF Config from AP CLI") + client.update_testrail(case_id=test_cases["bridge_vifs"], run_id=rid, status_id=4, + msg='Cannot determine VIF State - re-test required') + report_data['tests'][key][test_cases["bridge_vifs"]] = "error" + + ### Set LANForge port for tests + port = "eth2" + + # print iwinfo for information + iwinfo = iwinfo_status(ap_ip, ap_username, ap_password) + print(iwinfo) + + ###Run Client Single Connectivity Test Cases for Bridge SSIDs + # TC5214 - 2.4 GHz WPA2-Enterprise + test_case = test_cases["2g_eap_bridge"] + radio = lab_ap_info.lanforge_2dot4g + sta_list = [lanforge_prefix+"5214"] + ssid_name = profile_info_dict[fw_model]["twoFourG_WPA2-EAP_SSID"] + security = "wpa2" + eap_type = "TTLS" + try: + test_result = RunTest.Single_Client_EAP(port, sta_list, ssid_name, radio, security, eap_type, identity, + ttls_password, test_case, rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + ###Run Client Single Connectivity Test Cases for Bridge SSIDs + # TC - 2.4 GHz WPA2 + test_case = test_cases["2g_wpa2_bridge"] + radio = lab_ap_info.lanforge_2dot4g + station = [lanforge_prefix+"2237"] + ssid_name = profile_info_dict[fw_model]["twoFourG_WPA2_SSID"] + ssid_psk = profile_info_dict[fw_model]["twoFourG_WPA2_PSK"] + security = "wpa2" + try: + test_result = Test.Single_Client_Connectivity(port, radio, ssid_name, ssid_psk, security, station, + test_case, + rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC - 2.4 GHz WPA + test_case = test_cases["2g_wpa_bridge"] + radio = lab_ap_info.lanforge_2dot4g + station = [lanforge_prefix+"2420"] + ssid_name = profile_info_dict[fw_model]["twoFourG_WPA_SSID"] + ssid_psk = profile_info_dict[fw_model]["twoFourG_WPA_PSK"] + security = "wpa" + try: + test_result = Test.Single_Client_Connectivity(port, radio, ssid_name, ssid_psk, security, station, + test_case, + rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC - 5 GHz WPA2-Enterprise + test_case = test_cases["5g_eap_bridge"] + radio = lab_ap_info.lanforge_5g + sta_list = [lanforge_prefix+"5215"] + ssid_name = profile_info_dict[fw_model]["fiveG_WPA2-EAP_SSID"] + security = "wpa2" + eap_type = "TTLS" + try: + test_result = RunTest.Single_Client_EAP(port, sta_list, ssid_name, radio, security, eap_type, identity, + ttls_password, test_case, rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC 5 GHz WPA2 + test_case = test_cases["5g_wpa2_bridge"] + radio = lab_ap_info.lanforge_5g + station = [lanforge_prefix+"2236"] + ssid_name = profile_info_dict[fw_model]["fiveG_WPA2_SSID"] + ssid_psk = profile_info_dict[fw_model]["fiveG_WPA2_PSK"] + security = "wpa2" + try: + test_result = Test.Single_Client_Connectivity(port, radio, ssid_name, ssid_psk, security, station, + test_case, + rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC - 5 GHz WPA + test_case = test_cases["5g_wpa_bridge"] + radio = lab_ap_info.lanforge_5g + station = [lanforge_prefix+"2419"] + ssid_name = profile_info_dict[fw_model]["fiveG_WPA_SSID"] + ssid_psk = profile_info_dict[fw_model]["fiveG_WPA_PSK"] + security = "wpa" + try: + test_result = Test.Single_Client_Connectivity(port, radio, ssid_name, ssid_psk, security, station, + test_case, + rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + logger.info("Testing for " + fw_model + "Bridge Mode SSIDs Complete") + with open(report_path + today + '/report_data.json', 'w') as report_json_file: + json.dump(report_data, report_json_file) + + ########################################################################### + ################# NAT Mode Client Connectivity ############################ + ########################################################################### + + ### Create SSID Profiles + ssid_template = "templates/ssid_profile_template.json" + + # 5G SSIDs + try: + fiveG_eap = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_5G_EAP_NAT_' + today, + profile_info_dict[fw_model + '_nat']["fiveG_WPA2-EAP_SSID"], None, + radius_name, + "wpa2OnlyRadius", "NAT", 1, + ["is5GHzU", "is5GHz", "is5GHzL"]) + print("5G EAP SSID created successfully - NAT mode") + client.update_testrail(case_id=test_cases["ssid_5g_eap_nat"], run_id=rid, status_id=1, + msg='5G EAP SSID created successfully - NAT mode') + report_data['tests'][key][test_cases["ssid_5g_eap_nat"]] = "passed" + + except: + fiveG_eap = "error" + print("5G EAP SSID create failed - NAT mode") + client.update_testrail(case_id=test_cases["ssid_5g_eap_nat"], run_id=rid, status_id=5, + msg='5G EAP SSID create failed - NAT mode') + report_data['tests'][key][test_cases["ssid_5g_eap_nat"]] = "failed" + fiveG_eap = profile_info_dict[fw_model + '_nat']["fiveG_WPA2-EAP_profile"] + + try: + fiveG_wpa2 = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_5G_WPA2_NAT_' + today, + profile_info_dict[fw_model + '_nat']["fiveG_WPA2_SSID"], + profile_info_dict[fw_model + '_nat']["fiveG_WPA2_PSK"], + "Radius-Accounting-Profile", "wpa2OnlyPSK", "NAT", 1, + ["is5GHzU", "is5GHz", "is5GHzL"]) + print("5G WPA2 SSID created successfully - NAT mode") + client.update_testrail(case_id=test_cases["ssid_5g_wpa2_nat"], run_id=rid, status_id=1, + msg='5G WPA2 SSID created successfully - NAT mode') + report_data['tests'][key][test_cases["ssid_5g_wpa2_nat"]] = "passed" + except: + fiveG_wpa2 = "error" + print("5G WPA2 SSID create failed - NAT mode") + client.update_testrail(case_id=test_cases["ssid_5g_wpa2_nat"], run_id=rid, status_id=5, + msg='5G WPA2 SSID create failed - NAT mode') + report_data['tests'][key][test_cases["ssid_5g_wpa2_nat"]] = "failed" + fiveG_wpa2 = profile_info_dict[fw_model + '_nat']["fiveG_WPA2_profile"] + + try: + fiveG_wpa = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_5G_WPA_NAT_' + today, + profile_info_dict[fw_model + '_nat']["fiveG_WPA_SSID"], + profile_info_dict[fw_model + '_nat']["fiveG_WPA_PSK"], + "Radius-Accounting-Profile", "wpaPSK", "NAT", 1, + ["is5GHzU", "is5GHz", "is5GHzL"]) + print("5G WPA SSID created successfully - NAT mode") + client.update_testrail(case_id=test_cases["ssid_5g_wpa_nat"], run_id=rid, status_id=1, + msg='5G WPA SSID created successfully - NAT mode') + report_data['tests'][key][test_cases["ssid_5g_wpa_nat"]] = "passed" + except: + fiveG_wpa = "error" + print("5G WPA SSID create failed - NAT mode") + client.update_testrail(case_id=test_cases["ssid_5g_wpa_nat"], run_id=rid, status_id=5, + msg='5G WPA SSID create failed - NAT mode') + report_data['tests'][key][test_cases["ssid_5g_wpa_nat"]] = "failed" + fiveG_wpa = profile_info_dict[fw_model + '_nat']["fiveG_WPA_profile"] + + # 2.4G SSIDs + try: + twoFourG_eap = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_2G_EAP_NAT_' + today, + profile_info_dict[fw_model + '_nat']["twoFourG_WPA2-EAP_SSID"], + None, + radius_name, "wpa2OnlyRadius", "NAT", 1, ["is2dot4GHz"]) + print("2.4G EAP SSID created successfully - NAT mode") + client.update_testrail(case_id=test_cases["ssid_2g_eap_nat"], run_id=rid, status_id=1, + msg='2.4G EAP SSID created successfully - NAT mode') + report_data['tests'][key][test_cases["ssid_2g_eap_nat"]] = "passed" + except: + twoFourG_eap = "error" + print("2.4G EAP SSID create failed - NAT mode") + client.update_testrail(case_id=test_cases["ssid_2g_eap_nat"], run_id=rid, status_id=5, + msg='2.4G EAP SSID create failed - NAT mode') + report_data['tests'][key][test_cases["ssid_2g_eap_nat"]] = "failed" + twoFourG_eap = profile_info_dict[fw_model + '_nat']["twoFourG_WPA2-EAP_SSID"] + + try: + twoFourG_wpa2 = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_2G_WPA2_NAT_' + today, + profile_info_dict[fw_model + '_nat']["twoFourG_WPA2_SSID"], + profile_info_dict[fw_model + '_nat']["twoFourG_WPA2_PSK"], + "Radius-Accounting-Profile", "wpa2OnlyPSK", "NAT", 1, + ["is2dot4GHz"]) + print("2.4G WPA2 SSID created successfully - NAT mode") + client.update_testrail(case_id=test_cases["ssid_2g_wpa2_nat"], run_id=rid, status_id=1, + msg='2.4G WPA2 SSID created successfully - NAT mode') + report_data['tests'][key][test_cases["ssid_2g_wpa2_nat"]] = "passed" + except: + twoFourG_wpa2 = "error" + print("2.4G WPA2 SSID create failed - NAT mode") + client.update_testrail(case_id=test_cases["ssid_2g_wpa2_nat"], run_id=rid, status_id=5, + msg='2.4G WPA2 SSID create failed - NAT mode') + report_data['tests'][key][test_cases["ssid_2g_wpa2_nat"]] = "failed" + twoFourG_wpa2 = profile_info_dict[fw_model + '_nat']["twoFourG_WPA2_SSID"] + + try: + twoFourG_wpa = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_2G_WPA_NAT_' + today, + profile_info_dict[fw_model + '_nat']["twoFourG_WPA_SSID"], + profile_info_dict[fw_model + '_nat']["twoFourG_WPA_PSK"], + "Radius-Accounting-Profile", "wpaPSK", "NAT", 1, + ["is2dot4GHz"]) + print("2.4G WPA SSID created successfully - NAT mode") + client.update_testrail(case_id=test_cases["ssid_2g_wpa_nat"], run_id=rid, status_id=1, + msg='2.4G WPA SSID created successfully - NAT mode') + report_data['tests'][key][test_cases["ssid_2g_wpa_nat"]] = "passed" + except: + twoFourG_wpa = "error" + print("2.4G WPA SSID create failed - NAT mode") + client.update_testrail(case_id=test_cases["ssid_2g_wpa_nat"], run_id=rid, status_id=5, + msg='2.4G WPA SSID create failed - NAT mode') + report_data['tests'][key][test_cases["ssid_2g_wpa_nat"]] = "failed" + twoFourG_wpa = profile_info_dict[fw_model + '_nat']["twoFourG_WPA_SSID"] + + ### Create AP NAT Profile + rfProfileId = lab_ap_info.rf_profile + radiusProfileId = radius_profile + child_profiles = [fiveG_eap, fiveG_wpa2, fiveG_wpa, twoFourG_eap, twoFourG_wpa2, twoFourG_wpa, rfProfileId, + radiusProfileId] + print(child_profiles) + ap_template = "templates/ap_profile_template.json" + name = "Nightly_Sanity_" + fw_model + "_" + today + "_nat" + try: + create_ap_profile = CloudSDK.create_ap_profile(cloudSDK_url, bearer, ap_template, name, child_profiles) + test_profile_id = create_ap_profile + print("Test Profile ID for Test is:", test_profile_id) + client.update_testrail(case_id=test_cases["ap_nat"], run_id=rid, status_id=1, + msg='AP profile for NAT tests created successfully') + report_data['tests'][key][test_cases["ap_nat"]] = "passed" + except: + create_ap_profile = "error" + test_profile_id = profile_info_dict[fw_model + '_nat']["profile_id"] + print("Error creating AP profile for NAT tests. Will use existing AP profile") + client.update_testrail(case_id=test_cases["ap_nat"], run_id=rid, status_id=5, + msg='AP profile for NAT tests could not be created using API') + report_data['tests'][key][test_cases["ap_nat"]] = "failed" + + ###Set Proper AP Profile for NAT SSID Tests + ap_profile = CloudSDK.set_ap_profile(equipment_id, test_profile_id, cloudSDK_url, bearer) + + ### Wait for Profile Push + time.sleep(180) + + ###Check if VIF Config and VIF State reflect AP Profile from CloudSDK + ## VIF Config + try: + ssid_config = profile_info_dict[fw_model + '_nat']["ssid_list"] + print("SSIDs in AP Profile:", ssid_config) + + ssid_list = ap_ssh.get_vif_config(ap_ip, ap_username, ap_password) + print("SSIDs in AP VIF Config:", ssid_list) + + if set(ssid_list) == set(ssid_config): + print("SSIDs in Wifi_VIF_Config Match AP Profile Config") + client.update_testrail(case_id=test_cases["nat_vifc"], run_id=rid, status_id=1, + msg='SSIDs in VIF Config matches AP Profile Config') + report_data['tests'][key][test_cases["nat_vifc"]] = "passed" + else: + print("SSIDs in Wifi_VIF_Config do not match desired AP Profile Config") + client.update_testrail(case_id=test_cases["nat_vifc"], run_id=rid, status_id=5, + msg='SSIDs in VIF Config do not match AP Profile Config') + report_data['tests'][key][test_cases["nat_vifc"]] = "failed" + except: + ssid_list = "ERROR" + print("Error accessing VIF Config from AP CLI") + client.update_testrail(case_id=test_cases["nat_vifc"], run_id=rid, status_id=4, + msg='Cannot determine VIF Config - re-test required') + report_data['tests'][key][test_cases["nat_vifc"]] = "error" + # VIF State + try: + ssid_state = ap_ssh.get_vif_state(ap_ip, ap_username, ap_password) + print("SSIDs in AP VIF State:", ssid_state) + + if set(ssid_state) == set(ssid_config): + print("SSIDs properly applied on AP") + client.update_testrail(case_id=test_cases["nat_vifs"], run_id=rid, status_id=1, + msg='SSIDs in VIF Config applied to VIF State') + report_data['tests'][key][test_cases["nat_vifs"]] = "passed" + else: + print("SSIDs not applied on AP") + client.update_testrail(case_id=test_cases["nat_vifs"], run_id=rid, status_id=5, + msg='SSIDs in VIF Config not applied to VIF State') + report_data['tests'][key][test_cases["nat_vifs"]] = "failed" + except: + ssid_list = "ERROR" + print("Error accessing VIF State from AP CLI") + print("Error accessing VIF Config from AP CLI") + client.update_testrail(case_id=test_cases["nat_vifs"], run_id=rid, status_id=4, + msg='Cannot determine VIF State - re-test required') + report_data['tests'][key][test_cases["nat_vifs"]] = "error" + + ### Set LANForge port for tests + port = "eth2" + + # Print iwinfo for logs + iwinfo = iwinfo_status(ap_ip, ap_username, ap_password) + print(iwinfo) + + ###Run Client Single Connectivity Test Cases for NAT SSIDs + # TC - 2.4 GHz WPA2-Enterprise NAT + test_case = test_cases["2g_eap_nat"] + radio = lab_ap_info.lanforge_2dot4g + sta_list = [lanforge_prefix+"5216"] + ssid_name = profile_info_dict[fw_model + '_nat']["twoFourG_WPA2-EAP_SSID"] + security = "wpa2" + eap_type = "TTLS" + try: + test_result = RunTest.Single_Client_EAP(port, sta_list, ssid_name, radio, security, eap_type, identity, + ttls_password, test_case, rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC - 2.4 GHz WPA2 NAT + test_case = test_cases["2g_wpa2_nat"] + radio = lab_ap_info.lanforge_2dot4g + station = [lanforge_prefix+"4325"] + ssid_name = profile_info_dict[fw_model + '_nat']["twoFourG_WPA2_SSID"] + ssid_psk = profile_info_dict[fw_model + '_nat']["twoFourG_WPA2_PSK"] + security = "wpa2" + try: + test_result = Test.Single_Client_Connectivity(port, radio, ssid_name, ssid_psk, security, station, + test_case, + rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC - 2.4 GHz WPA NAT + test_case = test_cases["2g_wpa_nat"] + radio = lab_ap_info.lanforge_2dot4g + station = [lanforge_prefix+"4323"] + ssid_name = profile_info_dict[fw_model + '_nat']["twoFourG_WPA_SSID"] + ssid_psk = profile_info_dict[fw_model + '_nat']["twoFourG_WPA_PSK"] + security = "wpa" + try: + test_result = Test.Single_Client_Connectivity(port, radio, ssid_name, ssid_psk, security, station, + test_case, rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC - 5 GHz WPA2-Enterprise NAT + test_case = test_cases["5g_eap_nat"] + radio = lab_ap_info.lanforge_5g + sta_list = [lanforge_prefix+"5217"] + ssid_name = profile_info_dict[fw_model + '_nat']["fiveG_WPA2-EAP_SSID"] + security = "wpa2" + eap_type = "TTLS" + try: + test_result = RunTest.Single_Client_EAP(port, sta_list, ssid_name, radio, security, eap_type, identity, + ttls_password, test_case, rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC - 5 GHz WPA2 NAT + test_case = test_cases["5g_wpa2_nat"] + radio = lab_ap_info.lanforge_5g + station = [lanforge_prefix+"4326"] + ssid_name = profile_info_dict[fw_model + '_nat']["fiveG_WPA2_SSID"] + ssid_psk = profile_info_dict[fw_model]["fiveG_WPA2_PSK"] + security = "wpa2" + try: + test_result = Test.Single_Client_Connectivity(port, radio, ssid_name, ssid_psk, security, station, + test_case, + rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC - 5 GHz WPA NAT + test_case = test_cases["5g_wpa_nat"] + radio = lab_ap_info.lanforge_5g + station = [lanforge_prefix+"4324"] + ssid_name = profile_info_dict[fw_model + '_nat']["fiveG_WPA_SSID"] + ssid_psk = profile_info_dict[fw_model]["fiveG_WPA_PSK"] + security = "wpa" + try: + test_result = Test.Single_Client_Connectivity(port, radio, ssid_name, ssid_psk, security, station, + test_case, + rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + logger.info("Testing for " + fw_model + "NAT Mode SSIDs Complete") + with open(report_path + today + '/report_data.json', 'w') as report_json_file: + json.dump(report_data, report_json_file) + + ########################################################################### + ################# Customer VLAN Client Connectivity ####################### + ########################################################################### + + ### Create SSID Profiles + ssid_template = "templates/ssid_profile_template.json" + + # 5G SSIDs + try: + fiveG_eap = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_5G_EAP_VLAN' + today, + profile_info_dict[fw_model + '_vlan']["fiveG_WPA2-EAP_SSID"], None, + radius_name, + "wpa2OnlyRadius", "BRIDGE", 100, ["is5GHzU", "is5GHz", "is5GHzL"]) + print("5G EAP SSID created successfully - custom VLAN mode") + client.update_testrail(case_id=test_cases["ssid_5g_eap_vlan"], run_id=rid, status_id=1, + msg='5G EAP SSID created successfully - Custom VLAN mode') + report_data['tests'][key][test_cases["ssid_5g_eap_vlan"]] = "passed" + + except: + fiveG_eap = "error" + print("5G EAP SSID create failed - custom VLAN mode") + client.update_testrail(case_id=test_cases["ssid_5g_eap_vlan"], run_id=rid, status_id=5, + msg='5G EAP SSID create failed - custom VLAN mode') + report_data['tests'][key][test_cases["ssid_5g_eap_vlan"]] = "failed" + fiveG_eap = profile_info_dict[fw_model + '_vlan']["fiveG_WPA2-EAP_profile"] + + try: + fiveG_wpa2 = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_5G_WPA2_VLAN' + today, + profile_info_dict[fw_model + '_vlan']["fiveG_WPA2_SSID"], + profile_info_dict[fw_model + '_vlan']["fiveG_WPA2_PSK"], + "Radius-Accounting-Profile", "wpa2OnlyPSK", "BRIDGE", 100, + ["is5GHzU", "is5GHz", "is5GHzL"]) + print("5G WPA2 SSID created successfully - custom VLAN mode") + client.update_testrail(case_id=test_cases["ssid_5g_wpa2_vlan"], run_id=rid, status_id=1, + msg='5G WPA2 SSID created successfully - custom VLAN mode') + report_data['tests'][key][test_cases["ssid_5g_wpa2_vlan"]] = "passed" + except: + fiveG_wpa2 = "error" + print("5G WPA2 SSID create failed - custom VLAN mode") + client.update_testrail(case_id=test_cases["ssid_5g_wpa2_vlan"], run_id=rid, status_id=5, + msg='5G WPA2 SSID create failed - custom VLAN mode') + report_data['tests'][key][test_cases["ssid_5g_wpa2_vlan"]] = "failed" + fiveG_wpa2 = profile_info_dict[fw_model + '_vlan']["fiveG_WPA2_profile"] + + try: + fiveG_wpa = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_5G_WPA_VLAN_' + today, + profile_info_dict[fw_model + '_vlan']["fiveG_WPA_SSID"], + profile_info_dict[fw_model + '_vlan']["fiveG_WPA_PSK"], + "Radius-Accounting-Profile", "wpaPSK", "BRIDGE", 100, + ["is5GHzU", "is5GHz", "is5GHzL"]) + print("5G WPA SSID created successfully - custom VLAN mode") + client.update_testrail(case_id=test_cases["ssid_5g_wpa_vlan"], run_id=rid, status_id=1, + msg='5G WPA SSID created successfully - custom VLAN mode') + report_data['tests'][key][test_cases["ssid_5g_wpa_vlan"]] = "passed" + except: + fiveG_wpa = "error" + print("5G WPA SSID create failed - custom VLAN mode") + client.update_testrail(case_id=test_cases["ssid_5g_wpa_vlan"], run_id=rid, status_id=5, + msg='5G WPA SSID create failed - custom VLAN mode') + report_data['tests'][key][test_cases["ssid_5g_wpa_vlan"]] = "failed" + fiveG_wpa = profile_info_dict[fw_model + '_vlan']["fiveG_WPA_profile"] + + # 2.4G SSIDs + try: + twoFourG_eap = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_2G_EAP_VLAN_' + today, + profile_info_dict[fw_model + '_vlan']["twoFourG_WPA2-EAP_SSID"], + None, + radius_name, "wpa2OnlyRadius", "BRIDGE", 100, ["is2dot4GHz"]) + print("2.4G EAP SSID created successfully - custom VLAN mode") + client.update_testrail(case_id=test_cases["ssid_2g_eap_vlan"], run_id=rid, status_id=1, + msg='2.4G EAP SSID created successfully - custom VLAN mode') + report_data['tests'][key][test_cases["ssid_2g_eap_vlan"]] = "passed" + except: + twoFourG_eap = "error" + print("2.4G EAP SSID create failed - custom VLAN mode") + client.update_testrail(case_id=test_cases["ssid_2g_eap_vlan"], run_id=rid, status_id=5, + msg='2.4G EAP SSID create failed - custom VLAN mode') + report_data['tests'][key][test_cases["ssid_2g_eap_vlan"]] = "failed" + twoFourG_eap = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA2-EAP_SSID"] + + try: + twoFourG_wpa2 = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_2G_WPA2_VLAN_' + today, + profile_info_dict[fw_model + '_vlan']["twoFourG_WPA2_SSID"], + profile_info_dict[fw_model + '_vlan']["twoFourG_WPA2_PSK"], + "Radius-Accounting-Profile", "wpa2OnlyPSK", "BRIDGE", 100, + ["is2dot4GHz"]) + print("2.4G WPA2 SSID created successfully - custom VLAN mode") + client.update_testrail(case_id=test_cases["ssid_2g_wpa2_vlan"], run_id=rid, status_id=1, + msg='2.4G WPA2 SSID created successfully - custom VLAN mode') + report_data['tests'][key][test_cases["ssid_2g_wpa2_vlan"]] = "passed" + except: + twoFourG_wpa2 = "error" + print("2.4G WPA2 SSID create failed - custom VLAN mode") + client.update_testrail(case_id=test_cases["ssid_2g_wpa2_vlan"], run_id=rid, status_id=5, + msg='2.4G WPA2 SSID create failed - custom VLAN mode') + report_data['tests'][key][test_cases["ssid_2g_wpa2_vlan"]] = "failed" + twoFourG_wpa2 = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA2_SSID"] + + try: + twoFourG_wpa = CloudSDK.create_ssid_profile(cloudSDK_url, bearer, ssid_template, + fw_model + '_2G_WPA_VLAN_' + today, + profile_info_dict[fw_model + '_vlan']["twoFourG_WPA_SSID"], + profile_info_dict[fw_model + '_vlan']["twoFourG_WPA_PSK"], + "Radius-Accounting-Profile", "wpaPSK", "BRIDGE", 100, + ["is2dot4GHz"]) + print("2.4G WPA SSID created successfully - custom VLAN mode") + client.update_testrail(case_id=test_cases["ssid_2g_wpa_vlan"], run_id=rid, status_id=1, + msg='2.4G WPA SSID created successfully - custom VLAN mode') + report_data['tests'][key][test_cases["ssid_2g_wpa_vlan"]] = "passed" + except: + twoFourG_wpa = "error" + print("2.4G WPA SSID create failed - custom VLAN mode") + client.update_testrail(case_id=test_cases["ssid_2g_wpa_vlan"], run_id=rid, status_id=5, + msg='2.4G WPA SSID create failed - custom VLAN mode') + report_data['tests'][key][test_cases["ssid_2g_wpa_vlan"]] = "failed" + twoFourG_wpa = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA_SSID"] + + ### Create AP VLAN Profile + rfProfileId = lab_ap_info.rf_profile + radiusProfileId = radius_profile + child_profiles = [fiveG_eap, fiveG_wpa2, fiveG_wpa, twoFourG_eap, twoFourG_wpa2, twoFourG_wpa, rfProfileId, radiusProfileId] + print(child_profiles) + ap_template = "templates/ap_profile_template.json" + name = "Nightly_Sanity_" + fw_model + "_" + today + "_vlan" + + try: + create_ap_profile = CloudSDK.create_ap_profile(cloudSDK_url, bearer, ap_template, name, child_profiles) + test_profile_id = create_ap_profile + print("Test Profile ID for Test is:", test_profile_id) + client.update_testrail(case_id=test_cases["ap_vlan"], run_id=rid, status_id=1, + msg='AP profile for VLAN tests created successfully') + report_data['tests'][key][test_cases["ap_vlan"]] = "passed" + except: + create_ap_profile = "error" + test_profile_id = profile_info_dict[fw_model + '_vlan']["profile_id"] + print("Error creating AP profile for bridge tests. Will use existing AP profile") + client.update_testrail(case_id=test_cases["ap_vlan"], run_id=rid, status_id=5, + msg='AP profile for VLAN tests could not be created using API') + report_data['tests'][key][test_cases["ap_vlan"]] = "failed" + + ### Set Proper AP Profile for VLAN SSID Tests + ap_profile = CloudSDK.set_ap_profile(equipment_id, test_profile_id, cloudSDK_url, bearer) + + ### Wait for Profile Push + time.sleep(180) + + ###Check if VIF Config and VIF State reflect AP Profile from CloudSDK + ## VIF Config + try: + ssid_config = profile_info_dict[fw_model + '_vlan']["ssid_list"] + print("SSIDs in AP Profile:", ssid_config) + + ssid_list = ap_ssh.get_vif_config(ap_ip, ap_username, ap_password) + print("SSIDs in AP VIF Config:", ssid_list) + + if set(ssid_list) == set(ssid_config): + print("SSIDs in Wifi_VIF_Config Match AP Profile Config") + client.update_testrail(case_id=test_cases["vlan_vifc"], run_id=rid, status_id=1, + msg='SSIDs in VIF Config matches AP Profile Config') + report_data['tests'][key][test_cases["vlan_vifc"]] = "passed" + else: + print("SSIDs in Wifi_VIF_Config do not match desired AP Profile Config") + client.update_testrail(case_id=test_cases["vlan_vifc"], run_id=rid, status_id=5, + msg='SSIDs in VIF Config do not match AP Profile Config') + report_data['tests'][key][test_cases["vlan_vifc"]] = "failed" + except: + ssid_list = "ERROR" + print("Error accessing VIF Config from AP CLI") + client.update_testrail(case_id=test_cases["vlan_vifc"], run_id=rid, status_id=4, + msg='Cannot determine VIF Config - re-test required') + report_data['tests'][key][test_cases["vlan_vifc"]] = "error" + # VIF State + try: + ssid_state = ap_ssh.get_vif_state(ap_ip, ap_username, ap_password) + print("SSIDs in AP VIF State:", ssid_state) + + if set(ssid_state) == set(ssid_config): + print("SSIDs properly applied on AP") + client.update_testrail(case_id=test_cases["vlan_vifs"], run_id=rid, status_id=1, + msg='SSIDs in VIF Config applied to VIF State') + report_data['tests'][key][test_cases["vlan_vifs"]] = "passed" + else: + print("SSIDs not applied on AP") + client.update_testrail(case_id=test_cases["vlan_vifs"], run_id=rid, status_id=5, + msg='SSIDs in VIF Config not applied to VIF State') + report_data['tests'][key][test_cases["vlan_vifs"]] = "failed" + except: + ssid_list = "ERROR" + print("Error accessing VIF State from AP CLI") + print("Error accessing VIF Config from AP CLI") + client.update_testrail(case_id=test_cases["vlan_vifs"], run_id=rid, status_id=4, + msg='Cannot determine VIF State - re-test required') + report_data['tests'][key][test_cases["vlan_vifs"]] = "error" + + ### Set port for LANForge + port = "vlan100" + + # Print iwinfo for logs + iwinfo = iwinfo_status(ap_ip, ap_username, ap_password) + print(iwinfo) + + ###Run Client Single Connectivity Test Cases for VLAN SSIDs + # TC- 2.4 GHz WPA2-Enterprise VLAN + test_case = test_cases["2g_eap_vlan"] + radio = lab_ap_info.lanforge_2dot4g + sta_list = [lanforge_prefix+"5253"] + ssid_name = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA2-EAP_SSID"] + security = "wpa2" + eap_type = "TTLS" + try: + test_result = RunTest.Single_Client_EAP(port, sta_list, ssid_name, radio, security, eap_type, identity, + ttls_password, test_case, rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC - 2.4 GHz WPA2 VLAN + test_case = test_cases["2g_wpa2_vlan"] + radio = lab_ap_info.lanforge_2dot4g + station = [lanforge_prefix+"5251"] + ssid_name = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA2_SSID"] + ssid_psk = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA2_PSK"] + security = "wpa2" + try: + test_result = Test.Single_Client_Connectivity(port, radio, ssid_name, ssid_psk, security, station, + test_case, + rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC 4323 - 2.4 GHz WPA VLAN + test_case = test_cases["2g_wpa_vlan"] + radio = lab_ap_info.lanforge_2dot4g + station = [lanforge_prefix+"5252"] + ssid_name = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA_SSID"] + ssid_psk = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA_PSK"] + security = "wpa" + try: + test_result = Test.Single_Client_Connectivity(port, radio, ssid_name, ssid_psk, security, station, + test_case, rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC - 5 GHz WPA2-Enterprise VLAN + test_case = test_cases["5g_eap_vlan"] + radio = lab_ap_info.lanforge_5g + sta_list = [lanforge_prefix+"5250"] + ssid_name = profile_info_dict[fw_model + '_vlan']["fiveG_WPA2-EAP_SSID"] + security = "wpa2" + eap_type = "TTLS" + try: + test_result = RunTest.Single_Client_EAP(port, sta_list, ssid_name, radio, security, eap_type, identity, + ttls_password, test_case, rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC - 5 GHz WPA2 VLAN + test_case = test_cases["5g_wpa2_vlan"] + radio = lab_ap_info.lanforge_5g + station = [lanforge_prefix+"5248"] + ssid_name = profile_info_dict[fw_model + '_vlan']["fiveG_WPA2_SSID"] + ssid_psk = profile_info_dict[fw_model]["fiveG_WPA2_PSK"] + security = "wpa2" + try: + test_result = Test.Single_Client_Connectivity(port, radio, ssid_name, ssid_psk, security, station, + test_case, + rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + # TC 4324 - 5 GHz WPA VLAN + test_case = test_cases["5g_wpa_vlan"] + radio = lab_ap_info.lanforge_5g + station = [lanforge_prefix+"5249"] + ssid_name = profile_info_dict[fw_model + '_vlan']["fiveG_WPA_SSID"] + ssid_psk = profile_info_dict[fw_model]["fiveG_WPA_PSK"] + security = "wpa" + try: + test_result = Test.Single_Client_Connectivity(port, radio, ssid_name, ssid_psk, security, station, + test_case, + rid) + except: + test_result = "error" + Test.testrail_retest(test_case, rid, ssid_name) + pass + report_data['tests'][key][int(test_case)] = test_result + print(report_data['tests'][key]) + + time.sleep(10) + + logger.info("Testing for " + fw_model + "Custom VLAN SSIDs Complete") + + logger.info("Testing for " + fw_model + "Complete") + + # Add indication of complete TC pass/fail to sanity_status for pass to external json used by Throughput Test + x = all(status == "passed" for status in report_data["tests"][key].values()) + print(x) + + if x == True: + sanity_status['sanity_status'][key] = "passed" + + else: + sanity_status['sanity_status'][key] = "failed" + + ##Update sanity_status.json to indicate there has been a test on at least one AP model tonight + sanity_status['sanity_run']['new_data'] = "yes" + + print(sanity_status) + + # write to json file + with open('sanity_status.json', 'w') as json_file: + json.dump(sanity_status, json_file) + + # write to report_data contents to json file so it has something in case of unexpected fail + print(report_data) + with open(report_path + today + '/report_data.json', 'w') as report_json_file: + json.dump(report_data, report_json_file) + +# Dump all sanity test results to external json file again just to be sure +with open('sanity_status.json', 'w') as json_file: + json.dump(sanity_status, json_file) + +# Calculate percent of tests passed for report +for key in ap_models: + if report_data['fw_available'][key] is "No": + report_data["pass_percent"][key] = "Not Run" + else: + no_of_tests = len(report_data["tests"][key]) + passed_tests = sum(x == "passed" for x in report_data["tests"][key].values()) + print(passed_tests) + percent = float(passed_tests / no_of_tests) * 100 + percent_pass = round(percent, 2) + print(key, "pass rate is", str(percent_pass) + "%") + report_data["pass_percent"][key] = str(percent_pass) + '%' + +# write to report_data contents to json file +print(report_data) +with open(report_path + today + '/report_data.json', 'w') as report_json_file: + json.dump(report_data, report_json_file) + +print(".....End of Sanity Test.....") +logger.info("End of Sanity Test run") diff --git a/unit_tests/README.md b/unit_tests/README.md new file mode 100644 index 000000000..b75a4a412 --- /dev/null +++ b/unit_tests/README.md @@ -0,0 +1,66 @@ +# TIP CICD Sanity Scripts +This directory contains scripts and modules designed for wlan sanity testing. + +## Nightly Sanity +This script is used to look for and test new firmware available for the APs. AP equipment IDs and SSID information used in test is stored in the lab_ap_info file + +1. Check current CloudSDK version +2. Find latest dev firmware on TIP jfrog and create instances on CloudSDK (if necessary) +3. Create report_data.json file with information about versions and test case pass/fail +4. For each AP model: + 1. Check current AP firmware *(If AP already running newest firmware, test will skip)* + 2. Create Testrail test run with required test cases included + 3. Upgrade AP via CloudSDK API + 4. Check if AP upgrade and CloudSDK connection successful + 5. For each SSID mode (bridge, NAT and VLAN), marking TestRail and report_data.json with pass/fail: + 1. Create SSID Profiles for various security modes and radio types + 2. Create AP Profile for SSID mode + 3. Apply AP profile to AP + 5. Check that SSID have been applied properly on AP + 4. Perform client connectivity tests + 6. Update sanity_status.json with **overall** pass/fail + +## Throughput Test +This script is used to test UDP and TCP throughput on different modes of SSIDs, on multiple AP models. It is designed to run on APs that have successfully passed through Nightly_Sanity test. + +For each AP model: +1) Read sanity_status.json to see if throughput should be run, if yes: + 1) Run throughput tests on SSIDs modes + 2) Record results to CSV file +2) Update sanity_status.json that throughput tests have been run + +## Environment Variables +Environment variables required to run scripts and modules in this directory +#### Nightly_Sanity.py +CLOUD_SDK_URL: CloudSDK URL for API calls +SANITY_LOG_DIR: Logger file directory +SANITY_REPORT_DIR: Report file directory +REPORT_TEMPLATE: Report template path +TR_USER: TestRail Username +TR_PWD: TestRail Password +MILESTONE: TestRail Milestone ID +PROJECT_ID: TestRail Project ID +EAP_IDENTITY: EAP identity for testing +EAP_PWD: EAP password for testing +AP_USER: Username for AP +JFROG_USER: Jfrog username +JFROG_PWD: Jfrog password + +#### cloudsdk.py +CLOUDSDK_USER: CloudSDK username +CLOUDSDK_PWD: CloudSDK password + +#### cluster_version.py +AWS_USER: CloudSDK username +AWS_PWD: CloudSDK password + +#### testrail_api.py +TR_USER tr_user TestRail Username +TR_PWD tr_pw TestRail Password + +#### Throughput_Test.py +CLOUD_SDK_URL: CloudSDK URL for API calls +CSV_PATH: Path for CSV file +EAP_IDENTITY: EAP identity for testing +EAP_PWD: EAP password for testing +TPUT_LOG_DIR: Logger file directory diff --git a/unit_tests/Throughput_Test.py b/unit_tests/Throughput_Test.py new file mode 100755 index 000000000..cffcf93f0 --- /dev/null +++ b/unit_tests/Throughput_Test.py @@ -0,0 +1,530 @@ +import csv +import sys +import time +import datetime +from datetime import date +import json +import os +import logging + +import single_client_throughput +import cloudsdk +from cloudsdk import CloudSDK +import lab_ap_info + +cloudSDK_url=os.getenv('CLOUD_SDK_URL') +station = ["tput5000"] +runtime = 10 +csv_path=os.getenv('CSV_PATH') +bridge_upstream_port = "eth2" +nat_upstream_port = "eth2" +vlan_upstream_port = "vlan100" + +#EAP Credentials +identity=os.getenv('EAP_IDENTITY') +ttls_password=os.getenv('EAP_PWD') + +local_dir=os.getenv('TPUT_LOG_DIR') +logger = logging.getLogger('Throughput_Test') +hdlr = logging.FileHandler(local_dir+"/Throughput_Testing.log") +formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') +hdlr.setFormatter(formatter) +logger.addHandler(hdlr) +logger.setLevel(logging.INFO) + + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + +if 'py-json' not in sys.path: + sys.path.append('../../py-json') + +def throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput): + #parse client_tput list returned from single_client_throughput + udp_ds = client_tput[0].partition(": ")[2] + udp_us = client_tput[1].partition(": ")[2] + tcp_ds = client_tput[2].partition(": ")[2] + tcp_us = client_tput[3].partition(": ")[2] + # Find band for CSV ---> This code is not great, it SHOULD get that info from LANForge! + if "5G" in ssid_name: + frequency = "5 GHz" + elif "2dot4G" in ssid_name: + frequency = "2.4 GHz" + else: + frequency = "Unknown" + # Append row to top of CSV file + row = [ap_model, firmware, frequency, mimo, security, mode, udp_ds, udp_us, tcp_ds, tcp_us] + with open(csv_file, 'r') as readFile: + reader = csv.reader(readFile) + lines = list(reader) + lines.insert(1, row) + with open(csv_file, 'w') as writeFile: + writer = csv.writer(writeFile) + writer.writerows(lines) + readFile.close() + writeFile.close() + +#Import dictionaries for AP Info +from lab_ap_info import equipment_id_dict +from lab_ap_info import profile_info_dict +from lab_ap_info import ap_models +from lab_ap_info import mimo_2dot4g +from lab_ap_info import mimo_5g +from lab_ap_info import customer_id +from lab_ap_info import cloud_type +#import json file to determine if throughput should be run for specific AP model +sanity_status = json.load(open("sanity_status.json")) + +#create CSV file for test run +today = str(date.today()) +csv_file = csv_path+"throughput_test_"+today+".csv" +headers = ['AP Type', 'Firmware','Radio', 'MIMO', 'Security', 'Mode', 'UDP Downstream (Mbps)', 'UDP Upstream (Mbps)', 'TCP Downstream (Mbps)', 'TCP Upstream (Mbps)'] +with open(csv_file, "w") as file: + create = csv.writer(file) + create.writerow(headers) + file.close() + +ap_firmware_dict = { + "ea8300": '', + "ecw5211": '', + "ecw5410": '', + "ec420": '' +} + +logger.info('Start of Throughput Test') + +for key in equipment_id_dict: + if sanity_status['sanity_status'][key] == "passed": + logger.info("Running throughput test on " + key) + ##Get Bearer Token to make sure its valid (long tests can require re-auth) + bearer = CloudSDK.get_bearer(cloudSDK_url, cloud_type) + ###Get Current AP Firmware + equipment_id = equipment_id_dict[key] + ap_fw = CloudSDK.ap_firmware(customer_id, equipment_id, cloudSDK_url, bearer) + fw_model = ap_fw.partition("-")[0] + print("AP MODEL UNDER TEST IS", fw_model) + print('Current AP Firmware:', ap_fw) + ##add current FW to dictionary + ap_firmware_dict[fw_model] = ap_fw + + ########################################################################### + ############## Bridge Throughput Testing ################################# + ########################################################################### + print("Testing for Bridge SSIDs") + logger.info("Starting Brdige SSID tput tests on " + key) + ###Set Proper AP Profile for Bridge SSID Tests + test_profile_id = profile_info_dict[fw_model]["profile_id"] + #print(test_profile_id) + ap_profile = CloudSDK.set_ap_profile(equipment_id, test_profile_id, cloudSDK_url, bearer) + ### Wait for Profile Push + print('-----------------PROFILE PUSH -------------------') + time.sleep(180) + + ##Set port for LANForge + port = bridge_upstream_port + + # 5G WPA2 Enterprise UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + sta_list = station + radio = lab_ap_info.lanforge_5g + ssid_name = profile_info_dict[fw_model]["fiveG_WPA2-EAP_SSID"] + security = "wpa2" + eap_type = "TTLS" + mode = "Bridge" + mimo = mimo_5g[fw_model] + client_tput = single_client_throughput.eap_tput(sta_list, ssid_name, radio, security, eap_type, identity, ttls_password, port) + print(fw_model, "5 GHz WPA2-EAP throughput:\n", client_tput) + security = "wpa2-eap" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + #5G WPA2 UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + radio = lab_ap_info.lanforge_5g + ssid_name = profile_info_dict[fw_model]["fiveG_WPA2_SSID"] + ssid_psk = profile_info_dict[fw_model]["fiveG_WPA2_PSK"] + security = "wpa2" + mode = "Bridge" + mimo = mimo_5g[fw_model] + client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + print(fw_model, "5 GHz WPA2 throughput:\n",client_tput) + security = "wpa2-psk" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 5G WPA UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + radio = lab_ap_info.lanforge_5g + ssid_name = profile_info_dict[fw_model]["fiveG_WPA_SSID"] + ssid_psk = profile_info_dict[fw_model]["fiveG_WPA_PSK"] + security = "wpa" + mode = "Bridge" + mimo = mimo_5g[fw_model] + client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + print(fw_model, "5 GHz WPA throughput:\n",client_tput) + security = "wpa-psk" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 5G Open UDP DS/US and TCP DS/US + # ap_model = fw_model + # firmware = ap_fw + # radio = lab_ap_info.lanforge_5g + # ssid_name = profile_info_dict[fw_model]["fiveG_OPEN_SSID"] + # ssid_psk = "BLANK" + # security = "open" + #mode = "Bridge" + #mimo = mimo_5g[fw_model] + # client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + #print(fw_model, "5 GHz Open throughput:\n",client_tput) + #throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 2.4G WPA2 Enterprise UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + sta_list = station + radio = lab_ap_info.lanforge_2dot4g + ssid_name = profile_info_dict[fw_model]["twoFourG_WPA2-EAP_SSID"] + security = "wpa2" + eap_type = "TTLS" + mode = "Bridge" + mimo = mimo_2dot4g[fw_model] + client_tput = single_client_throughput.eap_tput(sta_list, ssid_name, radio, security, eap_type, identity, + ttls_password, port) + print(fw_model, "2.4 GHz WPA2-EAP throughput:\n", client_tput) + security = "wpa2-eap" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 2.4G WPA2 UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + radio = lab_ap_info.lanforge_2dot4g + ssid_name = profile_info_dict[fw_model]["twoFourG_WPA2_SSID"] + ssid_psk = profile_info_dict[fw_model]["twoFourG_WPA2_PSK"] + security = "wpa2" + mode = "Bridge" + mimo = mimo_2dot4g[fw_model] + client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + print(fw_model, "2.4 GHz WPA2 throughput:\n",client_tput) + security = "wpa2-psk" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 2.4G WPA UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + radio = lab_ap_info.lanforge_2dot4g + ssid_name = profile_info_dict[fw_model]["twoFourG_WPA_SSID"] + ssid_psk = profile_info_dict[fw_model]["twoFourG_WPA_PSK"] + security = "wpa" + mode = "Bridge" + mimo = mimo_2dot4g[fw_model] + client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + print(fw_model, "2.4 GHz WPA throughput:\n",client_tput) + security = "wpa-psk" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 2.4G Open UDP DS/US and TCP DS/US + #ap_model = fw_model + #firmware = ap_fw + # radio = lab_ap_info.lanforge_5g + # ssid_name = profile_info_dict[fw_model]["twoFourG_OPEN_SSID"] + # ssid_psk = "BLANK" + # security = "open" + #mode = "Bridge" + #mimo = mimo_2dot4g[fw_model] + #client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + #print(fw_model, "2.4 GHz Open throughput:\n",client_tput) + #throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + ########################################################################### + ################# NAT Mode Throughput Testing ############################ + ########################################################################### + print('Testing for NAT SSIDs') + logger.info("Starting NAT SSID tput tests on " + key) + ###Set Proper AP Profile for NAT SSID Tests + test_profile_id = profile_info_dict[fw_model + '_nat']["profile_id"] + print(test_profile_id) + ap_profile = CloudSDK.set_ap_profile(equipment_id, test_profile_id, cloudSDK_url, bearer) + + ### Wait for Profile Push + print('-----------------PROFILE PUSH -------------------') + time.sleep(180) + + ##Set port for LANForge + port = nat_upstream_port + + # 5G WPA2 Enterprise UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + sta_list = station + radio = lab_ap_info.lanforge_5g + ssid_name = profile_info_dict[fw_model+'_nat']["fiveG_WPA2-EAP_SSID"] + security = "wpa2" + eap_type = "TTLS" + mode = "NAT" + mimo = mimo_5g[fw_model] + client_tput = single_client_throughput.eap_tput(sta_list, ssid_name, radio, security, eap_type, identity, + ttls_password, port) + print(fw_model, "5 GHz WPA2-EAP NAT throughput:\n", client_tput) + security = "wpa2-eap" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 5G WPA2 NAT UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + radio = lab_ap_info.lanforge_5g + ssid_name = profile_info_dict[fw_model+'_nat']["fiveG_WPA2_SSID"] + ssid_psk = profile_info_dict[fw_model+'_nat']["fiveG_WPA2_PSK"] + security = "wpa2" + mode = "NAT" + mimo = mimo_5g[fw_model] + client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + print(fw_model, "5 GHz WPA2 NAT throughput:\n", client_tput) + security = "wpa2-psk" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 5G WPA UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + radio = lab_ap_info.lanforge_5g + ssid_name = profile_info_dict[fw_model+'_nat']["fiveG_WPA_SSID"] + ssid_psk = profile_info_dict[fw_model+'_nat']["fiveG_WPA_PSK"] + security = "wpa" + mode = "NAT" + mimo = mimo_5g[fw_model] + client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + print(fw_model, "5 GHz WPA NAT throughput:\n", client_tput) + security = "wpa-psk" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 5G Open UDP DS/US and TCP DS/US + # ap_model = fw_model + # firmware = ap_fw + # radio = lab_ap_info.lanforge_5g + # ssid_name = profile_info_dict[fw_model+'_nat']["fiveG_OPEN_SSID"] + # ssid_psk = "BLANK" + # security = "open" + # mode = "NAT" + #mimo = mimo_5g[fw_model] + # client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + # print(fw_model, "5 GHz Open NAT throughput:\n",client_tput) + # throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 2.4G WPA2 Enterprise UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + sta_list = station + radio = lab_ap_info.lanforge_2dot4g + ssid_name = profile_info_dict[fw_model+'_nat']["twoFourG_WPA2-EAP_SSID"] + security = "wpa2" + eap_type = "TTLS" + mode = "NAT" + mimo = mimo_2dot4g[fw_model] + client_tput = single_client_throughput.eap_tput(sta_list, ssid_name, radio, security, eap_type, identity, ttls_password, port) + print(fw_model, "2.4 GHz WPA2-EAP NAT throughput:\n", client_tput) + security = "wpa2-eap" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 2.4G WPA2 UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + radio = lab_ap_info.lanforge_2dot4g + ssid_name = profile_info_dict[fw_model+'_nat']["twoFourG_WPA2_SSID"] + ssid_psk = profile_info_dict[fw_model+'_nat']["twoFourG_WPA2_PSK"] + security = "wpa2" + mode = "NAT" + mimo = mimo_2dot4g[fw_model] + client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + print(fw_model, "2.4 GHz WPA2 NAT throughput:\n", client_tput) + security = "wpa2-psk" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 2.4G WPA UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + radio = lab_ap_info.lanforge_2dot4g + ssid_name = profile_info_dict[fw_model+'_nat']["twoFourG_WPA_SSID"] + ssid_psk = profile_info_dict[fw_model+'_nat']["twoFourG_WPA_PSK"] + security = "wpa" + mode = "NAT" + mimo = mimo_2dot4g[fw_model] + client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + print(fw_model, "2.4 GHz WPA NAT throughput:\n", client_tput) + security = "wpa-psk" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 2.4G Open NAT UDP DS/US and TCP DS/US + # ap_model = fw_model + # firmware = ap_fw + # radio = lab_ap_info.lanforge_5g + # ssid_name = profile_info_dict[fw_model+'_nat']["twoFourG_OPEN_SSID"] + # ssid_psk = "BLANK" + # security = "open" + # mode = "NAT" + #mimo = mimo_2dot4g[fw_model] + # client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + # print(fw_model, "2.4 GHz Open NAT throughput:\n",client_tput) + # throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + ########################################################################### + ################# Custom VLAN Mode Throughput Testing ##################### + ########################################################################### + print('Testing for Custom VLAN SSIDs') + logger.info("Starting Custom VLAN SSID tput tests on " + key) + ###Set Proper AP Profile for NAT SSID Tests + test_profile_id = profile_info_dict[fw_model + '_vlan']["profile_id"] + print(test_profile_id) + ap_profile = CloudSDK.set_ap_profile(equipment_id, test_profile_id, cloudSDK_url, bearer) + + ### Wait for Profile Push + print('-----------------PROFILE PUSH -------------------') + time.sleep(180) + + ##Set port for LANForge + port = vlan_upstream_port + + # 5G WPA2 Enterprise UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + sta_list = station + radio = lab_ap_info.lanforge_5g + ssid_name = profile_info_dict[fw_model + '_vlan']["fiveG_WPA2-EAP_SSID"] + security = "wpa2" + eap_type = "TTLS" + mode = "VLAN" + mimo = mimo_5g[fw_model] + client_tput = single_client_throughput.eap_tput(sta_list, ssid_name, radio, security, eap_type, identity, ttls_password, port) + print(fw_model, "5 GHz WPA2-EAP VLAN throughput:\n", client_tput) + security = "wpa2-eap" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 5G WPA2 VLAN UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + radio = lab_ap_info.lanforge_5g + ssid_name = profile_info_dict[fw_model + '_vlan']["fiveG_WPA2_SSID"] + ssid_psk = profile_info_dict[fw_model + '_vlan']["fiveG_WPA2_PSK"] + security = "wpa2" + mode = "VLAN" + mimo = mimo_5g[fw_model] + client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + print(fw_model, "5 GHz WPA2 VLAN throughput:\n", client_tput) + security = "wpa2-psk" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 5G WPA UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + radio = lab_ap_info.lanforge_5g + ssid_name = profile_info_dict[fw_model + '_vlan']["fiveG_WPA_SSID"] + ssid_psk = profile_info_dict[fw_model + '_vlan']["fiveG_WPA_PSK"] + security = "wpa" + mode = "VLAN" + mimo = mimo_5g[fw_model] + client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + print(fw_model, "5 GHz WPA VLAN throughput:\n", client_tput) + security = "wpa-psk" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 5G Open UDP DS/US and TCP DS/US + # ap_model = fw_model + # firmware = ap_fw + # radio = lab_ap_info.lanforge_5g + # ssid_name = profile_info_dict[fw_model+'_vlan']["fiveG_OPEN_SSID"] + # ssid_psk = "BLANK" + # security = "open" + # mode = "VLAN" + # mimo = mimo_5g[fw_model] + # client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + # print(fw_model, "5 GHz Open VLAN throughput:\n",client_tput) + # throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 2.4G WPA2 Enterprise UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + sta_list = station + radio = lab_ap_info.lanforge_2dot4g + ssid_name = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA2-EAP_SSID"] + security = "wpa2" + eap_type = "TTLS" + mode = "VLAN" + mimo = mimo_2dot4g[fw_model] + client_tput = single_client_throughput.eap_tput(sta_list, ssid_name, radio, security, eap_type, identity, ttls_password, port) + print(fw_model, "2.4 GHz WPA2-EAP VLAN throughput:\n", client_tput) + security = "wpa2-eap" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 2.4G WPA2 UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + radio = lab_ap_info.lanforge_2dot4g + ssid_name = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA2_SSID"] + ssid_psk = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA2_PSK"] + security = "wpa2" + mode = "VLAN" + mimo = mimo_2dot4g[fw_model] + client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + print(fw_model, "2.4 GHz WPA2 VLAN throughput:\n", client_tput) + security = "wpa2-psk" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 2.4G WPA UDP DS/US and TCP DS/US + ap_model = fw_model + firmware = ap_fw + radio = lab_ap_info.lanforge_2dot4g + ssid_name = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA_SSID"] + ssid_psk = profile_info_dict[fw_model + '_vlan']["twoFourG_WPA_PSK"] + security = "wpa" + mode = "VLAN" + mimo = mimo_2dot4g[fw_model] + client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + print(fw_model, "2.4 GHz WPA VLAN throughput:\n", client_tput) + security = "wpa-psk" + throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + # 2.4G Open VLAN UDP DS/US and TCP DS/US + # ap_model = fw_model + # firmware = ap_fw + # radio = lab_ap_info.lanforge_5g + # ssid_name = profile_info_dict[fw_model+'_vlan']["twoFourG_OPEN_SSID"] + # ssid_psk = "BLANK" + # security = "open" + # mode = "VLAN" + # mimo = mimo_2dot4g[fw_model] + # client_tput = single_client_throughput.main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, port) + # print(fw_model, "2.4 GHz Open VLAN throughput:\n",client_tput) + # throughput_csv(csv_file, ssid_name, ap_model, mimo, firmware, security, mode, client_tput) + + + #Indicates throughput has been run for AP model + sanity_status['sanity_status'][key] = "tput run" + logger.info("Trhoughput tests complete on " + key) + + elif sanity_status['sanity_status'][key] == "tput run": + print("Throughput test already run on", key) + logger.info("Throughput test already run on "+ key +" for latest AP FW") + + else: + print(key,"did not pass Nightly Sanity. Skipping throughput test on this AP Model") + logger.info(key+" did not pass Nightly Sanity. Skipping throughput test.") + +#Indicate which AP model has had tput test to external json file +with open('sanity_status.json', 'w') as json_file: + json.dump(sanity_status, json_file) + +with open(csv_file, 'r') as readFile: + reader = csv.reader(readFile) + lines = list(reader) + row_count = len(lines) + #print(row_count) + +if row_count <= 1: + os.remove(csv_file) + file.close() + +else: + print("Saving File") + file.close() + +print(" -- Throughput Testing Complete -- ") diff --git a/unit_tests/ap_ssh.py b/unit_tests/ap_ssh.py new file mode 100755 index 000000000..60f0ed455 --- /dev/null +++ b/unit_tests/ap_ssh.py @@ -0,0 +1,117 @@ +################################################################################## +# Module contains functions to get specific data from AP CLI using SSH +# +# Used by Nightly_Sanity and Throughput_Test ##################################### +################################################################################## + +import paramiko +from paramiko import SSHClient +import socket + +def ssh_cli_active_fw(ap_ip, username, password): + try: + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + client.connect(ap_ip, username=username, password=password, timeout=5) + stdin, stdout, stderr = client.exec_command('/usr/opensync/bin/ovsh s AWLAN_Node -c | grep FW_IMAGE_ACTIVE') + + version_matrix = str(stdout.read()) + version_matrix_split = version_matrix.partition('FW_IMAGE_ACTIVE","')[2] + cli_active_fw = version_matrix_split.partition('"],[')[0] + #print("Active FW is",cli_active_fw) + + stdin, stdout, stderr = client.exec_command('/usr/opensync/bin/ovsh s Manager -c | grep status') + status = str(stdout.read()) + + if "ACTIVE" in status: + #print("AP is in Active state") + state = "active" + elif "BACKOFF" in status: + #print("AP is in Backoff state") + state = "backoff" + else: + #print("AP is not in Active state") + state = "unknown" + + cli_info = { + "state": state, + "active_fw": cli_active_fw + } + + return(cli_info) + + except paramiko.ssh_exception.AuthenticationException: + print("Authentication Error, Check Credentials") + return "ERROR" + except paramiko.SSHException: + print("Cannot SSH to the AP") + return "ERROR" + except socket.timeout: + print("AP Unreachable") + return "ERROR" + +def iwinfo_status(ap_ip, username, password): + try: + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + client.connect(ap_ip, username=username, password=password, timeout=5) + stdin, stdout, stderr = client.exec_command('iwinfo | grep ESSID') + + for line in stdout.read().splitlines(): + print(line) + + except paramiko.ssh_exception.AuthenticationException: + print("Authentication Error, Check Credentials") + return "ERROR" + except paramiko.SSHException: + print("Cannot SSH to the AP") + return "ERROR" + except socket.timeout: + print("AP Unreachable") + return "ERROR" + +def get_vif_config(ap_ip, username, password): + try: + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + client.connect(ap_ip, username=username, password=password, timeout=5) + stdin, stdout, stderr = client.exec_command( + "/usr/opensync/bin/ovsh s Wifi_VIF_Config -c | grep 'ssid :'") + + output = str(stdout.read(), 'utf-8') + ssid_output = output.splitlines() + ssid_list = [s.strip('ssid : ') for s in ssid_output] + return ssid_list + + except paramiko.ssh_exception.AuthenticationException: + print("Authentication Error, Check Credentials") + return "ERROR" + except paramiko.SSHException: + print("Cannot SSH to the AP") + return "ERROR" + except socket.timeout: + print("AP Unreachable") + return "ERROR" + +def get_vif_state(ap_ip, username, password): + try: + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + client.connect(ap_ip, username=username, password=password, timeout=5) + stdin, stdout, stderr = client.exec_command( + "/usr/opensync/bin/ovsh s Wifi_VIF_State -c | grep 'ssid :'") + + output = str(stdout.read(), 'utf-8') + ssid_output = output.splitlines() + ssid_list = [s.strip('ssid : ') for s in ssid_output] + return ssid_list + + except paramiko.ssh_exception.AuthenticationException: + print("Authentication Error, Check Credentials") + return "ERROR" + except paramiko.SSHException: + print("Cannot SSH to the AP") + return "ERROR" + except socket.timeout: + print("AP Unreachable") + return "ERROR" \ No newline at end of file diff --git a/unit_tests/cloudsdk.py b/unit_tests/cloudsdk.py new file mode 100755 index 000000000..15c68deec --- /dev/null +++ b/unit_tests/cloudsdk.py @@ -0,0 +1,267 @@ +#!/usr/bin/python3 + +################################################################################## +# Module contains functions to interact with CloudSDK using APIs +# Start by calling get_bearer to obtain bearer token, then other APIs can be used +# +# Used by Nightly_Sanity and Throughput_Test ##################################### +################################################################################## + +import base64 +import urllib.request +from bs4 import BeautifulSoup +import ssl +import subprocess, os +from artifactory import ArtifactoryPath +import tarfile +import paramiko +from paramiko import SSHClient +from scp import SCPClient +import os +import pexpect +from pexpect import pxssh +import sys +import paramiko +from scp import SCPClient +import pprint +from pprint import pprint +from os import listdir +import re +import requests +import json +import testrail_api +import logging +import datetime +import time + +user=os.getenv('CLOUDSDK_USER') +password=os.getenv('CLOUDSDK_PWD') + +###Class for CloudSDK Interaction via RestAPI +class CloudSDK: + def __init__(self): + self.user = user + + def get_bearer(cloudSDK_url, cloud_type): + cloud_login_url = cloudSDK_url+"/management/"+cloud_type+"/oauth2/token" + payload = ''' + { + "userId": "'''+user+'''", + "password": "'''+password+'''" + } + ''' + headers = { + 'Content-Type': 'application/json' + } + try: + token_response = requests.request("POST", cloud_login_url, headers=headers, data=payload) + except requests.exceptions.RequestException as e: + raise SystemExit("Exiting Script! Cloud not get bearer token for reason:",e) + token_data = token_response.json() + bearer_token = token_data['access_token'] + return(bearer_token) + + def ap_firmware(customer_id,equipment_id, cloudSDK_url, bearer): + equip_fw_url = cloudSDK_url+"/portal/status/forEquipment?customerId="+customer_id+"&equipmentId="+equipment_id + payload = {} + headers = { + 'Authorization': 'Bearer ' + bearer + } + status_response = requests.request("GET", equip_fw_url, headers=headers, data=payload) + status_code = status_response.status_code + if status_code is 200: + status_data = status_response.json() + #print(status_data) + current_ap_fw = status_data[2]['details']['reportedSwVersion'] + return current_ap_fw + else: + return("ERROR") + + def CloudSDK_images(apModel, cloudSDK_url, bearer): + getFW_url = cloudSDK_url+"/portal/firmware/version/byEquipmentType?equipmentType=AP&modelId=" + apModel + payload = {} + headers = { + 'Authorization': 'Bearer ' + bearer + } + response = requests.request("GET", getFW_url, headers=headers, data=payload) + ap_fw_details = response.json() + ###return ap_fw_details + fwlist = [] + for version in ap_fw_details: + fwlist.append(version.get('versionName')) + return(fwlist) + #fw_versionNames = ap_fw_details[0]['versionName'] + #return fw_versionNames + + def firwmare_upload(commit, apModel,latest_image,fw_url,cloudSDK_url,bearer): + fw_upload_url = cloudSDK_url+"/portal/firmware/version" + payload = "{\n \"model_type\": \"FirmwareVersion\",\n \"id\": 0,\n \"equipmentType\": \"AP\",\n \"modelId\": \""+apModel+"\",\n \"versionName\": \""+latest_image+"\",\n \"description\": \"\",\n \"filename\": \""+fw_url+"\",\n \"commit\": \""+commit+"\",\n \"validationMethod\": \"MD5_CHECKSUM\",\n \"validationCode\": \"19494befa87eb6bb90a64fd515634263\",\n \"releaseDate\": 1596192028877,\n \"createdTimestamp\": 0,\n \"lastModifiedTimestamp\": 0\n}\n\n" + headers = { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + bearer + } + + response = requests.request("POST", fw_upload_url, headers=headers, data=payload) + #print(response) + upload_result = response.json() + return(upload_result) + + def get_firmware_id(latest_ap_image, cloudSDK_url, bearer): + #print(latest_ap_image) + fw_id_url = cloudSDK_url+"/portal/firmware/version/byName?firmwareVersionName="+latest_ap_image + + payload = {} + headers = { + 'Authorization': 'Bearer ' + bearer + } + response = requests.request("GET", fw_id_url, headers=headers, data=payload) + fw_data = response.json() + latest_fw_id = fw_data['id'] + return latest_fw_id + + def delete_firmware(fw_id, cloudSDK_url, bearer): + url = cloudSDK_url + '/portal/firmware/version?firmwareVersionId=' + fw_id + payload = {} + headers = { + 'Authorization': 'Bearer ' + bearer + } + response = requests.request("DELETE", url, headers=headers, data=payload) + return(response) + + def update_firmware(equipment_id, latest_firmware_id, cloudSDK_url, bearer): + url = cloudSDK_url+"/portal/equipmentGateway/requestFirmwareUpdate?equipmentId="+equipment_id+"&firmwareVersionId="+latest_firmware_id + + payload = {} + headers = { + 'Authorization': 'Bearer ' + bearer + } + + response = requests.request("POST", url, headers=headers, data=payload) + #print(response.text) + return response.json() + + def set_ap_profile(equipment_id, test_profile_id, cloudSDK_url, bearer): + ###Get AP Info + url = cloudSDK_url+"/portal/equipment?equipmentId="+equipment_id + payload = {} + headers = { + 'Authorization': 'Bearer ' + bearer + } + + response = requests.request("GET", url, headers=headers, data=payload) + print(response) + + ###Add Lab Profile ID to Equipment + equipment_info = response.json() + #print(equipment_info) + equipment_info["profileId"] = test_profile_id + #print(equipment_info) + + ###Update AP Info with Required Profile ID + url = cloudSDK_url+"/portal/equipment" + headers = { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + bearer + } + + response = requests.request("PUT", url, headers=headers, data=json.dumps(equipment_info)) + #print(response) + + def get_cloudsdk_version(cloudSDK_url, bearer): + #print(latest_ap_image) + url = cloudSDK_url+"/ping" + + payload = {} + headers = { + 'Authorization': 'Bearer ' + bearer + } + response = requests.request("GET", url, headers=headers, data=payload) + cloud_sdk_version = response.json() + return cloud_sdk_version + + def create_ap_profile(cloudSDK_url, bearer, template, name, child_profiles): + with open(template, 'r+') as ap_profile: + profile = json.load(ap_profile) + profile["name"] = name + profile["childProfileIds"] = child_profiles + + with open(template, 'w') as ap_profile: + json.dump(profile, ap_profile) + + url = cloudSDK_url+"/portal/profile" + headers = { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + bearer + } + response = requests.request("POST", url, headers=headers, data=open(template, 'rb')) + ap_profile = response.json() + print(ap_profile) + ap_profile_id = ap_profile['id'] + return ap_profile_id + + def create_ssid_profile(cloudSDK_url, bearer, template, name, ssid, passkey, radius, security, mode, vlan, radios): + with open(template, 'r+') as ssid_profile: + profile = json.load(ssid_profile) + profile['name'] = name + profile['details']['ssid'] = ssid + profile['details']['keyStr'] = passkey + profile['details']['radiusServiceName'] = radius + profile['details']['secureMode'] = security + profile['details']['forwardMode'] = mode + profile['details']['vlanId'] = vlan + profile['details']['appliedRadios'] = radios + with open(template, 'w') as ssid_profile: + json.dump(profile, ssid_profile) + + url = cloudSDK_url + "/portal/profile" + headers = { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + bearer + } + response = requests.request("POST", url, headers=headers, data=open(template, 'rb')) + ssid_profile = response.json() + #print(ssid_profile) + ssid_profile_id = ssid_profile['id'] + return ssid_profile_id + + def create_radius_profile(cloudSDK_url, bearer, template, name, subnet_name, subnet, subnet_mask, region, server_name, server_ip, secret, auth_port): + with open(template, 'r+') as radius_profile: + profile = json.load(radius_profile) + + profile['name'] = name + + subnet_config = profile['details']['subnetConfiguration'] + old_subnet_name = list(subnet_config.keys())[0] + subnet_config[subnet_name] = subnet_config.pop(old_subnet_name) + profile['details']['subnetConfiguration'][subnet_name]['subnetAddress'] = subnet + profile['details']['subnetConfiguration'][subnet_name]['subnetCidrPrefix'] = subnet_mask + profile['details']['subnetConfiguration'][subnet_name]['subnetName'] = subnet_name + + region_map = profile['details']['serviceRegionMap'] + old_region = list(region_map.keys())[0] + region_map[region] = region_map.pop(old_region) + profile['details']['serviceRegionName'] = region + profile['details']['subnetConfiguration'][subnet_name]['serviceRegionName'] = region + profile['details']['serviceRegionMap'][region]['regionName'] = region + + server_map = profile['details']['serviceRegionMap'][region]['serverMap'] + old_server_name = list(server_map.keys())[0] + server_map[server_name] = server_map.pop(old_server_name) + profile['details']['serviceRegionMap'][region]['serverMap'][server_name][0]['ipAddress'] = server_ip + profile['details']['serviceRegionMap'][region]['serverMap'][server_name][0]['secret'] = secret + profile['details']['serviceRegionMap'][region]['serverMap'][server_name][0]['authPort'] = auth_port + + with open(template, 'w') as radius_profile: + json.dump(profile, radius_profile) + + url = cloudSDK_url + "/portal/profile" + headers = { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + bearer + } + response = requests.request("POST", url, headers=headers, data=open(template, 'rb')) + radius_profile = response.json() + #print(radius_profile) + #print(ssid_profile) + radius_profile_id = radius_profile['id'] + return radius_profile_id \ No newline at end of file diff --git a/unit_tests/eap_connect.py b/unit_tests/eap_connect.py new file mode 100755 index 000000000..a9e0ca206 --- /dev/null +++ b/unit_tests/eap_connect.py @@ -0,0 +1,373 @@ +#!/usr/bin/env python3 + +######################################################################################################### +# Built to allow connection and test of clients using EAP-TTLS. +# Functions can be called to create a station, create TCP and UDP traffic, run it a short amount of time. +# +# Used by Nightly_Sanity and Throughput_Test ############################################################ +######################################################################################################### + +# This will create a station, create TCP and UDP traffic, run it a short amount of time, +# and verify whether traffic was sent and received. It also verifies the station connected +# to the requested BSSID if bssid is specified as an argument. +# The script will clean up the station and connections at the end of the test. + +import sys + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + +if 'py-json' not in sys.path: + sys.path.append('../../py-json') + +import argparse +import LANforge +from LANforge import LFUtils +# from LANforge import LFCliBase +from LANforge import lfcli_base +from LANforge.lfcli_base import LFCliBase +from LANforge.LFUtils import * +import realm +from realm import Realm +import pprint + +OPEN="open" +WEP="wep" +WPA="wpa" +WPA2="wpa2" +MODE_AUTO=0 + +class EAPConnect(LFCliBase): + def __init__(self, host, port, security=None, ssid=None, sta_list=None, number_template="00000", _debug_on=False, _dut_bssid="", + _exit_on_error=False, _sta_name=None, _resource=1, radio="wiphy0", key_mgmt="WPA-EAP", eap="", identity="", + ttls_passwd="", hessid=None, ttls_realm="", domain="", _sta_prefix='eap', _exit_on_fail=False, _cleanup_on_exit=True): + super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) + self.host = host + self.port = port + self.ssid = ssid + self.radio = radio + self.security = security + #self.password = password + self.sta_list = sta_list + self.key_mgmt = key_mgmt + self.eap = eap + self.sta_prefix = _sta_prefix + self.identity = identity + self.ttls_passwd = ttls_passwd + self.ttls_realm = ttls_realm + self.domain = domain + self.hessid = hessid + self.dut_bssid = _dut_bssid + self.timeout = 120 + self.number_template = number_template + self.debug = _debug_on + self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) + self.station_profile = self.local_realm.new_station_profile() + self.station_profile.lfclient_url = self.lfclient_url + self.station_profile.ssid = self.ssid + self.station_profile.security = self.security + self.station_profile.number_template_ = self.number_template + self.station_profile.mode = 0 + #Added to test_ipv4_ttls code + self.upstream_url = None # defer construction + self.sta_url_map = None + self.upstream_resource = None + self.upstream_port = "eth2" + self.station_names = [] + if _sta_name is not None: + self.station_names = [_sta_name] + self.localrealm = Realm(lfclient_host=host, lfclient_port=port) + self.resource = _resource + self.cleanup_on_exit = _cleanup_on_exit + self.resulting_stations = {} + self.resulting_endpoints = {} + self.station_profile = None + self.l3_udp_profile = None + self.l3_tcp_profile = None + + # def get_realm(self) -> Realm: # py > 3.6 + def get_realm(self): + return self.localrealm + + def get_station_url(self, sta_name_=None): + if sta_name_ is None: + raise ValueError("get_station_url wants a station name") + if self.sta_url_map is None: + self.sta_url_map = {} + for sta_name in self.station_names: + self.sta_url_map[sta_name] = "port/1/%s/%s" % (self.resource, sta_name) + return self.sta_url_map[sta_name_] + + def get_upstream_url(self): + if self.upstream_url is None: + self.upstream_url = "port/1/%s/%s" % (self.upstream_resource, self.upstream_port) + return self.upstream_url + + # Compare pre-test values to post-test values + def compare_vals(self, name, postVal, print_pass=False, print_fail=True): + # print(f"Comparing {name}") + if postVal > 0: + self._pass("%s %s" % (name, postVal), print_pass) + else: + self._fail("%s did not report traffic: %s" % (name, postVal), print_fail) + + def remove_stations(self): + for name in self.station_names: + LFUtils.removePort(self.resource, name, self.lfclient_url) + + def num_associated(self, bssid): + counter = 0 + # print("there are %d results" % len(self.station_results)) + fields = "_links,port,alias,ip,ap,port+type" + self.station_results = self.localrealm.find_ports_like("%s*"%self.sta_prefix, fields, debug_=False) + if (self.station_results is None) or (len(self.station_results) < 1): + self.get_failed_result_list() + for eid,record in self.station_results.items(): + #print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ") + #pprint(eid) + #pprint(record) + if record["ap"] == bssid: + counter += 1 + #print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ") + return counter + + def clear_test_results(self): + self.resulting_stations = {} + self.resulting_endpoints = {} + super().clear_test_results() + #super(StaConnect, self).clear_test_results().test_results.clear() + + def setup(self): + self.clear_test_results() + self.check_connect() + upstream_json = self.json_get("%s?fields=alias,phantom,down,port,ip" % self.get_upstream_url(), debug_=False) + + if upstream_json is None: + self._fail(message="Unable to query %s, bye" % self.upstream_port, print_=True) + return False + + if upstream_json['interface']['ip'] == "0.0.0.0": + if self.debug: + pprint.pprint(upstream_json) + self._fail("Warning: %s lacks ip address" % self.get_upstream_url(), print_=True) + return False + + # remove old stations + print("Removing old stations") + for sta_name in self.station_names: + sta_url = self.get_station_url(sta_name) + response = self.json_get(sta_url) + if (response is not None) and (response["interface"] is not None): + for sta_name in self.station_names: + LFUtils.removePort(self.resource, sta_name, self.lfclient_url) + LFUtils.wait_until_ports_disappear(self.lfclient_url, self.station_names) + + # Create stations and turn dhcp on + self.station_profile = self.localrealm.new_station_profile() + + # Build stations + self.station_profile.use_security(self.security, self.ssid, passwd="[BLANK]") + self.station_profile.set_number_template(self.number_template) + print("Creating stations") + self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) + self.station_profile.set_command_param("set_port", "report_timer", 1500) + self.station_profile.set_command_flag("set_port", "rpt_timer", 1) + self.station_profile.set_wifi_extra(key_mgmt=self.key_mgmt, eap=self.eap, identity=self.identity, + passwd=self.ttls_passwd, + realm=self.ttls_realm, domain=self.domain, + hessid=self.hessid) + self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug, use_radius=True, hs20_enable=False) + self._pass("PASS: Station build finished") + + # Create UDP endpoints + self.l3_udp_profile = self.localrealm.new_l3_cx_profile() + self.l3_udp_profile.side_a_min_bps = 128000 + self.l3_udp_profile.side_b_min_bps = 128000 + self.l3_udp_profile.side_a_min_pdu = 1200 + self.l3_udp_profile.side_b_min_pdu = 1500 + self.l3_udp_profile.report_timer = 1000 + self.l3_udp_profile.name_prefix = "udp" + self.l3_udp_profile.create(endp_type="lf_udp", + side_a=list(self.localrealm.find_ports_like("%s*"%self.sta_prefix)), + side_b="%d.%s" % (self.resource, self.upstream_port), + suppress_related_commands=True) + + # Create TCP endpoints + self.l3_tcp_profile = self.localrealm.new_l3_cx_profile() + self.l3_tcp_profile.side_a_min_bps = 128000 + self.l3_tcp_profile.side_b_min_bps = 56000 + self.l3_tcp_profile.name_prefix = "tcp" + self.l3_tcp_profile.report_timer = 1000 + self.l3_tcp_profile.create(endp_type="lf_tcp", + side_a=list(self.localrealm.find_ports_like("%s*"%self.sta_prefix)), + side_b="%d.%s" % (self.resource, self.upstream_port), + suppress_related_commands=True) + + def start(self): + if self.station_profile is None: + self._fail("Incorrect setup") + pprint.pprint(self.station_profile) + if self.station_profile.up is None: + self._fail("Incorrect station profile, missing profile.up") + if self.station_profile.up == False: + print("\nBringing ports up...") + data = {"shelf": 1, + "resource": self.resource, + "port": "ALL", + "probe_flags": 1} + self.json_post("/cli-json/nc_show_ports", data) + self.station_profile.admin_up() + LFUtils.waitUntilPortsAdminUp(self.resource, self.lfclient_url, self.station_names) + + # station_info = self.jsonGet(self.mgr_url, "%s?fields=port,ip,ap" % (self.getStaUrl())) + duration = 0 + maxTime = 60 + ip = "0.0.0.0" + ap = "" + print("Waiting for %s stations to associate to AP: " % len(self.station_names), end="") + connected_stations = {} + while (len(connected_stations.keys()) < len(self.station_names)) and (duration < maxTime): + duration += 3 + time.sleep(3) + print(".", end="") + for sta_name in self.station_names: + sta_url = self.get_station_url(sta_name) + station_info = self.json_get(sta_url + "?fields=port,ip,ap") + + # LFUtils.debug_printer.pprint(station_info) + if (station_info is not None) and ("interface" in station_info): + if "ip" in station_info["interface"]: + ip = station_info["interface"]["ip"] + if "ap" in station_info["interface"]: + ap = station_info["interface"]["ap"] + + if (ap == "Not-Associated") or (ap == ""): + if self.debug: + print(" -%s," % sta_name, end="") + else: + if ip == "0.0.0.0": + if self.debug: + print(" %s (0.0.0.0)" % sta_name, end="") + else: + connected_stations[sta_name] = sta_url + data = { + "shelf":1, + "resource": self.resource, + "port": "ALL", + "probe_flags": 1 + } + self.json_post("/cli-json/nc_show_ports", data) + + for sta_name in self.station_names: + sta_url = self.get_station_url(sta_name) + station_info = self.json_get(sta_url) # + "?fields=port,ip,ap") + if station_info is None: + print("unable to query %s" % sta_url) + self.resulting_stations[sta_url] = station_info + ap = station_info["interface"]["ap"] + ip = station_info["interface"]["ip"] + if (ap != "") and (ap != "Not-Associated"): + print(" %s +AP %s, " % (sta_name, ap), end="") + if self.dut_bssid != "": + if self.dut_bssid.lower() == ap.lower(): + self._pass(sta_name+" connected to BSSID: " + ap) + # self.test_results.append("PASSED: ) + # print("PASSED: Connected to BSSID: "+ap) + else: + self._fail("%s connected to wrong BSSID, requested: %s Actual: %s" % (sta_name, self.dut_bssid, ap)) + else: + self._fail(sta_name+" did not connect to AP") + return False + + if ip == "0.0.0.0": + self._fail("%s did not get an ip. Ending test" % sta_name) + else: + self._pass("%s connected to AP: %s With IP: %s" % (sta_name, ap, ip)) + + if self.passes() == False: + if self.cleanup_on_exit: + print("Cleaning up...") + self.remove_stations() + return False + + # start cx traffic + print("\nStarting CX Traffic") + self.l3_udp_profile.start_cx() + self.l3_tcp_profile.start_cx() + time.sleep(1) + # Refresh stats + self.l3_udp_profile.refresh_cx() + self.l3_tcp_profile.refresh_cx() + + def collect_endp_stats(self, endp_map): + print("Collecting Data") + fields="?fields=name,tx+bytes,rx+bytes" + for (cx_name, endps) in endp_map.items(): + try: + endp_url = "/endp/%s%s" % (endps[0], fields) + endp_json = self.json_get(endp_url) + self.resulting_endpoints[endp_url] = endp_json + ptest_a_tx = endp_json['endpoint']['tx bytes'] + ptest_a_rx = endp_json['endpoint']['rx bytes'] + + #ptest = self.json_get("/endp/%s?fields=tx+bytes,rx+bytes" % cx_names[cx_name]["b"]) + endp_url = "/endp/%s%s" % (endps[1], fields) + endp_json = self.json_get(endp_url) + self.resulting_endpoints[endp_url] = endp_json + + ptest_b_tx = endp_json['endpoint']['tx bytes'] + ptest_b_rx = endp_json['endpoint']['rx bytes'] + + self.compare_vals("testTCP-A TX", ptest_a_tx) + self.compare_vals("testTCP-A RX", ptest_a_rx) + + self.compare_vals("testTCP-B TX", ptest_b_tx) + self.compare_vals("testTCP-B RX", ptest_b_rx) + + except Exception as e: + print("Is this the function having the error?") + self.error(e) + + + def stop(self): + # stop cx traffic + print("Stopping CX Traffic") + self.l3_udp_profile.stop_cx() + self.l3_tcp_profile.stop_cx() + + # Refresh stats + print("\nRefresh CX stats") + self.l3_udp_profile.refresh_cx() + self.l3_tcp_profile.refresh_cx() + + print("Sleeping for 5 seconds") + time.sleep(5) + + # get data for endpoints JSON + self.collect_endp_stats(self.l3_udp_profile.created_cx) + self.collect_endp_stats(self.l3_tcp_profile.created_cx) + # print("\n") + + def cleanup(self): + # remove all endpoints and cxs + if self.cleanup_on_exit: + for sta_name in self.station_names: + LFUtils.removePort(self.resource, sta_name, self.lfclient_url) + curr_endp_names = [] + removeCX(self.lfclient_url, self.l3_udp_profile.get_cx_names()) + removeCX(self.lfclient_url, self.l3_tcp_profile.get_cx_names()) + for (cx_name, endp_names) in self.l3_udp_profile.created_cx.items(): + curr_endp_names.append(endp_names[0]) + curr_endp_names.append(endp_names[1]) + for (cx_name, endp_names) in self.l3_tcp_profile.created_cx.items(): + curr_endp_names.append(endp_names[0]) + curr_endp_names.append(endp_names[1]) + removeEndps(self.lfclient_url, curr_endp_names, debug= self.debug) + +# ~class + + + +if __name__ == "__main__": + main() diff --git a/unit_tests/lab_ap_info.py b/unit_tests/lab_ap_info.py new file mode 100755 index 000000000..bf58106db --- /dev/null +++ b/unit_tests/lab_ap_info.py @@ -0,0 +1,635 @@ +#!/usr/bin/python3 + +##AP Models Under Test +ap_models = ["ec420","ea8300","ecw5211","ecw5410"] + +##Cloud Type(cloudSDK = v1, CMAP = cmap) +cloud_type = "v1" + +##LANForge Info +lanforge_ip = "10.10.10.201" +lanforge_2dot4g = "wiphy0" +lanforge_5g = "wiphy3" +lanforge_prefix = "sdk" + +##RADIUS Info +radius_info = { + + "name": "Lab-RADIUS", + "subnet_name": "Lab", + "subnet": "10.10.0.0", + "subnet_mask": 16, + "region": "Toronto", + "server_name": "Lab-RADIUS", + "server_ip": "10.10.10.203", + "secret": "testing123", + "auth_port": 1812 +} +##AP Models for firmware upload +cloud_sdk_models = { + "ec420": "EC420-G1", + "ea8300": "EA8300-CA", + "ecw5211": "ECW5211", + "ecw5410": "ECW5410" +} + +mimo_5g = { + "ec420": "4x4", + "ea8300": "2x2", + "ecw5211": "2x2", + "ecw5410": "4x4" +} + +mimo_2dot4g = { + "ec420": "2x2", + "ea8300": "2x2", + "ecw5211": "2x2", + "ecw5410": "4x4" +} + +sanity_status = { + "ea8300": "failed", + "ecw5211": 'passed', + "ecw5410": 'failed', + "ec420": 'failed' +} + +##Customer ID for testing +customer_id = "2" + +##Equipment IDs for Lab APs under test +equipment_id_dict = { + "ea8300": "19", + "ecw5410": "20", + "ecw5211": "21", + "ec420": "27" +} + +equipment_ip_dict = { + "ea8300": "10.10.10.103", + "ecw5410": "10.10.10.105", + "ec420": "10.10.10.104", + "ecw5211": "10.10.10.102" +} + +eqiupment_credentials_dict = { + "ea8300": "openwifi", + "ecw5410": "openwifi", + "ec420": "openwifi", + "ecw5211": "admin123" +} + +##Test Case information - Maps a generic TC name to TestRail TC numbers +test_cases = { + "ap_upgrade": 2233, + "5g_wpa2_bridge": 2236, + "2g_wpa2_bridge": 2237, + "5g_wpa_bridge": 2419, + "2g_wpa_bridge": 2420, + "2g_wpa_nat": 4323, + "5g_wpa_nat": 4324, + "2g_wpa2_nat": 4325, + "5g_wpa2_nat": 4326, + "2g_eap_bridge": 5214, + "5g_eap_bridge": 5215, + "2g_eap_nat": 5216, + "5g_eap_nat": 5217, + "cloud_connection": 5222, + "cloud_fw": 5247, + "5g_wpa2_vlan": 5248, + "5g_wpa_vlan": 5249, + "5g_eap_vlan": 5250, + "2g_wpa2_vlan": 5251, + "2g_wpa_vlan": 5252, + "2g_eap_vlan": 5253, + "cloud_ver": 5540, + "bridge_vifc": 5541, + "nat_vifc": 5542, + "vlan_vifc": 5543, + "bridge_vifs": 5544, + "nat_vifs": 5545, + "vlan_vifs": 5546, + "upgrade_api": 5547, + "create_fw": 5548, + "ap_bridge": 5641, + "ap_nat": 5642, + "ap_vlan": 5643, + "ssid_2g_eap_bridge": 5644, + "ssid_2g_wpa2_bridge": 5645, + "ssid_2g_wpa_bridge": 5646, + "ssid_5g_eap_bridge": 5647, + "ssid_5g_wpa2_bridge": 5648, + "ssid_5g_wpa_bridge": 5649, + "ssid_2g_eap_nat": 5650, + "ssid_2g_wpa2_nat": 5651, + "ssid_2g_wpa_nat": 5652, + "ssid_5g_eap_nat": 5653, + "ssid_5g_wpa2_nat": 5654, + "ssid_5g_wpa_nat": 5655, + "ssid_2g_eap_vlan": 5656, + "ssid_2g_wpa2_vlan": 5657, + "ssid_2g_wpa_vlan": 5658, + "ssid_5g_eap_vlan": 5659, + "ssid_5g_wpa2_vlan": 5660, + "ssid_5g_wpa_vlan": 5661, + "radius_profile": 5808 +} + +## Other profiles +radius_profile = 129 +rf_profile = 10 + +###Testing AP Profile Information +profile_info_dict = { + "ecw5410": { + "profile_id": "2", + "childProfileIds": [ + 129, + 3, + 10, + 11, + 12, + 13, + 190, + 191 + ], + "fiveG_WPA2_SSID": "ECW5410_5G_WPA2", + "fiveG_WPA2_PSK": "Connectus123$", + "fiveG_WPA_SSID": "ECW5410_5G_WPA", + "fiveG_WPA_PSK": "Connectus123$", + "fiveG_OPEN_SSID": "ECW5410_5G_OPEN", + "fiveG_WPA2-EAP_SSID": "ECW5410_5G_WPA2-EAP", + "twoFourG_OPEN_SSID": "ECW5410_2dot4G_OPEN", + "twoFourG_WPA2_SSID": "ECW5410_2dot4G_WPA2", + "twoFourG_WPA2_PSK": "Connectus123$", + "twoFourG_WPA_SSID": "ECW5410_2dot4G_WPA", + "twoFourG_WPA_PSK": "Connectus123$", + "twoFourG_WPA2-EAP_SSID": "ECW5410_2dot4G_WPA2-EAP", + "fiveG_WPA2_profile": 3, + "fiveG_WPA_profile": 13, + "fiveG_WPA2-EAP_profile": 191, + "twoFourG_WPA2_profile": 11, + "twoFourG_WPA_profile": 12, + "twoFourG_WPA2-EAP_profile": 190, + "ssid_list": [ + "ECW5410_5G_WPA2", + "ECW5410_5G_WPA", + "ECW5410_5G_WPA2-EAP", + "ECW5410_2dot4G_WPA2", + "ECW5410_2dot4G_WPA", + "ECW5410_2dot4G_WPA2-EAP" + ] + }, + + "ea8300": { + "profile_id": "153", + "childProfileIds": [ + 17, + 129, + 18, + 201, + 202, + 10, + 14, + 15 + ], + "fiveG_WPA2_SSID": "EA8300_5G_WPA2", + "fiveG_WPA2_PSK": "Connectus123$", + "fiveG_WPA_SSID": "EA8300_5G_WPA", + "fiveG_WPA_PSK": "Connectus123$", + "fiveG_OPEN_SSID": "EA8300_5G_OPEN", + "fiveG_WPA2-EAP_SSID": "EA8300_5G_WPA2-EAP", + "twoFourG_OPEN_SSID": "EA8300_2dot4G_OPEN", + "twoFourG_WPA2_SSID": "EA8300_2dot4G_WPA2", + "twoFourG_WPA2_PSK": "Connectus123$", + "twoFourG_WPA_SSID": "EA8300_2dot4G_WPA", + "twoFourG_WPA_PSK": "Connectus123$", + "twoFourG_WPA2-EAP_SSID": "EA8300_2dot4G_WPA2-EAP", + "fiveG_WPA2_profile": 14, + "fiveG_WPA_profile": 15, + "fiveG_WPA2-EAP_profile": 202, + "twoFourG_WPA2_profile": 17, + "twoFourG_WPA_profile": 18, + "twoFourG_WPA2-EAP_profile": 201, + # EA8300 has 2x 5GHz SSIDs because it is a tri-radio AP! + "ssid_list": [ + "EA8300_5G_WPA2", + "EA8300_5G_WPA2", + "EA8300_5G_WPA", + "EA8300_5G_WPA", + "EA8300_5G_WPA2-EAP", + "EA8300_5G_WPA2-EAP", + "EA8300_2dot4G_WPA2", + "EA8300_2dot4G_WPA", + "EA8300_2dot4G_WPA2-EAP" + ] + }, + + "ec420": { + "profile_id": "20", + "childProfileIds": [ + 129, + 209, + 210, + 21, + 22, + 24, + 25, + 10 + ], + "fiveG_WPA2_SSID": "EC420_5G_WPA2", + "fiveG_WPA2_PSK": "Connectus123$", + "fiveG_WPA_SSID": "EC420_5G_WPA", + "fiveG_WPA_PSK": "Connectus123$", + "fiveG_OPEN_SSID": "EC420_5G_OPEN", + "fiveG_WPA2-EAP_SSID": "EC420_5G_WPA2-EAP", + "twoFourG_OPEN_SSID": "EC420_2dot4G_OPEN", + "twoFourG_WPA2_SSID": "EC420_2dot4G_WPA2", + "twoFourG_WPA2_PSK": "Connectus123$", + "twoFourG_WPA_SSID": "EC420_2dot4G_WPA", + "twoFourG_WPA_PSK": "Connectus123$", + "twoFourG_WPA2-EAP_SSID": "EC420_2dot4G_WPA2-EAP", + "fiveG_WPA2_profile": 21, + "fiveG_WPA_profile": 22, + "fiveG_WPA2-EAP_profile": 210, + "twoFourG_WPA2_profile": 24, + "twoFourG_WPA_profile": 25, + "twoFourG_WPA2-EAP_profile": 209, + "ssid_list": [ + "EC420_5G_WPA2", + "EC420_5G_WPA", + "EC420_5G_WPA2-EAP", + "EC420_2dot4G_WPA2", + "EC420_2dot4G_WPA", + "EC420_2dot4G_WPA2-EAP" + ] + }, + + "ecw5211": { + "profile_id": "27", + "childProfileIds": [ + 32, + 129, + 10, + 28, + 29, + 205, + 206, + 31 + ], + "fiveG_WPA2_SSID": "ECW5211_5G_WPA2", + "fiveG_WPA2_PSK": "Connectus123$", + "fiveG_WPA_SSID": "ECW5211_5G_WPA", + "fiveG_WPA_PSK": "Connectus123$", + "fiveG_OPEN_SSID": "ECW5211_5G_OPEN", + "fiveG_WPA2-EAP_SSID": "ECW5211_5G_WPA2-EAP", + "twoFourG_OPEN_SSID": "ECW5211_2dot4G_OPEN", + "twoFourG_WPA2_SSID": "ECW5211_2dot4G_WPA2", + "twoFourG_WPA2_PSK": "Connectus123$", + "twoFourG_WPA_SSID": "ECW5211_2dot4G_WPA", + "twoFourG_WPA_PSK": "Connectus123$", + "twoFourG_WPA2-EAP_SSID": "ECW5211_2dot4G_WPA2-EAP", + "fiveG_WPA2_profile": 28, + "fiveG_WPA_profile": 29, + "fiveG_WPA2-EAP_profile": 206, + "twoFourG_WPA2_profile": 31, + "twoFourG_WPA_profile": 32, + "twoFourG_WPA2-EAP_profile": 205, + "ssid_list": [ + "ECW5211_5G_WPA2", + "ECW5211_5G_WPA", + "ECW5211_5G_WPA2-EAP", + "ECW5211_2dot4G_WPA2", + "ECW5211_2dot4G_WPA", + "ECW5211_2dot4G_WPA2-EAP" + ] + }, + + "ecw5410_nat": { + "profile_id": "68", + "childProfileIds": [ + 192, + 129, + 81, + 193, + 82, + 10, + 78, + 79 + ], + "fiveG_WPA2_SSID": "ECW5410_5G_WPA2_NAT", + "fiveG_WPA2_PSK": "Connectus123$", + "fiveG_WPA_SSID": "ECW5410_5G_WPA_NAT", + "fiveG_WPA_PSK": "Connectus123$", + "fiveG_OPEN_SSID": "ECW5410_5G_OPEN_NAT", + "fiveG_WPA2-EAP_SSID": "ECW5410_5G_WPA2-EAP_NAT", + "twoFourG_OPEN_SSID": "ECW5410_2dot4G_OPEN_NAT", + "twoFourG_WPA2_SSID": "ECW5410_2dot4G_WPA2_NAT", + "twoFourG_WPA2_PSK": "Connectus123$", + "twoFourG_WPA_SSID": "ECW5410_2dot4G_WPA_NAT", + "twoFourG_WPA_PSK": "Connectus123$", + "twoFourG_WPA2-EAP_SSID": "ECW5410_2dot4G_WPA2-EAP_NAT", + "fiveG_WPA2_profile": 78, + "fiveG_WPA_profile": 79, + "fiveG_WPA2-EAP_profile": 192, + "twoFourG_WPA2_profile": 81, + "twoFourG_WPA_profile": 82, + "twoFourG_WPA2-EAP_profile": 193, + "ssid_list": [ + "ECW5410_5G_WPA2_NAT", + "ECW5410_5G_WPA_NAT", + "ECW5410_5G_WPA2-EAP_NAT", + "ECW5410_2dot4G_WPA2_NAT", + "ECW5410_2dot4G_WPA_NAT", + "ECW5410_2dot4G_WPA2-EAP_NAT" + ] + }, + + "ea8300_nat": { + "profile_id": "67", + "childProfileIds": [ + 129, + 72, + 73, + 10, + 75, + 203, + 76, + 204 + ], + "fiveG_WPA2_SSID": "EA8300_5G_WPA2_NAT", + "fiveG_WPA2_PSK": "Connectus123$", + "fiveG_WPA_SSID": "EA8300_5G_WPA_NAT", + "fiveG_WPA_PSK": "Connectus123$", + "fiveG_OPEN_SSID": "EA8300_5G_OPEN_NAT", + "fiveG_WPA2-EAP_SSID": "EA8300_5G_WPA2-EAP_NAT", + "twoFourG_OPEN_SSID": "EA8300_2dot4G_OPEN_NAT", + "twoFourG_WPA2_SSID": "EA8300_2dot4G_WPA2_NAT", + "twoFourG_WPA2_PSK": "Connectus123$", + "twoFourG_WPA_SSID": "EA8300_2dot4G_WPA_NAT", + "twoFourG_WPA_PSK": "Connectus123$", + "twoFourG_WPA2-EAP_SSID": "EA8300_2dot4G_WPA2-EAP_NAT", + "fiveG_WPA2_profile": 72, + "fiveG_WPA_profile": 73, + "fiveG_WPA2-EAP_profile": 203, + "twoFourG_WPA2_profile": 75, + "twoFourG_WPA_profile": 76, + "twoFourG_WPA2-EAP_profile": 204, + # EA8300 has 2x 5GHz SSIDs because it is a tri-radio AP! + "ssid_list": [ + "EA8300_5G_WPA2_NAT", + "EA8300_5G_WPA2_NAT", + "EA8300_5G_WPA_NAT", + "EA8300_5G_WPA_NAT", + "EA8300_5G_WPA2-EAP_NAT", + "EA8300_5G_WPA2-EAP_NAT", + "EA8300_2dot4G_WPA2_NAT", + "EA8300_2dot4G_WPA_NAT", + "EA8300_2dot4G_WPA2-EAP_NAT" + ] + }, + + "ec420_nat": { + "profile_id": "70", + "childProfileIds": [ + 129, + 211, + 212, + 90, + 10, + 91, + 93, + 94 + ], + "fiveG_WPA2_SSID": "EC420_5G_WPA2_NAT", + "fiveG_WPA2_PSK": "Connectus123$", + "fiveG_WPA_SSID": "EC420_5G_WPA_NAT", + "fiveG_WPA_PSK": "Connectus123$", + "fiveG_OPEN_SSID": "EC420_5G_OPEN_NAT", + "fiveG_WPA2-EAP_SSID": "EC420_5G_WPA2-EAP_NAT", + "twoFourG_OPEN_SSID": "EC420_2dot4G_OPEN_NAT", + "twoFourG_WPA2_SSID": "EC420_2dot4G_WPA2_NAT", + "twoFourG_WPA2_PSK": "Connectus123$", + "twoFourG_WPA_SSID": "EC420_2dot4G_WPA_NAT", + "twoFourG_WPA_PSK": "Connectus123$", + "twoFourG_WPA2-EAP_SSID": "EC420_2dot4G_WPA2-EAP_NAT", + "fiveG_WPA2_profile": 90, + "fiveG_WPA_profile": 91, + "fiveG_WPA2-EAP_profile": 211, + "twoFourG_WPA2_profile": 93, + "twoFourG_WPA_profile": 94, + "twoFourG_WPA2-EAP_profile": 212, + "ssid_list": [ + "EC420_5G_WPA2_NAT", + "EC420_5G_WPA_NAT", + "EC420_5G_WPA2-EAP_NAT", + "EC420_2dot4G_WPA2_NAT", + "EC420_2dot4G_WPA_NAT", + "EC420_2dot4G_WPA2-EAP_NAT" + ] + }, + + "ecw5211_nat": { + "profile_id": "69", + "childProfileIds": [ + 208, + 129, + 84, + 85, + 87, + 88, + 10, + 207 + ], + "fiveG_WPA2_SSID": "ECW5211_5G_WPA2_NAT", + "fiveG_WPA2_PSK": "Connectus123$", + "fiveG_WPA_SSID": "ECW5211_5G_WPA_NAT", + "fiveG_WPA_PSK": "Connectus123$", + "fiveG_OPEN_SSID": "ECW5211_5G_OPEN_NAT", + "fiveG_WPA2-EAP_SSID": "ECW5211_5G_WPA2-EAP_NAT", + "twoFourG_OPEN_SSID": "ECW5211_2dot4G_OPEN_NAT", + "twoFourG_WPA2_SSID": "ECW5211_2dot4G_WPA2_NAT", + "twoFourG_WPA2_PSK": "Connectus123$", + "twoFourG_WPA_SSID": "ECW5211_2dot4G_WPA_NAT", + "twoFourG_WPA_PSK": "Connectus123$", + "twoFourG_WPA2-EAP_SSID": "ECW5211_2dot4G_WPA2-EAP_NAT", + "fiveG_WPA2_profile": 84, + "fiveG_WPA_profile": 85, + "fiveG_WPA2-EAP_profile": 207, + "twoFourG_WPA2_profile": 87, + "twoFourG_WPA_profile": 88, + "twoFourG_WPA2-EAP_profile": 208, + "ssid_list": [ + "ECW5211_5G_WPA2_NAT", + "ECW5211_5G_WPA_NAT", + "ECW5211_5G_WPA2-EAP_NAT", + "ECW5211_2dot4G_WPA2_NAT", + "ECW5211_2dot4G_WPA_NAT", + "ECW5211_2dot4G_WPA2-EAP_NAT" + ] + }, + + "ecw5410_vlan": { + "profile_id": "338", + "childProfileIds": [ + 336, + 320, + 129, + 337, + 10, + 333, + 334, + 335 + ], + "fiveG_WPA2_SSID": "ECW5410_5G_WPA2_VLAN", + "fiveG_WPA2_PSK": "Connectus123$", + "fiveG_WPA_SSID": "ECW5410_5G_WPA_VLAN", + "fiveG_WPA_PSK": "Connectus123$", + "fiveG_OPEN_SSID": "ECW5410_5G_OPEN_VLAN", + "fiveG_WPA2-EAP_SSID": "ECW5410_5G_WPA2-EAP_VLAN", + "twoFourG_OPEN_SSID": "ECW5410_2dot4G_OPEN_VLAN", + "twoFourG_WPA2_SSID": "ECW5410_2dot4G_WPA2_VLAN", + "twoFourG_WPA2_PSK": "Connectus123$", + "twoFourG_WPA_SSID": "ECW5410_2dot4G_WPA_VLAN", + "twoFourG_WPA_PSK": "Connectus123$", + "twoFourG_WPA2-EAP_SSID": "ECW5410_2dot4G_WPA2-EAP_VLAN", + "fiveG_WPA2_profile": 320, + "fiveG_WPA_profile": 333, + "fiveG_WPA2-EAP_profile": 337, + "twoFourG_WPA2_profile": 334, + "twoFourG_WPA_profile": 335, + "twoFourG_WPA2-EAP_profile": 336, + "ssid_list": [ + "ECW5410_5G_WPA2_VLAN", + "ECW5410_5G_WPA_VLAN", + "ECW5410_5G_WPA2-EAP_VLAN", + "ECW5410_2dot4G_WPA2_VLAN", + "ECW5410_2dot4G_WPA_VLAN", + "ECW5410_2dot4G_WPA2-EAP_VLAN" + ] + }, + + "ea8300_vlan": { + "profile_id": "319", + "childProfileIds": [ + 129, + 313, + 10, + 314, + 315, + 316, + 317, + 318 + ], + "fiveG_WPA2_SSID": "EA8300_5G_WPA2_VLAN", + "fiveG_WPA2_PSK": "Connectus123$", + "fiveG_WPA_SSID": "EA8300_5G_WPA_VLAN", + "fiveG_WPA_PSK": "Connectus123$", + "fiveG_OPEN_SSID": "EA8300_5G_OPEN_VLAN", + "fiveG_WPA2-EAP_SSID": "EA8300_5G_WPA2-EAP_VLAN", + "twoFourG_OPEN_SSID": "EA8300_2dot4G_OPEN_VLAN", + "twoFourG_WPA2_SSID": "EA8300_2dot4G_WPA2_VLAN", + "twoFourG_WPA2_PSK": "Connectus123$", + "twoFourG_WPA_SSID": "EA8300_2dot4G_WPA_VLAN", + "twoFourG_WPA_PSK": "Connectus123$", + "twoFourG_WPA2-EAP_SSID": "EA8300_2dot4G_WPA2-EAP_VLAN", + "fiveG_WPA2_profile": 313, + "fiveG_WPA_profile": 314, + "fiveG_WPA2-EAP_profile": 318, + "twoFourG_WPA2_profile": 315, + "twoFourG_WPA_profile": 316, + "twoFourG_WPA2-EAP_profile": 317, + # EA8300 has 2x 5GHz SSIDs because it is a tri-radio AP! + "ssid_list": [ + "EA8300_5G_WPA2_VLAN", + "EA8300_5G_WPA2_VLAN", + "EA8300_5G_WPA_VLAN", + "EA8300_5G_WPA_VLAN", + "EA8300_5G_WPA2-EAP_VLAN", + "EA8300_5G_WPA2-EAP_VLAN", + "EA8300_2dot4G_WPA2_VLAN", + "EA8300_2dot4G_WPA_VLAN", + "EA8300_2dot4G_WPA2-EAP_VLAN" + ] + }, + + "ec420_vlan": { + "profile_id": "357", + "childProfileIds": [ + 352, + 129, + 353, + 354, + 355, + 356, + 10, + 351 + ], + "fiveG_WPA2_SSID": "EC420_5G_WPA2_VLAN", + "fiveG_WPA2_PSK": "Connectus123$", + "fiveG_WPA_SSID": "EC420_5G_WPA_VLAN", + "fiveG_WPA_PSK": "Connectus123$", + "fiveG_OPEN_SSID": "EC420_5G_OPEN_VLAN", + "fiveG_WPA2-EAP_SSID": "EC420_5G_WPA2-EAP_VLAN", + "twoFourG_OPEN_SSID": "EC420_2dot4G_OPEN_VLAN", + "twoFourG_WPA2_SSID": "EC420_2dot4G_WPA2_VLAN", + "twoFourG_WPA2_PSK": "Connectus123$", + "twoFourG_WPA_SSID": "EC420_2dot4G_WPA_VLAN", + "twoFourG_WPA_PSK": "Connectus123$", + "twoFourG_WPA2-EAP_SSID": "EC420_2dot4G_WPA2-EAP_VLAN", + "fiveG_WPA2_profile": 351, + "fiveG_WPA_profile": 352, + "fiveG_WPA2-EAP_profile": 356, + "twoFourG_WPA2_profile": 353, + "twoFourG_WPA_profile": 354, + "twoFourG_WPA2-EAP_profile": 355, + "ssid_list": [ + "EC420_5G_WPA2_VLAN", + "EC420_5G_WPA_VLAN", + "EC420_5G_WPA2-EAP_VLAN", + "EC420_2dot4G_WPA2_VLAN", + "EC420_2dot4G_WPA_VLAN", + "EC420_2dot4G_WPA2-EAP_VLAN" + ] + }, + + "ecw5211_vlan": { + "profile_id": "364", + "childProfileIds": [ + 129, + 358, + 359, + 360, + 361, + 10, + 362, + 363 + ], + "fiveG_WPA2_SSID": "ECW5211_5G_WPA2_VLAN", + "fiveG_WPA2_PSK": "Connectus123$", + "fiveG_WPA_SSID": "ECW5211_5G_WPA_VLAN", + "fiveG_WPA_PSK": "Connectus123$", + "fiveG_OPEN_SSID": "ECW5211_5G_OPEN_VLAN", + "fiveG_WPA2-EAP_SSID": "ECW5211_5G_WPA2-EAP_VLAN", + "twoFourG_OPEN_SSID": "ECW5211_2dot4G_OPEN_VLAN", + "twoFourG_WPA2_SSID": "ECW5211_2dot4G_WPA2_VLAN", + "twoFourG_WPA2_PSK": "Connectus123$", + "twoFourG_WPA_SSID": "ECW5211_2dot4G_WPA_VLAN", + "twoFourG_WPA_PSK": "Connectus123$", + "twoFourG_WPA2-EAP_SSID": "ECW5211_2dot4G_WPA2-EAP_VLAN", + "fiveG_WPA2_profile": 358, + "fiveG_WPA_profile": 359, + "fiveG_WPA2-EAP_profile": 363, + "twoFourG_WPA2_profile": 360, + "twoFourG_WPA_profile": 361, + "twoFourG_WPA2-EAP_profile": 362, + "ssid_list": [ + "ECW5211_5G_WPA2_VLAN", + "ECW5211_5G_WPA_VLAN", + "ECW5211_5G_WPA2-EAP_VLAN", + "ECW5211_2dot4G_WPA2_VLAN", + "ECW5211_2dot4G_WPA_VLAN", + "ECW5211_2dot4G_WPA2-EAP_VLAN" + ] + } +} diff --git a/unit_tests/reports/report_template.php b/unit_tests/reports/report_template.php new file mode 100755 index 000000000..f25fcda54 --- /dev/null +++ b/unit_tests/reports/report_template.php @@ -0,0 +1,622 @@ + + + + +Testing Report + + + + + + + + +
+

CICD Nightly Sanity Report -

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Test Results

+
EA8300 ResultECW5211 ResultECW5410 ResultEC420 Result
New FW Available
FW Under Test
CloudSDK Commit Date
CloudSDK Commit ID
CloudSDK Project Version
Test Pass Rate
Test CaseCategoryDescription
5540CloudSDKGet CloudSDK Version with API
5548CloudSDKCreate FW version on CloudSDK using API
5547CloudSDKRequest AP Upgrade using API
2233APAP Upgrade Successful
5247CloudSDKCloudSDK Reports Correct FW
5222CloudSDKAP-CloudSDK Connection Active
5808CloudSDKCreate RADIUS Profile
5644CloudSDKCreate SSID Profile 2.4 GHz WPA2-EAP - Bridge Mode
5645CloudSDKCreate SSID Profile 2.4 GHz WPA2 - Bridge Mode
5646CloudSDKCreate SSID Profile 2.4 GHz WPA - Bridge Mode
5647CloudSDKCreate SSID Profile 5 GHz WPA2-EAP - Bridge Mode
5647CloudSDKCreate SSID Profile 5 GHz WPA2 - Bridge Mode
5648CloudSDKCreate SSID Profile 5 GHz WPA - Bridge Mode
5641CloudSDKCreate AP Profile - Bridge Mode
5541CloudSDKCloudSDK Pushes Correct AP Profile - Bridge Mode
5544APAP Applies Correct AP Profile - Bridge Mode
5214APClient connects to 2.4 GHz WPA2-EAP - Bridge Mode
2237APClient connects to 2.4 GHz WPA2 - Bridge Mode
2420APClient connects to 2.4 GHz WPA - Bridge Mode
5215APClient connects to 5 GHz WPA2-EAP - Bridge Mode
2236APClient connects to 5 GHz WPA2 - Bridge Mode
2419APClient connects to 5 GHz WPA - Bridge Mode
5650CloudSDKCreate SSID Profile 2.4 GHz WPA2-EAP - NAT Mode
5651CloudSDKCreate SSID Profile 2.4 GHz WPA2 - NAT Mode
5652CloudSDKCreate SSID Profile 2.4 GHz WPA - NAT Mode
5653CloudSDKCreate SSID Profile 5 GHz WPA2-EAP - NAT Mode
5654CloudSDKCreate SSID Profile 5 GHz WPA2 - NAT Mode
5655CloudSDKCreate SSID Profile 5 GHz WPA - NAT Mode
5642CloudSDKCreate AP Profile - NAT Mode
5542CloudSDKCloudSDK Pushes Correct AP Profile - NAT Mode
5545APAP Applies Correct AP Profile - NAT Mode
5216APClient connects to 2.4 GHz WPA2-EAP - NAT Mode
4325APClient connects to 2.4 GHz WPA2 - NAT Mode
4323APClient connects to 2.4 GHz WPA - NAT Mode
5217APClient connects to 5 GHz WPA2-EAP - NAT Mode
4326APClient connects to 5 GHz WPA2 - NAT Mode
4324APClient connects to 5 GHz WPA - NAT Mode
5656CloudSDKCreate SSID Profile 2.4 GHz WPA2-EAP - Custom VLAN
5657CloudSDKCreate SSID Profile 2.4 GHz WPA2 - Custom VLAN
5658CloudSDKCreate SSID Profile 2.4 GHz WPA - Custom VLAN
5659CloudSDKCreate SSID Profile 5 GHz WPA2-EAP - Custom VLAN
5660CloudSDKCreate SSID Profile 5 GHz WPA2 - Custom VLAN
5661CloudSDKCreate SSID Profile 5 GHz WPA - Custom VLAN
5643CloudSDKCreate AP Profile - Custom VLAN
5543CloudSDKCloudSDK Pushes Correct AP Profile - Custom VLAN
5546APAP Applies Correct AP Profile - Custom VLAN
5253APClient connects to 2.4 GHz WPA2-EAP - Custom VLAN
5251APClient connects to 2.4 GHz WPA2 - Custom VLAN
5252APClient connects to 2.4 GHz WPA - Custom VLAN
5250APClient connects to 5 GHz WPA2-EAP - Custom VLAN
5248APClient connects to 5 GHz WPA2 - Custom VLAN
5249APClient connects to 5 GHz WPA - Custom VLAN
+ + \ No newline at end of file diff --git a/unit_tests/sanity_status.json b/unit_tests/sanity_status.json new file mode 100755 index 000000000..a0d9d4c0e --- /dev/null +++ b/unit_tests/sanity_status.json @@ -0,0 +1 @@ +{"sanity_status": {"ea8300": "failed", "ecw5211": "failed", "ecw5410": "failed", "ec420": "failed"}, "sanity_run": {"new_data": "yes"}} \ No newline at end of file diff --git a/unit_tests/single_client_throughput.py b/unit_tests/single_client_throughput.py new file mode 100755 index 000000000..51ab2c9b5 --- /dev/null +++ b/unit_tests/single_client_throughput.py @@ -0,0 +1,1064 @@ +#!/usr/bin/env python3 + +#################################################################################### +# Script is based off of LANForge sta_connect2.py +# Script built for max throughput testing on a single client +# The main function of the script creates a station, then tests: +# 1. UDP Downstream (AP to STA) +# 2. UDP Upstream (STA to AP) +# 3. TCP Downstream (AP to STA) +# 4. TCP Upstream (STA to AP) +# The script will clean up the station and connections at the end of the test. +# +# Used by Throughput_Test ########################################################### +#################################################################################### + +# Script is based off of sta_connect2.py +# Script built for max throughput testing on a single client +# The main function of the script creates a station, then tests: +# 1. UDP Downstream (AP to STA) +# 2. UDP Upstream (STA to AP) +# 3. TCP Downstream (AP to STA) +# 4. TCP Upstream (STA to AP) +# The script will clean up the station and connections at the end of the test. + +import sys +import csv + +if sys.version_info[0] != 3: + print("This script requires Python 3") + exit(1) + +if 'py-json' not in sys.path: + sys.path.append('../../py-json') + +import argparse +from LANforge import LFUtils +# from LANforge import LFCliBase +from LANforge import lfcli_base +from LANforge.lfcli_base import LFCliBase +from LANforge.LFUtils import * +import realm +from realm import Realm +import pprint + +OPEN="open" +WEP="wep" +WPA="wpa" +WPA2="wpa2" +MODE_AUTO=0 + +class SingleClient(LFCliBase): + def __init__(self, host, port, _dut_ssid="jedway-open-1", _dut_passwd="NA", _dut_bssid="", + _user="", _passwd="", _sta_mode="0", _radio="wiphy0", + _resource=1, _upstream_resource=1, _upstream_port="eth1", + _sta_name=None, debug_=False, _dut_security=OPEN, _exit_on_error=False, + _cleanup_on_exit=True, _runtime_sec=60, _exit_on_fail=False): + # do not use `super(LFCLiBase,self).__init__(self, host, port, _debugOn) + # that is py2 era syntax and will force self into the host variable, making you + # very confused. + super().__init__(host, port, _debug=debug_, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) + self.debug = debug_ + self.dut_security = _dut_security + self.dut_ssid = _dut_ssid + self.dut_passwd = _dut_passwd + self.dut_bssid = _dut_bssid + self.user = _user + self.passwd = _passwd + self.sta_mode = _sta_mode # See add_sta LANforge CLI users guide entry + self.radio = _radio + self.resource = _resource + self.upstream_resource = _upstream_resource + self.upstream_port = _upstream_port + self.runtime_secs = _runtime_sec + self.cleanup_on_exit = _cleanup_on_exit + self.sta_url_map = None # defer construction + self.upstream_url = None # defer construction + self.station_names = [] + if _sta_name is not None: + self.station_names = [ _sta_name ] + # self.localrealm :Realm = Realm(lfclient_host=host, lfclient_port=port) # py > 3.6 + self.localrealm = Realm(lfclient_host=host, lfclient_port=port) # py > 3.6 + self.resulting_stations = {} + self.resulting_endpoints = {} + self.station_profile = None + self.l3_udp_profile = None + self.l3_tcp_profile = None + + # def get_realm(self) -> Realm: # py > 3.6 + def get_realm(self): + return self.localrealm + + def get_station_url(self, sta_name_=None): + if sta_name_ is None: + raise ValueError("get_station_url wants a station name") + if self.sta_url_map is None: + self.sta_url_map = {} + for sta_name in self.station_names: + self.sta_url_map[sta_name] = "port/1/%s/%s" % (self.resource, sta_name) + return self.sta_url_map[sta_name_] + + def get_upstream_url(self): + if self.upstream_url is None: + self.upstream_url = "port/1/%s/%s" % (self.upstream_resource, self.upstream_port) + return self.upstream_url + + # Compare pre-test values to post-test values + def compare_vals(self, name, postVal, print_pass=False, print_fail=True): + # print(f"Comparing {name}") + if postVal > 0: + self._pass("%s %s" % (name, postVal), print_pass) + else: + self._fail("%s did not report traffic: %s" % (name, postVal), print_fail) + + def remove_stations(self): + for name in self.station_names: + LFUtils.removePort(self.resource, name, self.lfclient_url) + + def num_associated(self, bssid): + counter = 0 + # print("there are %d results" % len(self.station_results)) + fields = "_links,port,alias,ip,ap,port+type" + self.station_results = self.localrealm.find_ports_like("sta*", fields, debug_=False) + if (self.station_results is None) or (len(self.station_results) < 1): + self.get_failed_result_list() + for eid,record in self.station_results.items(): + #print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ") + #pprint(eid) + #pprint(record) + if record["ap"] == bssid: + counter += 1 + #print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ") + return counter + + def clear_test_results(self): + self.resulting_stations = {} + self.resulting_endpoints = {} + super().clear_test_results() + #super(StaConnect, self).clear_test_results().test_results.clear() + + def setup(self): + self.clear_test_results() + self.check_connect() + upstream_json = self.json_get("%s?fields=alias,phantom,down,port,ip" % self.get_upstream_url(), debug_=False) + + if upstream_json is None: + self._fail(message="Unable to query %s, bye" % self.upstream_port, print_=True) + return False + + if upstream_json['interface']['ip'] == "0.0.0.0": + if self.debug: + pprint.pprint(upstream_json) + self._fail("Warning: %s lacks ip address" % self.get_upstream_url(), print_=True) + return False + + # remove old stations + print("Removing old stations") + for sta_name in self.station_names: + sta_url = self.get_station_url(sta_name) + response = self.json_get(sta_url) + if (response is not None) and (response["interface"] is not None): + for sta_name in self.station_names: + LFUtils.removePort(self.resource, sta_name, self.lfclient_url) + LFUtils.wait_until_ports_disappear(self.lfclient_url, self.station_names) + + # Create stations and turn dhcp on + self.station_profile = self.localrealm.new_station_profile() + + if self.dut_security == WPA2: + self.station_profile.use_security(security_type="wpa2", ssid=self.dut_ssid, passwd=self.dut_passwd) + elif self.dut_security == WPA: + self.station_profile.use_security(security_type="wpa", ssid=self.dut_ssid, passwd=self.dut_passwd) + elif self.dut_security == OPEN: + self.station_profile.use_security(security_type="open", ssid=self.dut_ssid, passwd="[BLANK]") + elif self.dut_security == WPA: + self.station_profile.use_security(security_type="wpa", ssid=self.dut_ssid, passwd=self.dut_passwd) + elif self.dut_security == WEP: + self.station_profile.use_security(security_type="wep", ssid=self.dut_ssid, passwd=self.dut_passwd) + self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) + + print("Adding new stations ", end="") + self.station_profile.create(radio=self.radio, sta_names_=self.station_names, up_=False, debug=self.debug, suppress_related_commands_=True) + LFUtils.wait_until_ports_appear(self.lfclient_url, self.station_names, debug=self.debug) + + def start(self): + if self.station_profile is None: + self._fail("Incorrect setup") + pprint.pprint(self.station_profile) + if self.station_profile.up is None: + self._fail("Incorrect station profile, missing profile.up") + if self.station_profile.up == False: + print("\nBringing ports up...") + data = {"shelf": 1, + "resource": self.resource, + "port": "ALL", + "probe_flags": 1} + self.json_post("/cli-json/nc_show_ports", data) + self.station_profile.admin_up() + LFUtils.waitUntilPortsAdminUp(self.resource, self.lfclient_url, self.station_names) + + # station_info = self.jsonGet(self.mgr_url, "%s?fields=port,ip,ap" % (self.getStaUrl())) + duration = 0 + maxTime = 100 + ip = "0.0.0.0" + ap = "" + print("Waiting for %s stations to associate to AP: " % len(self.station_names), end="") + connected_stations = {} + while (len(connected_stations.keys()) < len(self.station_names)) and (duration < maxTime): + duration += 3 + time.sleep(10) + print(".", end="") + for sta_name in self.station_names: + sta_url = self.get_station_url(sta_name) + station_info = self.json_get(sta_url + "?fields=port,ip,ap") + + # LFUtils.debug_printer.pprint(station_info) + if (station_info is not None) and ("interface" in station_info): + if "ip" in station_info["interface"]: + ip = station_info["interface"]["ip"] + if "ap" in station_info["interface"]: + ap = station_info["interface"]["ap"] + + if (ap == "Not-Associated") or (ap == ""): + if self.debug: + print(" -%s," % sta_name, end="") + else: + if ip == "0.0.0.0": + if self.debug: + print(" %s (0.0.0.0)" % sta_name, end="") + else: + connected_stations[sta_name] = sta_url + data = { + "shelf":1, + "resource": self.resource, + "port": "ALL", + "probe_flags": 1 + } + self.json_post("/cli-json/nc_show_ports", data) + + for sta_name in self.station_names: + sta_url = self.get_station_url(sta_name) + station_info = self.json_get(sta_url) # + "?fields=port,ip,ap") + if station_info is None: + print("unable to query %s" % sta_url) + self.resulting_stations[sta_url] = station_info + ap = station_info["interface"]["ap"] + ip = station_info["interface"]["ip"] + if (ap != "") and (ap != "Not-Associated"): + print(" %s +AP %s, " % (sta_name, ap), end="") + if self.dut_bssid != "": + if self.dut_bssid.lower() == ap.lower(): + self._pass(sta_name+" connected to BSSID: " + ap) + # self.test_results.append("PASSED: ) + # print("PASSED: Connected to BSSID: "+ap) + else: + self._fail("%s connected to wrong BSSID, requested: %s Actual: %s" % (sta_name, self.dut_bssid, ap)) + else: + self._fail(sta_name+" did not connect to AP") + return False + + if ip == "0.0.0.0": + self._fail("%s did not get an ip. Ending test" % sta_name) + else: + self._pass("%s connected to AP: %s With IP: %s" % (sta_name, ap, ip)) + + if self.passes() == False: + if self.cleanup_on_exit: + print("Cleaning up...") + self.remove_stations() + return False + + def udp_profile(self, side_a_min_bps, side_b_min_bps, side_a_min_pdu, side_b_min_pdu): + # Create UDP endpoint - Alex's code! + self.l3_udp_tput_profile = self.localrealm.new_l3_cx_profile() + self.l3_udp_tput_profile.side_a_min_bps = side_a_min_bps + self.l3_udp_tput_profile.side_b_min_bps = side_b_min_bps + self.l3_udp_tput_profile.side_a_min_pdu = side_a_min_pdu + self.l3_udp_tput_profile.side_b_min_pdu = side_b_min_pdu + self.l3_udp_tput_profile.report_timer = 1000 + self.l3_udp_tput_profile.name_prefix = "udp" + self.l3_udp_tput_profile.create(endp_type="lf_udp", + side_a=list(self.localrealm.find_ports_like("tput+")), + side_b="%d.%s" % (self.resource, self.upstream_port), + suppress_related_commands=True) + + def tcp_profile(self, side_a_min_bps, side_b_min_bps): + # Create TCP endpoints - original code! + self.l3_tcp_tput_profile = self.localrealm.new_l3_cx_profile() + self.l3_tcp_tput_profile.side_a_min_bps = side_a_min_bps + self.l3_tcp_tput_profile.side_b_min_bps = side_b_min_bps + self.l3_tcp_tput_profile.name_prefix = "tcp" + self.l3_tcp_tput_profile.report_timer = 1000 + self.l3_tcp_tput_profile.create(endp_type="lf_tcp", + side_a=list(self.localrealm.find_ports_like("tput+")), + side_b="%d.%s" % (self.resource, self.upstream_port), + suppress_related_commands=True) + + # Start UDP Downstream Traffic + def udp_throughput(self): + print("\nStarting UDP Traffic") + self.l3_udp_tput_profile.start_cx() + time.sleep(1) + self.l3_udp_tput_profile.refresh_cx() + + def tcp_throughput(self): + print("\nStarting TCP Traffic") + self.l3_tcp_tput_profile.start_cx() + time.sleep(1) + self.l3_tcp_tput_profile.refresh_cx() + + def udp_stop(self): + # stop cx traffic + print("Stopping CX Traffic") + self.l3_udp_tput_profile.stop_cx() + + # Refresh stats + print("\nRefresh CX stats") + self.l3_udp_tput_profile.refresh_cx() + + print("Sleeping for 5 seconds") + time.sleep(5) + + # get data for endpoints JSON + return self.collect_client_stats(self.l3_udp_tput_profile.created_cx) + # print("\n") + + def tcp_stop(self): + # stop cx traffic + print("Stopping CX Traffic") + self.l3_tcp_tput_profile.stop_cx() + + # Refresh stats + print("\nRefresh CX stats") + self.l3_tcp_tput_profile.refresh_cx() + + print("Sleeping for 5 seconds") + time.sleep(5) + + # get data for endpoints JSON + return self.collect_client_stats(self.l3_tcp_tput_profile.created_cx) + # print("\n") + + # New Endpoint code to print TX and RX numbers + def collect_client_stats(self, endp_map): + print("Collecting Data") + fields="?fields=name,tx+bytes,rx+bytes" + for (cx_name, endps) in endp_map.items(): + try: + endp_url = "/endp/%s%s" % (endps[0], fields) + endp_json = self.json_get(endp_url) + self.resulting_endpoints[endp_url] = endp_json + ptest_a_tx = endp_json['endpoint']['tx bytes'] + ptest_a_rx = endp_json['endpoint']['rx bytes'] + + # ptest = self.json_get("/endp/%s?fields=tx+bytes,rx+bytes" % cx_names[cx_name]["b"]) + endp_url = "/endp/%s%s" % (endps[1], fields) + endp_json = self.json_get(endp_url) + self.resulting_endpoints[endp_url] = endp_json + ptest_b_tx = endp_json['endpoint']['tx bytes'] + ptest_b_rx = endp_json['endpoint']['rx bytes'] + + byte_values = [] + byte_values.append("Station TX: " + str(ptest_a_tx)) + byte_values.append("Station RX: " + str(ptest_a_rx)) + byte_values.append("AP TX: " + str(ptest_b_tx)) + byte_values.append("AP RX: " + str(ptest_b_rx)) + + return byte_values + + except Exception as e: + self.error(e) + + def cleanup_udp(self): + # remove all endpoints and cxs + if self.cleanup_on_exit: + for sta_name in self.station_names: + LFUtils.removePort(self.resource, sta_name, self.lfclient_url) + curr_endp_names = [] + removeCX(self.lfclient_url, self.l3_udp_tput_profile.get_cx_names()) + for (cx_name, endp_names) in self.l3_udp_tput_profile.created_cx.items(): + curr_endp_names.append(endp_names[0]) + curr_endp_names.append(endp_names[1]) + removeEndps(self.lfclient_url, curr_endp_names, debug= self.debug) + + def cleanup_tcp(self): + # remove all endpoints and cxs + if self.cleanup_on_exit: + for sta_name in self.station_names: + LFUtils.removePort(self.resource, sta_name, self.lfclient_url) + curr_endp_names = [] + removeCX(self.lfclient_url, self.l3_tcp_tput_profile.get_cx_names()) + for (cx_name, endp_names) in self.l3_tcp_tput_profile.created_cx.items(): + curr_endp_names.append(endp_names[0]) + curr_endp_names.append(endp_names[1]) + removeEndps(self.lfclient_url, curr_endp_names, debug= self.debug) + + def cleanup(self): + # remove all endpoints and cxs + if self.cleanup_on_exit: + for sta_name in self.station_names: + LFUtils.removePort(self.resource, sta_name, self.lfclient_url) + curr_endp_names = [] + removeCX(self.lfclient_url, self.l3_tcp_tput_profile.get_cx_names()) + removeCX(self.lfclient_url, self.l3_udp_tput_profile.get_cx_names()) + for (cx_name, endp_names) in self.l3_tcp_tput_profile.created_cx.items(): + curr_endp_names.append(endp_names[0]) + curr_endp_names.append(endp_names[1]) + for (cx_name, endp_names) in self.l3_udp_tput_profile.created_cx.items(): + curr_endp_names.append(endp_names[0]) + curr_endp_names.append(endp_names[1]) + removeEndps(self.lfclient_url, curr_endp_names, debug=self.debug) + + def udp_unidirectional(self, side_a_min_bps, side_b_min_bps, side_a_min_pdu, side_b_min_pdu, direction, values_line): + self.udp_profile(side_a_min_bps, side_b_min_bps, side_a_min_pdu, side_b_min_pdu) + self.start() + print("Running", direction, "Traffic for %s seconds" % self.runtime_secs) + self.udp_throughput() + print("napping %f sec" % self.runtime_secs) + time.sleep(self.runtime_secs) + values = self.udp_stop() + print(values) + # Get value required for measurement + bytes = values[values_line] + # Get value in Bits and convert to Mbps + bits = (int(bytes.split(": ", 1)[1])) * 8 + mpbs = round((bits / 1000000) / self.runtime_secs, 2) + return mpbs + + def tcp_unidirectional(self, side_a_min_bps, side_b_min_bps, direction, values_line): + self.tcp_profile(side_a_min_bps, side_b_min_bps) + self.start() + print("Running", direction, "Traffic for %s seconds" % self.runtime_secs) + self.tcp_throughput() + print("napping %f sec" % self.runtime_secs) + time.sleep(self.runtime_secs) + values = self.tcp_stop() + print(values) + # Get value required for measurement + bytes = values[values_line] + # Get value in Bits and convert to Mbps + bits = (int(bytes.split(": ", 1)[1])) * 8 + mpbs = round((bits / 1000000) / self.runtime_secs, 2) + return mpbs + + def throughput_csv(csv_file, ssid_name, ap_model, firmware, security, udp_ds, udp_us, tcp_ds, tcp_us): + # Find band for CSV ---> This code is not great, it SHOULD get that info from LANForge! + if "5G" in ssid_name: + frequency = "5 GHz" + + elif "2dot4G" in ssid_name: + frequency = "2.4 GHz" + + else: + frequency = "Unknown" + + # Append row to top of CSV file + row = [ap_model, firmware, frequency, security, udp_ds, udp_us, tcp_ds, tcp_us] + + with open(csv_file, 'r') as readFile: + reader = csv.reader(readFile) + lines = list(reader) + lines.insert(1, row) + + with open(csv_file, 'w') as writeFile: + writer = csv.writer(writeFile) + writer.writerows(lines) + + readFile.close() + writeFile.close() + + +class SingleClientEAP(LFCliBase): + def __init__(self, host, port, security=None, ssid=None, sta_list=None, number_template="00000", _debug_on=False, _dut_bssid="", + _exit_on_error=False, _sta_name=None, _resource=1, radio="wiphy0", key_mgmt="WPA-EAP", eap="", identity="", + ttls_passwd="", hessid=None, ttls_realm="", domain="", _exit_on_fail=False, _cleanup_on_exit=True): + super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail) + self.host = host + self.port = port + self.ssid = ssid + self.radio = radio + self.security = security + #self.password = password + self.sta_list = sta_list + self.key_mgmt = key_mgmt + self.eap = eap + self.identity = identity + self.ttls_passwd = ttls_passwd + self.ttls_realm = ttls_realm + self.domain = domain + self.hessid = hessid + self.dut_bssid = _dut_bssid + self.timeout = 120 + self.number_template = number_template + self.debug = _debug_on + self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port) + self.station_profile = self.local_realm.new_station_profile() + self.station_profile.lfclient_url = self.lfclient_url + self.station_profile.ssid = self.ssid + self.station_profile.security = self.security + self.station_profile.number_template_ = self.number_template + self.station_profile.mode = 0 + #Added to test_ipv4_ttls code + self.upstream_url = None # defer construction + self.sta_url_map = None + self.upstream_resource = None + self.upstream_port = None + self.station_names = [] + if _sta_name is not None: + self.station_names = [_sta_name] + self.localrealm = Realm(lfclient_host=host, lfclient_port=port) + self.resource = _resource + self.cleanup_on_exit = _cleanup_on_exit + self.resulting_stations = {} + self.resulting_endpoints = {} + self.station_profile = None + self.l3_udp_profile = None + self.l3_tcp_profile = None + + # def get_realm(self) -> Realm: # py > 3.6 + def get_realm(self): + return self.localrealm + + def get_station_url(self, sta_name_=None): + if sta_name_ is None: + raise ValueError("get_station_url wants a station name") + if self.sta_url_map is None: + self.sta_url_map = {} + for sta_name in self.station_names: + self.sta_url_map[sta_name] = "port/1/%s/%s" % (self.resource, sta_name) + return self.sta_url_map[sta_name_] + + def get_upstream_url(self): + if self.upstream_url is None: + self.upstream_url = "port/1/%s/%s" % (self.upstream_resource, self.upstream_port) + return self.upstream_url + + # Compare pre-test values to post-test values + def compare_vals(self, name, postVal, print_pass=False, print_fail=True): + # print(f"Comparing {name}") + if postVal > 0: + self._pass("%s %s" % (name, postVal), print_pass) + else: + self._fail("%s did not report traffic: %s" % (name, postVal), print_fail) + + def remove_stations(self): + for name in self.station_names: + LFUtils.removePort(self.resource, name, self.lfclient_url) + + def num_associated(self, bssid): + counter = 0 + # print("there are %d results" % len(self.station_results)) + fields = "_links,port,alias,ip,ap,port+type" + self.station_results = self.localrealm.find_ports_like("eap*", fields, debug_=False) + if (self.station_results is None) or (len(self.station_results) < 1): + self.get_failed_result_list() + for eid,record in self.station_results.items(): + #print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ") + #pprint(eid) + #pprint(record) + if record["ap"] == bssid: + counter += 1 + #print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ") + return counter + + def clear_test_results(self): + self.resulting_stations = {} + self.resulting_endpoints = {} + super().clear_test_results() + #super(StaConnect, self).clear_test_results().test_results.clear() + + def setup(self): + self.clear_test_results() + self.check_connect() + upstream_json = self.json_get("%s?fields=alias,phantom,down,port,ip" % self.get_upstream_url(), debug_=False) + + if upstream_json is None: + self._fail(message="Unable to query %s, bye" % self.upstream_port, print_=True) + return False + + if upstream_json['interface']['ip'] == "0.0.0.0": + if self.debug: + pprint.pprint(upstream_json) + self._fail("Warning: %s lacks ip address" % self.get_upstream_url(), print_=True) + return False + + # remove old stations + print("Removing old stations") + for sta_name in self.station_names: + sta_url = self.get_station_url(sta_name) + response = self.json_get(sta_url) + if (response is not None) and (response["interface"] is not None): + for sta_name in self.station_names: + LFUtils.removePort(self.resource, sta_name, self.lfclient_url) + LFUtils.wait_until_ports_disappear(self.lfclient_url, self.station_names) + + # Create stations and turn dhcp on + self.station_profile = self.localrealm.new_station_profile() + + # Build stations + self.station_profile.use_security(self.security, self.ssid, passwd="[BLANK]") + self.station_profile.set_number_template(self.number_template) + print("Creating stations") + self.station_profile.set_command_flag("add_sta", "create_admin_down", 1) + self.station_profile.set_command_param("set_port", "report_timer", 1500) + self.station_profile.set_command_flag("set_port", "rpt_timer", 1) + self.station_profile.set_wifi_extra(key_mgmt=self.key_mgmt, eap=self.eap, identity=self.identity, + passwd=self.ttls_passwd, + realm=self.ttls_realm, domain=self.domain, + hessid=self.hessid) + self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug, use_radius=True, hs20_enable=False) + self._pass("PASS: Station build finished") + + def start(self): + if self.station_profile is None: + self._fail("Incorrect setup") + pprint.pprint(self.station_profile) + if self.station_profile.up is None: + self._fail("Incorrect station profile, missing profile.up") + if self.station_profile.up == False: + print("\nBringing ports up...") + data = {"shelf": 1, + "resource": self.resource, + "port": "ALL", + "probe_flags": 1} + self.json_post("/cli-json/nc_show_ports", data) + self.station_profile.admin_up() + LFUtils.waitUntilPortsAdminUp(self.resource, self.lfclient_url, self.station_names) + + # station_info = self.jsonGet(self.mgr_url, "%s?fields=port,ip,ap" % (self.getStaUrl())) + duration = 0 + maxTime = 30 + ip = "0.0.0.0" + ap = "" + print("Waiting for %s stations to associate to AP: " % len(self.station_names), end="") + connected_stations = {} + while (len(connected_stations.keys()) < len(self.station_names)) and (duration < maxTime): + duration += 3 + time.sleep(10) + print(".", end="") + for sta_name in self.station_names: + sta_url = self.get_station_url(sta_name) + station_info = self.json_get(sta_url + "?fields=port,ip,ap") + + # LFUtils.debug_printer.pprint(station_info) + if (station_info is not None) and ("interface" in station_info): + if "ip" in station_info["interface"]: + ip = station_info["interface"]["ip"] + if "ap" in station_info["interface"]: + ap = station_info["interface"]["ap"] + + if (ap == "Not-Associated") or (ap == ""): + if self.debug: + print(" -%s," % sta_name, end="") + else: + if ip == "0.0.0.0": + if self.debug: + print(" %s (0.0.0.0)" % sta_name, end="") + else: + connected_stations[sta_name] = sta_url + data = { + "shelf":1, + "resource": self.resource, + "port": "ALL", + "probe_flags": 1 + } + self.json_post("/cli-json/nc_show_ports", data) + + for sta_name in self.station_names: + sta_url = self.get_station_url(sta_name) + station_info = self.json_get(sta_url) # + "?fields=port,ip,ap") + if station_info is None: + print("unable to query %s" % sta_url) + self.resulting_stations[sta_url] = station_info + ap = station_info["interface"]["ap"] + ip = station_info["interface"]["ip"] + if (ap != "") and (ap != "Not-Associated"): + print(" %s +AP %s, " % (sta_name, ap), end="") + if self.dut_bssid != "": + if self.dut_bssid.lower() == ap.lower(): + self._pass(sta_name+" connected to BSSID: " + ap) + # self.test_results.append("PASSED: ) + # print("PASSED: Connected to BSSID: "+ap) + else: + self._fail("%s connected to wrong BSSID, requested: %s Actual: %s" % (sta_name, self.dut_bssid, ap)) + else: + self._fail(sta_name+" did not connect to AP") + return False + + if ip == "0.0.0.0": + self._fail("%s did not get an ip. Ending test" % sta_name) + else: + self._pass("%s connected to AP: %s With IP: %s" % (sta_name, ap, ip)) + + if self.passes() == False: + if self.cleanup_on_exit: + print("Cleaning up...") + self.remove_stations() + return False + + def udp_profile(self, side_a_min_bps, side_b_min_bps, side_a_min_pdu, side_b_min_pdu): + # Create UDP endpoint - Alex's code! + self.l3_udp_tput_profile = self.localrealm.new_l3_cx_profile() + self.l3_udp_tput_profile.side_a_min_bps = side_a_min_bps + self.l3_udp_tput_profile.side_b_min_bps = side_b_min_bps + self.l3_udp_tput_profile.side_a_min_pdu = side_a_min_pdu + self.l3_udp_tput_profile.side_b_min_pdu = side_b_min_pdu + self.l3_udp_tput_profile.report_timer = 1000 + self.l3_udp_tput_profile.name_prefix = "udp" + self.l3_udp_tput_profile.create(endp_type="lf_udp", + side_a=list(self.localrealm.find_ports_like("tput+")), + side_b="%d.%s" % (self.resource, self.upstream_port), + suppress_related_commands=True) + + def tcp_profile(self, side_a_min_bps, side_b_min_bps): + # Create TCP endpoints - original code! + self.l3_tcp_tput_profile = self.localrealm.new_l3_cx_profile() + self.l3_tcp_tput_profile.side_a_min_bps = side_a_min_bps + self.l3_tcp_tput_profile.side_b_min_bps = side_b_min_bps + self.l3_tcp_tput_profile.name_prefix = "tcp" + self.l3_tcp_tput_profile.report_timer = 1000 + self.l3_tcp_tput_profile.create(endp_type="lf_tcp", + side_a=list(self.localrealm.find_ports_like("tput+")), + side_b="%d.%s" % (self.resource, self.upstream_port), + suppress_related_commands=True) + + # Start UDP Downstream Traffic + def udp_throughput(self): + print("\nStarting UDP Traffic") + self.l3_udp_tput_profile.start_cx() + time.sleep(1) + self.l3_udp_tput_profile.refresh_cx() + + def tcp_throughput(self): + print("\nStarting TCP Traffic") + self.l3_tcp_tput_profile.start_cx() + time.sleep(1) + self.l3_tcp_tput_profile.refresh_cx() + + def udp_stop(self): + # stop cx traffic + print("Stopping CX Traffic") + self.l3_udp_tput_profile.stop_cx() + + # Refresh stats + print("\nRefresh CX stats") + self.l3_udp_tput_profile.refresh_cx() + + print("Sleeping for 5 seconds") + time.sleep(5) + + # get data for endpoints JSON + return self.collect_client_stats(self.l3_udp_tput_profile.created_cx) + # print("\n") + + def tcp_stop(self): + # stop cx traffic + print("Stopping CX Traffic") + self.l3_tcp_tput_profile.stop_cx() + + # Refresh stats + print("\nRefresh CX stats") + self.l3_tcp_tput_profile.refresh_cx() + + print("Sleeping for 5 seconds") + time.sleep(5) + + # get data for endpoints JSON + return self.collect_client_stats(self.l3_tcp_tput_profile.created_cx) + # print("\n") + + # New Endpoint code to print TX and RX numbers + def collect_client_stats(self, endp_map): + print("Collecting Data") + fields="?fields=name,tx+bytes,rx+bytes" + for (cx_name, endps) in endp_map.items(): + try: + endp_url = "/endp/%s%s" % (endps[0], fields) + endp_json = self.json_get(endp_url) + self.resulting_endpoints[endp_url] = endp_json + ptest_a_tx = endp_json['endpoint']['tx bytes'] + ptest_a_rx = endp_json['endpoint']['rx bytes'] + + # ptest = self.json_get("/endp/%s?fields=tx+bytes,rx+bytes" % cx_names[cx_name]["b"]) + endp_url = "/endp/%s%s" % (endps[1], fields) + endp_json = self.json_get(endp_url) + self.resulting_endpoints[endp_url] = endp_json + ptest_b_tx = endp_json['endpoint']['tx bytes'] + ptest_b_rx = endp_json['endpoint']['rx bytes'] + + byte_values = [] + byte_values.append("Station TX: " + str(ptest_a_tx)) + byte_values.append("Station RX: " + str(ptest_a_rx)) + byte_values.append("AP TX: " + str(ptest_b_tx)) + byte_values.append("AP RX: " + str(ptest_b_rx)) + + return byte_values + + except Exception as e: + self.error(e) + + def cleanup_udp(self): + # remove all endpoints and cxs + if self.cleanup_on_exit: + for sta_name in self.station_names: + LFUtils.removePort(self.resource, sta_name, self.lfclient_url) + curr_endp_names = [] + removeCX(self.lfclient_url, self.l3_udp_tput_profile.get_cx_names()) + for (cx_name, endp_names) in self.l3_udp_tput_profile.created_cx.items(): + curr_endp_names.append(endp_names[0]) + curr_endp_names.append(endp_names[1]) + removeEndps(self.lfclient_url, curr_endp_names, debug= self.debug) + + def cleanup_tcp(self): + # remove all endpoints and cxs + if self.cleanup_on_exit: + for sta_name in self.station_names: + LFUtils.removePort(self.resource, sta_name, self.lfclient_url) + curr_endp_names = [] + removeCX(self.lfclient_url, self.l3_tcp_tput_profile.get_cx_names()) + for (cx_name, endp_names) in self.l3_tcp_tput_profile.created_cx.items(): + curr_endp_names.append(endp_names[0]) + curr_endp_names.append(endp_names[1]) + removeEndps(self.lfclient_url, curr_endp_names, debug= self.debug) + + def cleanup(self): + # remove all endpoints and cxs + if self.cleanup_on_exit: + for sta_name in self.station_names: + LFUtils.removePort(self.resource, sta_name, self.lfclient_url) + curr_endp_names = [] + removeCX(self.lfclient_url, self.l3_tcp_tput_profile.get_cx_names()) + removeCX(self.lfclient_url, self.l3_udp_tput_profile.get_cx_names()) + for (cx_name, endp_names) in self.l3_tcp_tput_profile.created_cx.items(): + curr_endp_names.append(endp_names[0]) + curr_endp_names.append(endp_names[1]) + for (cx_name, endp_names) in self.l3_udp_tput_profile.created_cx.items(): + curr_endp_names.append(endp_names[0]) + curr_endp_names.append(endp_names[1]) + removeEndps(self.lfclient_url, curr_endp_names, debug=self.debug) + + def udp_unidirectional(self, side_a_min_bps, side_b_min_bps, side_a_min_pdu, side_b_min_pdu, direction, values_line): + self.udp_profile(side_a_min_bps, side_b_min_bps, side_a_min_pdu, side_b_min_pdu) + self.start() + print("Running", direction, "Traffic for %s seconds" % self.runtime_secs) + self.udp_throughput() + print("napping %f sec" % self.runtime_secs) + time.sleep(self.runtime_secs) + values = self.udp_stop() + print(values) + # Get value required for measurement + bytes = values[values_line] + # Get value in Bits and convert to Mbps + bits = (int(bytes.split(": ", 1)[1])) * 8 + mpbs = round((bits / 1000000) / self.runtime_secs, 2) + return mpbs + + def tcp_unidirectional(self, side_a_min_bps, side_b_min_bps, direction, values_line): + self.tcp_profile(side_a_min_bps, side_b_min_bps) + self.start() + print("Running", direction, "Traffic for %s seconds" % self.runtime_secs) + self.tcp_throughput() + print("napping %f sec" % self.runtime_secs) + time.sleep(self.runtime_secs) + values = self.tcp_stop() + print(values) + # Get value required for measurement + bytes = values[values_line] + # Get value in Bits and convert to Mbps + bits = (int(bytes.split(": ", 1)[1])) * 8 + mpbs = round((bits / 1000000) / self.runtime_secs, 2) + return mpbs +# ~class + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +########################## Test Code ################################ + +##Main will perform 4 throughput tests on SSID provided by input and return a list with the values + +def main(ap_model, firmware, radio, ssid_name, ssid_psk, security, station, runtime, upstream_port): + ######## Establish Client Connection ######################### + singleClient = SingleClient("10.10.10.201", 8080, debug_=False) + singleClient.sta_mode = 0 + singleClient.upstream_resource = 1 + singleClient.upstream_port = upstream_port + singleClient.radio = radio + singleClient.resource = 1 + singleClient.dut_ssid = ssid_name + singleClient.dut_passwd = ssid_psk + singleClient.dut_security = security + singleClient.station_names = station + singleClient.runtime_secs = runtime + singleClient.cleanup_on_exit = True + + #Create List for Throughput Data + tput_data = [] + + ####### Setup UDP Profile and Run Traffic Downstream (AP to STA) ####################### + singleClient.setup() + side_a_min_bps = 56000 + side_b_min_bps = 500000000 + side_a_min_pdu = 1200 + side_b_min_pdu = 1500 + direction = "Downstream" + values_line = 1 # 1 = Station Rx + try: + udp_ds = singleClient.udp_unidirectional(side_a_min_bps, side_b_min_bps, side_a_min_pdu, side_b_min_pdu, direction, values_line) + print("UDP Downstream:", udp_ds, "Mbps") + tput_data.append("UDP Downstream: " + str(udp_ds)) + except: + udp_ds = "error" + print("UDP Downstream Test Error") + tput_data.append("UDP Downstream: Error") + + + ####### Setup UDP Profile and Run Traffic Upstream (STA to AP) ####################### + #singleClient.setup() + side_a_min_bps = 500000000 + side_b_min_bps = 0 + side_a_min_pdu = 1200 + side_b_min_pdu = 1500 + direction = "Upstream" + values_line = 3 # 3 = AP Rx + try: + udp_us = singleClient.udp_unidirectional(side_a_min_bps, side_b_min_bps, side_a_min_pdu, side_b_min_pdu, direction, values_line) + print("UDP Upstream:",udp_us,"Mbps") + tput_data.append("UDP Upstream: " + str(udp_us)) + except: + udp_us = "error" + print("UDP Upstream Test Error") + tput_data.append("UDP Upstream: Error") + #Cleanup UDP Endpoints + #singleClient.cleanup_udp() + + + ####### Setup TCP Profile and Run Traffic Downstream (AP to STA) ####################### + #singleClient.setup() + side_a_min_bps = 0 + side_b_min_bps = 500000000 + direction = "Downstream" + values_line = 1 # 1 = Station Rx + try: + tcp_ds = singleClient.tcp_unidirectional(side_a_min_bps, side_b_min_bps, direction, values_line) + print("TCP Downstream:",tcp_ds,"Mbps") + tput_data.append("TCP Downstream: " + str(tcp_ds)) + except: + tcp_ds = "error" + print("TCP Downstream Test Error") + tput_data.append("TCP Downstream: Error") + + ####### Setup TCP Profile and Run Traffic Upstream (STA to AP) ####################### + #singleClient.setup() + side_a_min_bps = 500000000 + side_b_min_bps = 0 + direction = "Upstream" + values_line = 3 # 3 = AP Rx + try: + tcp_us = singleClient.tcp_unidirectional(side_a_min_bps, side_b_min_bps, direction, values_line) + print("TCP Upstream:",tcp_us,"Mbps") + tput_data.append("TCP Upstream: " + str(tcp_us)) + except: + tcp_us = "error" + print("TCP Upstream Test Error") + tput_data.append("TCP Uptream: Error") + + #Cleanup TCP Endpoints + #singleClient.cleanup_tcp() + + #Cleanup Endpoints + singleClient.cleanup() + + return(tput_data) + +def eap_tput(sta_list, ssid_name, radio, security, eap_type, identity, ttls_password, upstream_port): + eap_connect = SingleClientEAP("10.10.10.201", 8080, _debug_on=False) + eap_connect.upstream_resource = 1 + eap_connect.upstream_port = upstream_port + eap_connect.security = security + eap_connect.sta_list = sta_list + eap_connect.station_names = sta_list + eap_connect.ssid = ssid_name + eap_connect.radio = radio + eap_connect.eap = eap_type + eap_connect.identity = identity + eap_connect.ttls_passwd = ttls_password + eap_connect.runtime_secs = 10 + + #Create List for Throughput Data + tput_data = [] + + ####### Setup UDP Profile and Run Traffic Downstream (AP to STA) ####################### + eap_connect.setup() + side_a_min_bps = 56000 + side_b_min_bps = 500000000 + side_a_min_pdu = 1200 + side_b_min_pdu = 1500 + direction = "Downstream" + values_line = 1 # 1 = Station Rx + try: + udp_ds = eap_connect.udp_unidirectional(side_a_min_bps, side_b_min_bps, side_a_min_pdu, side_b_min_pdu, direction, values_line) + print("UDP Downstream:", udp_ds, "Mbps") + tput_data.append("UDP Downstream: " + str(udp_ds)) + except: + udp_ds = "error" + print("UDP Downstream Test Error") + tput_data.append("UDP Downstream: Error") + + + ####### Setup UDP Profile and Run Traffic Upstream (STA to AP) ####################### + #singleClient.setup() + side_a_min_bps = 500000000 + side_b_min_bps = 0 + side_a_min_pdu = 1200 + side_b_min_pdu = 1500 + direction = "Upstream" + values_line = 3 # 3 = AP Rx + try: + udp_us = eap_connect.udp_unidirectional(side_a_min_bps, side_b_min_bps, side_a_min_pdu, side_b_min_pdu, direction, values_line) + print("UDP Upstream:",udp_us,"Mbps") + tput_data.append("UDP Upstream: " + str(udp_us)) + except: + udp_us = "error" + print("UDP Upstream Test Error") + tput_data.append("UDP Upstream: Error") + #Cleanup UDP Endpoints + #singleClient.cleanup_udp() + + + ####### Setup TCP Profile and Run Traffic Downstream (AP to STA) ####################### + #singleClient.setup() + side_a_min_bps = 0 + side_b_min_bps = 500000000 + direction = "Downstream" + values_line = 1 # 1 = Station Rx + try: + tcp_ds = eap_connect.tcp_unidirectional(side_a_min_bps, side_b_min_bps, direction, values_line) + print("TCP Downstream:",tcp_ds,"Mbps") + tput_data.append("TCP Downstream: " + str(tcp_ds)) + except: + tcp_ds = "error" + print("TCP Downstream Test Error") + tput_data.append("TCP Downstream: Error") + + ####### Setup TCP Profile and Run Traffic Upstream (STA to AP) ####################### + #singleClient.setup() + side_a_min_bps = 500000000 + side_b_min_bps = 0 + direction = "Upstream" + values_line = 3 # 3 = AP Rx + try: + tcp_us = eap_connect.tcp_unidirectional(side_a_min_bps, side_b_min_bps, direction, values_line) + print("TCP Upstream:",tcp_us,"Mbps") + tput_data.append("TCP Upstream: " + str(tcp_us)) + except: + tcp_us = "error" + print("TCP Upstream Test Error") + tput_data.append("TCP Uptream: Error") + + #Cleanup TCP Endpoints + #singleClient.cleanup_tcp() + + #Cleanup Endpoints + eap_connect.cleanup() + + return(tput_data) diff --git a/unit_tests/templates/ap_profile_template.json b/unit_tests/templates/ap_profile_template.json new file mode 100644 index 000000000..f4cc328c9 --- /dev/null +++ b/unit_tests/templates/ap_profile_template.json @@ -0,0 +1 @@ +{"model_type": "Profile", "id": 2, "customerId": 2, "profileType": "equipment_ap", "name": "Nightly_Sanity_ea8300_2020-12-13_vlan", "details": {"model_type": "ApNetworkConfiguration", "networkConfigVersion": "AP-1", "equipmentType": "AP", "vlanNative": true, "vlan": 0, "ntpServer": {"model_type": "AutoOrManualString", "auto": true, "value": null}, "syslogRelay": {"model_type": "SyslogRelay", "enabled": false, "srvHostIp": null, "srvHostPort": 514, "severity": "NOTICE"}, "rtlsSettings": {"model_type": "RtlsSettings", "enabled": false, "srvHostIp": null, "srvHostPort": 0}, "syntheticClientEnabled": false, "ledControlEnabled": true, "equipmentDiscovery": false, "greTunnelName": null, "greParentIfName": null, "greLocalInetAddr": null, "greRemoteInetAddr": null, "greRemoteMacAddr": null, "radioMap": {"is5GHz": {"model_type": "RadioProfileConfiguration", "bestApEnabled": true, "bestAPSteerType": "both"}, "is2dot4GHz": {"model_type": "RadioProfileConfiguration", "bestApEnabled": true, "bestAPSteerType": "both"}, "is5GHzU": {"model_type": "RadioProfileConfiguration", "bestApEnabled": true, "bestAPSteerType": "both"}, "is5GHzL": {"model_type": "RadioProfileConfiguration", "bestApEnabled": true, "bestAPSteerType": "both"}}, "profileType": "equipment_ap"}, "createdTimestamp": 1598524693438, "lastModifiedTimestamp": 1607377963675, "childProfileIds": [967, 968, 969, 970, 971, 972, 10, 129]} \ No newline at end of file diff --git a/unit_tests/templates/radius_profile_template.json b/unit_tests/templates/radius_profile_template.json new file mode 100644 index 000000000..a61228682 --- /dev/null +++ b/unit_tests/templates/radius_profile_template.json @@ -0,0 +1 @@ +{"model_type": "Profile", "id": 718, "customerId": 8, "profileType": "radius", "name": "Lab-RADIUS", "details": {"model_type": "RadiusProfile", "subnetConfiguration": {"Lab": {"model_type": "RadiusSubnetConfiguration", "subnetAddress": "10.10.0.0", "subnetCidrPrefix": 16, "subnetName": "Lab", "proxyConfig": {"model_type": "RadiusProxyConfiguration", "floatingIpAddress": null, "floatingIfCidrPrefix": null, "floatingIfGwAddress": null, "floatingIfVlan": null, "sharedSecret": null}, "probeInterval": null, "serviceRegionName": "Toronto"}}, "serviceRegionMap": {"Toronto": {"model_type": "RadiusServiceRegion", "serverMap": {"Lab-RADIUS": [{"model_type": "RadiusServer", "ipAddress": "10.10.10.203", "secret": "testing123", "authPort": 1812, "timeout": null}]}, "regionName": "Toronto"}}, "profileType": "radius", "serviceRegionName": "Toronto"}, "createdTimestamp": 1610045826067, "lastModifiedTimestamp": 1610045826067, "childProfileIds": []} \ No newline at end of file diff --git a/unit_tests/templates/ssid_profile_template.json b/unit_tests/templates/ssid_profile_template.json new file mode 100644 index 000000000..b83a5492c --- /dev/null +++ b/unit_tests/templates/ssid_profile_template.json @@ -0,0 +1 @@ +{"model_type": "Profile", "id": 28, "customerId": 2, "profileType": "ssid", "name": "ea8300_2G_WPA_VLAN_2020-12-13", "details": {"model_type": "SsidConfiguration", "ssid": "EA8300_2dot4G_WPA_VLAN", "appliedRadios": ["is2dot4GHz"], "ssidAdminState": "enabled", "secureMode": "wpaPSK", "vlanId": 100, "keyStr": "Connectus123$", "broadcastSsid": "enabled", "keyRefresh": 0, "noLocalSubnets": false, "radiusServiceName": "Radius-Accounting-Profile", "radiusAccountingServiceName": null, "radiusAcountingServiceInterval": null, "captivePortalId": null, "bandwidthLimitDown": 0, "bandwidthLimitUp": 0, "clientBandwidthLimitDown": 0, "clientBandwidthLimitUp": 0, "videoTrafficOnly": false, "radioBasedConfigs": {"is2dot4GHz": {"model_type": "RadioBasedSsidConfiguration", "enable80211r": null, "enable80211k": null, "enable80211v": null}, "is5GHz": {"model_type": "RadioBasedSsidConfiguration", "enable80211r": null, "enable80211k": null, "enable80211v": null}, "is5GHzU": {"model_type": "RadioBasedSsidConfiguration", "enable80211r": null, "enable80211k": null, "enable80211v": null}, "is5GHzL": {"model_type": "RadioBasedSsidConfiguration", "enable80211r": null, "enable80211k": null, "enable80211v": null}}, "bonjourGatewayProfileId": null, "enable80211w": null, "wepConfig": null, "forwardMode": "BRIDGE", "profileType": "ssid"}, "createdTimestamp": 1598557809816, "lastModifiedTimestamp": 1598557809816, "childProfileIds": []} \ No newline at end of file diff --git a/unit_tests/testrail_api.py b/unit_tests/testrail_api.py new file mode 100644 index 000000000..486356ec8 --- /dev/null +++ b/unit_tests/testrail_api.py @@ -0,0 +1,187 @@ +"""TestRail API binding for Python 3.x. + +""" + +#################################################################### +# Custom version of testrail_api module +# +# Used by Nightly_Sanity ########################################### +#################################################################### + +import base64 +import json + +import requests +from pprint import pprint +import os +tr_user=os.getenv('TR_USER') +tr_pw=os.getenv('TR_PWD') +project = os.getenv('PROJECT_ID') + + +class APIClient: + def __init__(self, base_url): + self.user = tr_user + self.password = tr_pw + if not base_url.endswith('/'): + base_url += '/' + self.__url = base_url + 'index.php?/api/v2/' + + + def send_get(self, uri, filepath=None): + """Issue a GET request (read) against the API. + + Args: + uri: The API method to call including parameters, e.g. get_case/1. + filepath: The path and file name for attachment download; used only + for 'get_attachment/:attachment_id'. + + Returns: + A dict containing the result of the request. + """ + return self.__send_request('GET', uri, filepath) + + def send_post(self, uri, data): + """Issue a POST request (write) against the API. + + Args: + uri: The API method to call, including parameters, e.g. add_case/1. + data: The data to submit as part of the request as a dict; strings + must be UTF-8 encoded. If adding an attachment, must be the + path to the file. + + Returns: + A dict containing the result of the request. + """ + return self.__send_request('POST', uri, data) + + def __send_request(self, method, uri, data): + url = self.__url + uri + + auth = str( + base64.b64encode( + bytes('%s:%s' % (self.user, self.password), 'utf-8') + ), + 'ascii' + ).strip() + headers = {'Authorization': 'Basic ' + auth} + #print("Method =" , method) + + if method == 'POST': + if uri[:14] == 'add_attachment': # add_attachment API method + files = {'attachment': (open(data, 'rb'))} + response = requests.post(url, headers=headers, files=files) + files['attachment'].close() + else: + headers['Content-Type'] = 'application/json' + payload = bytes(json.dumps(data), 'utf-8') + response = requests.post(url, headers=headers, data=payload) + else: + headers['Content-Type'] = 'application/json' + response = requests.get(url, headers=headers) + #print("headers = ", headers) + #print("resonse=", response) + #print("response code =", response.status_code) + + if response.status_code > 201: + + try: + error = response.json() + except: # response.content not formatted as JSON + error = str(response.content) + #raise APIError('TestRail API returned HTTP %s (%s)' % (response.status_code, error)) + print('TestRail API returned HTTP %s (%s)' % (response.status_code, error)) + return + else: + print(uri[:15]) + if uri[:15] == 'get_attachments': # Expecting file, not JSON + try: + print('opening file') + print (str(response.content)) + open(data, 'wb').write(response.content) + print('opened file') + return (data) + except: + return ("Error saving attachment.") + else: + + try: + return response.json() + except: # Nothing to return + return {} + + def get_project_id(self, project_name): + "Get the project ID using project name" + project_id = None + projects = client.send_get('get_projects') + ##pprint(projects) + for project in projects: + if project['name']== project_name: + project_id = project['id'] + # project_found_flag=True + break + print("project Id =",project_id) + return project_id + + def get_run_id(self, test_run_name): + "Get the run ID using test name and project name" + run_id = None + project_id = client.get_project_id(project_name=project) + + try: + test_runs = client.send_get('get_runs/%s' % (project_id)) + #print("------------TEST RUNS----------") + #pprint(test_runs) + + except Exception: + print + 'Exception in update_testrail() updating TestRail.' + return None + else: + for test_run in test_runs: + if test_run['name'] == test_run_name: + run_id = test_run['id'] + #print("run Id in Test Runs=",run_id) + break + return run_id + + + def update_testrail(self, case_id, run_id, status_id, msg): + "Update TestRail for a given run_id and case_id" + update_flag = False + # Get the TestRail client account details + # Update the result in TestRail using send_post function. + # Parameters for add_result_for_case is the combination of runid and case id. + # status_id is 1 for Passed, 2 For Blocked, 4 for Retest and 5 for Failed + #status_id = 1 if result_flag is True else 5 + + print("result status Pass/Fail = ", status_id) + print("case id=", case_id) + print("run id passed to update is ", run_id, case_id) + if run_id is not None: + try: + result = client.send_post( + 'add_result_for_case/%s/%s' % (run_id, case_id), + {'status_id': status_id, 'comment': msg}) + print("result in post",result) + except Exception: + print + 'Exception in update_testrail() updating TestRail.' + + else: + print + 'Updated test result for case: %s in test run: %s with msg:%s' % (case_id, run_id, msg) + + return update_flag + + def create_testrun(self, name, case_ids, project_id, milestone_id, description): + result = client.send_post( + 'add_run/%s' % (project_id), + {'name': name, 'case_ids': case_ids, 'milestone_id': milestone_id, 'description': description, 'include_all': False}) + print("result in post", result) + +client: APIClient = APIClient(os.getenv('TESTRAIL_URL')) + + +class APIError(Exception): + pass