- Modify CN deployment and termination functions to include namespace and path parameters. - Update `Module_UE` class with new attributes for namespace and CN path. - Integrate `cnID` for OC CN deployment and termination in `epc.py`. - Extract `cn_id` from XML configurations for CN operations. - Update XML files to include `cn_id` tag for 5G Core initialization and termination. (Used in OAIUE and AW2S pipeline, for OC CN deployment. This change will not affect other CN deployments.)
909 lines
35 KiB
Python
909 lines
35 KiB
Python
#/*
|
|
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
# * contributor license agreements. See the NOTICE file distributed with
|
|
# * this work for additional information regarding copyright ownership.
|
|
# * The OpenAirInterface Software Alliance licenses this file to You under
|
|
# * the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
# * except in compliance with the License.
|
|
# * You may obtain a copy of the License at
|
|
# *
|
|
# * http://www.openairinterface.org/?page_id=698
|
|
# *
|
|
# * Unless required by applicable law or agreed to in writing, software
|
|
# * distributed under the License is distributed on an "AS IS" BASIS,
|
|
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# * See the License for the specific language governing permissions and
|
|
# * limitations under the License.
|
|
# *-------------------------------------------------------------------------------
|
|
# * For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
# * contact@openairinterface.org
|
|
# */
|
|
#---------------------------------------------------------------------
|
|
# Python for CI of OAI-eNB + COTS-UE
|
|
#
|
|
# Required Python Version
|
|
# Python 3.x
|
|
#
|
|
# Required Python Package
|
|
# pexpect
|
|
#---------------------------------------------------------------------
|
|
|
|
|
|
|
|
#-----------------------------------------------------------
|
|
# Import Components
|
|
#-----------------------------------------------------------
|
|
|
|
import helpreadme as HELP
|
|
import constants as CONST
|
|
|
|
|
|
import cls_oaicitest #main class for OAI CI test framework
|
|
import cls_physim #class PhySim for physical simulators build and test
|
|
import cls_containerize #class Containerize for all container-based operations on RAN/UE objects
|
|
import cls_static_code_analysis #class for static code analysis
|
|
import cls_physim1 #class PhySim for physical simulators deploy and run
|
|
import cls_cluster # class for building/deploying on cluster
|
|
|
|
import sshconnection
|
|
import epc
|
|
import ran
|
|
import cls_oai_html
|
|
|
|
|
|
#-----------------------------------------------------------
|
|
# Import Libs
|
|
#-----------------------------------------------------------
|
|
import sys # arg
|
|
import re # reg
|
|
import pexpect # pexpect
|
|
import time # sleep
|
|
import os
|
|
import subprocess
|
|
import xml.etree.ElementTree as ET
|
|
import logging
|
|
import datetime
|
|
import signal
|
|
import subprocess
|
|
import traceback
|
|
from multiprocessing import Process, Lock, SimpleQueue
|
|
logging.basicConfig(
|
|
level=logging.DEBUG,
|
|
stream=sys.stdout,
|
|
format="[%(asctime)s] %(levelname)8s: %(message)s"
|
|
)
|
|
|
|
|
|
|
|
|
|
#-----------------------------------------------------------
|
|
# General Functions
|
|
#-----------------------------------------------------------
|
|
|
|
|
|
|
|
def CheckClassValidity(xml_class_list,action,id):
|
|
if action not in xml_class_list:
|
|
logging.error('test-case ' + id + ' has unlisted class ' + action + ' ##CHECK xml_class_list.yml')
|
|
resp=False
|
|
else:
|
|
resp=True
|
|
return resp
|
|
|
|
|
|
#assigning parameters to object instance attributes (even if the attributes do not exist !!)
|
|
def AssignParams(params_dict):
|
|
|
|
for key,value in params_dict.items():
|
|
setattr(CiTestObj, key, value)
|
|
setattr(RAN, key, value)
|
|
setattr(HTML, key, value)
|
|
setattr(ldpc, key, value)
|
|
|
|
|
|
|
|
def GetParametersFromXML(action):
|
|
if action == 'Build_eNB' or action == 'Build_Image' or action == 'Build_Proxy' or action == "Build_Cluster_Image" or action == "Build_Run_Tests":
|
|
RAN.Build_eNB_args=test.findtext('Build_eNB_args')
|
|
CONTAINERS.imageKind=test.findtext('kind')
|
|
forced_workspace_cleanup = test.findtext('forced_workspace_cleanup')
|
|
RAN.Build_eNB_forced_workspace_cleanup=False
|
|
CONTAINERS.forcedWorkspaceCleanup=False
|
|
CLUSTER.forcedWorkspaceCleanup = False
|
|
if forced_workspace_cleanup is not None and re.match('true', forced_workspace_cleanup, re.IGNORECASE):
|
|
RAN.Build_eNB_forced_workspace_cleanup = True
|
|
CONTAINERS.forcedWorkspaceCleanup = True
|
|
CLUSTER.forcedWorkspaceCleanup = True
|
|
eNB_instance=test.findtext('eNB_instance')
|
|
if (eNB_instance is None):
|
|
RAN.eNB_instance=0
|
|
CONTAINERS.eNB_instance=0
|
|
else:
|
|
RAN.eNB_instance=int(eNB_instance)
|
|
CONTAINERS.eNB_instance=int(eNB_instance)
|
|
eNB_serverId=test.findtext('eNB_serverId')
|
|
if (eNB_serverId is None):
|
|
RAN.eNB_serverId[RAN.eNB_instance]='0'
|
|
CONTAINERS.eNB_serverId[RAN.eNB_instance]='0'
|
|
else:
|
|
RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId
|
|
CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]=eNB_serverId
|
|
xmlBgBuildField = test.findtext('backgroundBuild')
|
|
if (xmlBgBuildField is None):
|
|
RAN.backgroundBuild=False
|
|
else:
|
|
if re.match('true', xmlBgBuildField, re.IGNORECASE):
|
|
RAN.backgroundBuild=True
|
|
else:
|
|
RAN.backgroundBuild=False
|
|
proxy_commit = test.findtext('proxy_commit')
|
|
if proxy_commit is not None:
|
|
CONTAINERS.proxyCommit = proxy_commit
|
|
|
|
elif action == 'WaitEndBuild_eNB':
|
|
RAN.Build_eNB_args=test.findtext('Build_eNB_args')
|
|
eNB_instance=test.findtext('eNB_instance')
|
|
if (eNB_instance is None):
|
|
RAN.eNB_instance=0
|
|
else:
|
|
RAN.eNB_instance=int(eNB_instance)
|
|
eNB_serverId=test.findtext('eNB_serverId')
|
|
if (eNB_serverId is None):
|
|
RAN.eNB_serverId[RAN.eNB_instance]='0'
|
|
else:
|
|
RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId
|
|
|
|
elif action == 'Initialize_eNB':
|
|
RAN.eNB_Trace=test.findtext('eNB_Trace')
|
|
RAN.eNB_Stats=test.findtext('eNB_Stats')
|
|
datalog_rt_stats_file=test.findtext('rt_stats_cfg')
|
|
if datalog_rt_stats_file is None:
|
|
RAN.datalog_rt_stats_file='datalog_rt_stats.default.yaml'
|
|
else:
|
|
RAN.datalog_rt_stats_file=datalog_rt_stats_file
|
|
RAN.Initialize_eNB_args=test.findtext('Initialize_eNB_args')
|
|
eNB_instance=test.findtext('eNB_instance')
|
|
USRPIPAddress=test.findtext('USRP_IPAddress')
|
|
if USRPIPAddress is None:
|
|
RAN.USRPIPAddress=''
|
|
else:
|
|
RAN.USRPIPAddress=USRPIPAddress
|
|
if (eNB_instance is None):
|
|
RAN.eNB_instance=0
|
|
else:
|
|
RAN.eNB_instance=int(eNB_instance)
|
|
eNB_serverId=test.findtext('eNB_serverId')
|
|
if (eNB_serverId is None):
|
|
RAN.eNB_serverId[RAN.eNB_instance]='0'
|
|
else:
|
|
RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId
|
|
|
|
#local variable air_interface
|
|
air_interface = test.findtext('air_interface')
|
|
if (air_interface is None) or (air_interface.lower() not in ['nr','lte']):
|
|
RAN.air_interface[RAN.eNB_instance] = 'lte-softmodem'
|
|
else:
|
|
RAN.air_interface[RAN.eNB_instance] = air_interface.lower() +'-softmodem'
|
|
|
|
cmd_prefix = test.findtext('cmd_prefix')
|
|
if cmd_prefix is not None: RAN.cmd_prefix = cmd_prefix
|
|
|
|
elif action == 'Terminate_eNB':
|
|
eNB_instance=test.findtext('eNB_instance')
|
|
if (eNB_instance is None):
|
|
RAN.eNB_instance=0
|
|
else:
|
|
RAN.eNB_instance=int(eNB_instance)
|
|
eNB_serverId=test.findtext('eNB_serverId')
|
|
if (eNB_serverId is None):
|
|
RAN.eNB_serverId[RAN.eNB_instance]='0'
|
|
else:
|
|
RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId
|
|
|
|
#retx checkers
|
|
string_field=test.findtext('d_retx_th')
|
|
if (string_field is not None):
|
|
RAN.ran_checkers['d_retx_th'] = [float(x) for x in string_field.split(',')]
|
|
string_field=test.findtext('u_retx_th')
|
|
if (string_field is not None):
|
|
RAN.ran_checkers['u_retx_th'] = [float(x) for x in string_field.split(',')]
|
|
|
|
#local variable air_interface
|
|
air_interface = test.findtext('air_interface')
|
|
if (air_interface is None) or (air_interface.lower() not in ['nr','lte']):
|
|
RAN.air_interface[RAN.eNB_instance] = 'lte-softmodem'
|
|
else:
|
|
RAN.air_interface[RAN.eNB_instance] = air_interface.lower() +'-softmodem'
|
|
|
|
elif action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Terminate_UE' or action == 'CheckStatusUE' or action == 'DataEnable_UE' or action == 'DataDisable_UE':
|
|
CiTestObj.ue_ids = test.findtext('id').split(' ')
|
|
|
|
elif action == 'Build_OAI_UE':
|
|
CiTestObj.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args')
|
|
CiTestObj.clean_repository = test.findtext('clean_repository')
|
|
if (CiTestObj.clean_repository == 'false'):
|
|
CiTestObj.clean_repository = False
|
|
else:
|
|
CiTestObj.clean_repository = True
|
|
|
|
elif action == 'Initialize_OAI_UE':
|
|
CiTestObj.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args')
|
|
UE_instance = test.findtext('UE_instance')
|
|
if (UE_instance is None):
|
|
CiTestObj.UE_instance = 0
|
|
else:
|
|
CiTestObj.UE_instance = UE_instance
|
|
|
|
#local variable air_interface
|
|
air_interface = test.findtext('air_interface')
|
|
if (air_interface is None) or (air_interface.lower() not in ['nr','lte']):
|
|
CiTestObj.air_interface = 'lte-uesoftmodem'
|
|
elif (air_interface.lower() in ['nr','lte']):
|
|
CiTestObj.air_interface = air_interface.lower() +'-uesoftmodem'
|
|
else :
|
|
logging.error('OCP UE -- NOT SUPPORTED')
|
|
|
|
CiTestObj.cmd_prefix = test.findtext('cmd_prefix') or ""
|
|
|
|
elif action == 'Terminate_OAI_UE':
|
|
UE_instance=test.findtext('UE_instance')
|
|
if (UE_instance is None):
|
|
CiTestObj.UE_instance = '0'
|
|
else:
|
|
CiTestObj.UE_instance = int(UE_instance)
|
|
|
|
#local variable air_interface
|
|
air_interface = test.findtext('air_interface')
|
|
if (air_interface is None) or (air_interface.lower() not in ['nr','lte']):
|
|
CiTestObj.air_interface = 'lte-uesoftmodem'
|
|
else:
|
|
CiTestObj.air_interface = air_interface.lower() +'-uesoftmodem'
|
|
|
|
elif action == 'Ping':
|
|
CiTestObj.ping_args = test.findtext('ping_args')
|
|
CiTestObj.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold')
|
|
CiTestObj.ue_ids = test.findtext('id').split(' ')
|
|
ping_rttavg_threshold = test.findtext('ping_rttavg_threshold') or ''
|
|
|
|
elif action == 'Iperf':
|
|
CiTestObj.iperf_args = test.findtext('iperf_args')
|
|
CiTestObj.ue_ids = test.findtext('id').split(' ')
|
|
CiTestObj.svr_id = test.findtext('svr_id') or None
|
|
CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold')
|
|
CiTestObj.iperf_bitrate_threshold = test.findtext('iperf_bitrate_threshold') or '90'
|
|
CiTestObj.iperf_profile = test.findtext('iperf_profile') or 'balanced'
|
|
CiTestObj.iperf_tcp_rate_target = test.findtext('iperf_tcp_rate_target') or None
|
|
if CiTestObj.iperf_profile != 'balanced' and CiTestObj.iperf_profile != 'unbalanced' and CiTestObj.iperf_profile != 'single-ue':
|
|
logging.error(f'test-case has wrong profile {CiTestObj.iperf_profile}, forcing balanced')
|
|
CiTestObj.iperf_profile = 'balanced'
|
|
CiTestObj.iperf_options = test.findtext('iperf_options') or 'check'
|
|
if CiTestObj.iperf_options != 'check' and CiTestObj.iperf_options != 'sink':
|
|
logging.error('test-case has wrong option ' + CiTestObj.iperf_options)
|
|
CiTestObj.iperf_options = 'check'
|
|
|
|
elif action == 'IdleSleep':
|
|
string_field = test.findtext('idle_sleep_time_in_sec')
|
|
if (string_field is None):
|
|
CiTestObj.idle_sleep_time = 5
|
|
else:
|
|
CiTestObj.idle_sleep_time = int(string_field)
|
|
|
|
elif action == 'Perform_X2_Handover':
|
|
string_field = test.findtext('x2_ho_options')
|
|
if (string_field is None):
|
|
CiTestObj.x2_ho_options = 'network'
|
|
else:
|
|
if string_field != 'network':
|
|
logging.error('ERROR: test-case has wrong option ' + string_field)
|
|
CiTestObj.x2_ho_options = 'network'
|
|
else:
|
|
CiTestObj.x2_ho_options = string_field
|
|
|
|
elif action == 'Build_PhySim':
|
|
ldpc.buildargs = test.findtext('physim_build_args')
|
|
forced_workspace_cleanup = test.findtext('forced_workspace_cleanup')
|
|
if (forced_workspace_cleanup is None):
|
|
ldpc.forced_workspace_cleanup=False
|
|
else:
|
|
if re.match('true', forced_workspace_cleanup, re.IGNORECASE):
|
|
ldpc.forced_workspace_cleanup=True
|
|
else:
|
|
ldpc.forced_workspace_cleanup=False
|
|
|
|
elif action == 'Initialize_MME':
|
|
string_field = test.findtext('option')
|
|
if (string_field is not None):
|
|
EPC.mmeConfFile = string_field
|
|
|
|
elif action == 'Initialize_HSS' or action == 'Initialize_SPGW':
|
|
pass
|
|
elif action == 'Terminate_HSS' or action == 'Terminate_MME' or action == 'Terminate_SPGW':
|
|
pass
|
|
|
|
elif action == 'Deploy_EPC':
|
|
string_field = test.findtext('parameters')
|
|
if (string_field is not None):
|
|
EPC.yamlPath = string_field
|
|
|
|
elif action == 'Initialize_5GCN':
|
|
string_field = test.findtext('args')
|
|
if (string_field is not None):
|
|
EPC.cfgDeploy = string_field
|
|
EPC.cnID = test.findtext('cn_id')
|
|
|
|
elif action == 'Terminate_5GCN':
|
|
string_field = test.findtext('args')
|
|
if (string_field is not None):
|
|
EPC.cfgUnDeploy = string_field
|
|
EPC.cnID = test.findtext('cn_id')
|
|
|
|
elif action == 'Deploy_Object' or action == 'Undeploy_Object':
|
|
eNB_instance=test.findtext('eNB_instance')
|
|
if (eNB_instance is None):
|
|
CONTAINERS.eNB_instance=0
|
|
else:
|
|
CONTAINERS.eNB_instance=int(eNB_instance)
|
|
eNB_serverId=test.findtext('eNB_serverId')
|
|
if (eNB_serverId is None):
|
|
CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]='0'
|
|
else:
|
|
CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]=eNB_serverId
|
|
string_field = test.findtext('yaml_path')
|
|
if (string_field is not None):
|
|
CONTAINERS.yamlPath[CONTAINERS.eNB_instance] = string_field
|
|
string_field=test.findtext('d_retx_th')
|
|
if (string_field is not None):
|
|
CONTAINERS.ran_checkers['d_retx_th'] = [float(x) for x in string_field.split(',')]
|
|
string_field=test.findtext('u_retx_th')
|
|
if (string_field is not None):
|
|
CONTAINERS.ran_checkers['u_retx_th'] = [float(x) for x in string_field.split(',')]
|
|
string_field = test.findtext('services')
|
|
if string_field is not None:
|
|
CONTAINERS.services[CONTAINERS.eNB_instance] = string_field
|
|
|
|
elif action == 'DeployGenObject' or action == 'UndeployGenObject' or action == 'StatsFromGenObject':
|
|
string_field=test.findtext('yaml_path')
|
|
if (string_field is not None):
|
|
CONTAINERS.yamlPath[0] = string_field
|
|
string_field=test.findtext('services')
|
|
if (string_field is not None):
|
|
CONTAINERS.services[0] = string_field
|
|
string_field=test.findtext('nb_healthy')
|
|
if (string_field is not None):
|
|
CONTAINERS.nb_healthy[0] = int(string_field)
|
|
string_field=test.findtext('d_retx_th')
|
|
if (string_field is not None):
|
|
CONTAINERS.ran_checkers['d_retx_th'] = [float(x) for x in string_field.split(',')]
|
|
string_field=test.findtext('u_retx_th')
|
|
if (string_field is not None):
|
|
CONTAINERS.ran_checkers['u_retx_th'] = [float(x) for x in string_field.split(',')]
|
|
|
|
elif action == 'Run_CUDATest' or action == 'Run_NRulsimTest' or action == 'Run_T2Test':
|
|
ldpc.runargs = test.findtext('physim_run_args')
|
|
ldpc.runsim = test.findtext('physim_run')
|
|
ldpc.timethrs = test.findtext('physim_time_threshold')
|
|
|
|
elif action == 'LicenceAndFormattingCheck':
|
|
pass
|
|
|
|
elif action == 'Cppcheck_Analysis':
|
|
pass
|
|
|
|
elif action == 'Push_Local_Registry':
|
|
string_field = test.findtext('registry_svr_id')
|
|
if (string_field is not None):
|
|
CONTAINERS.registrySvrId = string_field
|
|
|
|
elif action == 'Pull_Local_Registry':
|
|
string_field = test.findtext('test_svr_id')
|
|
if (string_field is not None):
|
|
CONTAINERS.testSvrId = string_field
|
|
CONTAINERS.imageToPull.clear()
|
|
string_field = test.findtext('images_to_pull')
|
|
if (string_field is not None):
|
|
CONTAINERS.imageToPull = string_field.split()
|
|
|
|
elif action == 'Clean_Test_Server_Images':
|
|
string_field = test.findtext('test_svr_id')
|
|
if (string_field is not None):
|
|
CONTAINERS.testSvrId = string_field
|
|
elif action == 'Custom_Command':
|
|
RAN.node = test.findtext('node')
|
|
RAN.command = test.findtext('command')
|
|
RAN.command_fail = test.findtext('command_fail') in ['True', 'true', 'Yes', 'yes']
|
|
elif action == 'Pull_Cluster_Image':
|
|
string_field = test.findtext('images_to_pull')
|
|
if (string_field is not None):
|
|
CLUSTER.imageToPull = string_field.split()
|
|
string_field = test.findtext('test_svr_id')
|
|
if (string_field is not None):
|
|
CLUSTER.testSvrId = string_field
|
|
else:
|
|
logging.warning(f"unknown action {action} from option-parsing point-of-view")
|
|
|
|
|
|
#check if given test is in list
|
|
#it is in list if one of the strings in 'list' is at the beginning of 'test'
|
|
def test_in_list(test, list):
|
|
for check in list:
|
|
check=check.replace('+','')
|
|
if (test.startswith(check)):
|
|
return True
|
|
return False
|
|
|
|
def receive_signal(signum, frame):
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#-----------------------------------------------------------
|
|
# MAIN PART
|
|
#-----------------------------------------------------------
|
|
|
|
#loading xml action list from yaml
|
|
import yaml
|
|
xml_class_list_file='xml_class_list.yml'
|
|
if (os.path.isfile(xml_class_list_file)):
|
|
yaml_file=xml_class_list_file
|
|
elif (os.path.isfile('ci-scripts/'+xml_class_list_file)):
|
|
yaml_file='ci-scripts/'+xml_class_list_file
|
|
else:
|
|
logging.error("XML action list yaml file cannot be found")
|
|
sys.exit("XML action list yaml file cannot be found")
|
|
|
|
with open(yaml_file,'r') as f:
|
|
# The FullLoader parameter handles the conversion-$
|
|
#from YAML scalar values to Python dictionary format$
|
|
xml_class_list = yaml.load(f,Loader=yaml.FullLoader)
|
|
|
|
mode = ''
|
|
|
|
CiTestObj = cls_oaicitest.OaiCiTest()
|
|
|
|
SSH = sshconnection.SSHConnection()
|
|
EPC = epc.EPCManagement()
|
|
RAN = ran.RANManagement()
|
|
HTML = cls_oai_html.HTMLManagement()
|
|
CONTAINERS = cls_containerize.Containerize()
|
|
SCA = cls_static_code_analysis.StaticCodeAnalysis()
|
|
PHYSIM = cls_physim1.PhySim()
|
|
CLUSTER = cls_cluster.Cluster()
|
|
|
|
ldpc=cls_physim.PhySim() #create an instance for LDPC test using GPU or CPU build
|
|
|
|
|
|
#-----------------------------------------------------------
|
|
# Parsing Command Line Arguments
|
|
#-----------------------------------------------------------
|
|
|
|
import args_parse
|
|
py_param_file_present, py_params, mode = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP,SCA,PHYSIM,CLUSTER)
|
|
|
|
|
|
|
|
#-----------------------------------------------------------
|
|
# TEMPORARY params management (UNUSED)
|
|
#-----------------------------------------------------------
|
|
#temporary solution for testing:
|
|
if py_param_file_present == True:
|
|
AssignParams(py_params)
|
|
|
|
#-----------------------------------------------------------
|
|
# mode amd XML class (action) analysis
|
|
#-----------------------------------------------------------
|
|
cwd = os.getcwd()
|
|
|
|
if re.match('^TerminateeNB$', mode, re.IGNORECASE):
|
|
if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
if RAN.eNBIPAddress == 'none':
|
|
sys.exit(0)
|
|
RAN.eNB_instance=0
|
|
RAN.eNB_serverId[0]='0'
|
|
RAN.eNBSourceCodePath='/tmp/'
|
|
RAN.TerminateeNB(HTML, EPC)
|
|
elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE):
|
|
if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
signal.signal(signal.SIGUSR1, receive_signal)
|
|
CiTestObj.TerminateOAIUE(HTML,RAN,EPC,CONTAINERS)
|
|
elif re.match('^TerminateHSS$', mode, re.IGNORECASE):
|
|
if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
EPC.TerminateHSS(HTML)
|
|
elif re.match('^TerminateMME$', mode, re.IGNORECASE):
|
|
if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
EPC.TerminateMME(HTML)
|
|
elif re.match('^TerminateSPGW$', mode, re.IGNORECASE):
|
|
if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath== '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
EPC.TerminateSPGW(HTML)
|
|
elif re.match('^LogCollectBuild$', mode, re.IGNORECASE):
|
|
if (RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''):
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
if RAN.eNBIPAddress == 'none':
|
|
sys.exit(0)
|
|
CiTestObj.LogCollectBuild(RAN)
|
|
elif re.match('^LogCollecteNB$', mode, re.IGNORECASE):
|
|
if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
if RAN.eNBIPAddress == 'none':
|
|
cmd = 'zip -r enb.log.' + RAN.BuildId + '.zip cmake_targets/log'
|
|
logging.info(cmd)
|
|
zipStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=60)
|
|
sys.exit(0)
|
|
RAN.LogCollecteNB()
|
|
elif re.match('^LogCollectHSS$', mode, re.IGNORECASE):
|
|
if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
EPC.LogCollectHSS()
|
|
elif re.match('^LogCollectMME$', mode, re.IGNORECASE):
|
|
if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
EPC.LogCollectMME()
|
|
elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE):
|
|
if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
EPC.LogCollectSPGW()
|
|
elif re.match('^LogCollectPing$', mode, re.IGNORECASE):
|
|
if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
CiTestObj.LogCollectPing(EPC)
|
|
elif re.match('^LogCollectIperf$', mode, re.IGNORECASE):
|
|
if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
CiTestObj.LogCollectIperf(EPC)
|
|
elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE):
|
|
if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Insufficient Parameter')
|
|
CiTestObj.LogCollectOAIUE()
|
|
elif re.match('^InitiateHtml$', mode, re.IGNORECASE):
|
|
count = 0
|
|
foundCount = 0
|
|
while (count < HTML.nbTestXMLfiles):
|
|
#xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[count]
|
|
xml_test_file = sys.path[0] + "/" + CiTestObj.testXMLfiles[count]
|
|
if (os.path.isfile(xml_test_file)):
|
|
try:
|
|
xmlTree = ET.parse(xml_test_file)
|
|
except Exception as e:
|
|
print(f"Error: {e} while parsing file: {xml_test_file}.")
|
|
xmlRoot = xmlTree.getroot()
|
|
HTML.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count)))
|
|
HTML.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='test-tab-' + str(count)))
|
|
HTML.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign'))
|
|
foundCount += 1
|
|
count += 1
|
|
if foundCount != HTML.nbTestXMLfiles:
|
|
HTML.nbTestXMLfiles=foundCount
|
|
|
|
HTML.CreateHtmlHeader()
|
|
elif re.match('^FinalizeHtml$', mode, re.IGNORECASE):
|
|
logging.info('\u001B[1m----------------------------------------\u001B[0m')
|
|
logging.info('\u001B[1m Creating HTML footer \u001B[0m')
|
|
logging.info('\u001B[1m----------------------------------------\u001B[0m')
|
|
|
|
HTML.CreateHtmlFooter(CiTestObj.finalStatus)
|
|
elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE):
|
|
logging.info('\u001B[1m----------------------------------------\u001B[0m')
|
|
logging.info('\u001B[1m Starting Scenario: ' + CiTestObj.testXMLfiles[0] + '\u001B[0m')
|
|
logging.info('\u001B[1m----------------------------------------\u001B[0m')
|
|
if re.match('^TesteNB$', mode, re.IGNORECASE):
|
|
if RAN.eNBIPAddress == '' or RAN.ranRepository == '' or RAN.ranBranch == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '' or EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '' or EPC.Type == '':
|
|
HELP.EPCSrvHelp(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath, EPC.Type)
|
|
if RAN.ranRepository == '':
|
|
HELP.GitSrvHelp(RAN.ranRepository, RAN.ranBranch, RAN.ranCommitID, RAN.ranAllowMerge, RAN.ranTargetBranch)
|
|
if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '':
|
|
HELP.eNBSrvHelp(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath)
|
|
sys.exit('Insufficient Parameter')
|
|
else:
|
|
if CiTestObj.UEIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '':
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('UE: Insufficient Parameter')
|
|
|
|
#read test_case_list.xml file
|
|
# if no parameters for XML file, use default value
|
|
if (HTML.nbTestXMLfiles != 1):
|
|
xml_test_file = cwd + "/test_case_list.xml"
|
|
else:
|
|
xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[0]
|
|
|
|
xmlTree = ET.parse(xml_test_file)
|
|
xmlRoot = xmlTree.getroot()
|
|
|
|
exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='')
|
|
requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='')
|
|
if (HTML.nbTestXMLfiles == 1):
|
|
HTML.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0'))
|
|
HTML.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0'))
|
|
repeatCount = xmlRoot.findtext('repeatCount',default='1')
|
|
testStability = xmlRoot.findtext('TestUnstable',default='False')
|
|
CiTestObj.repeatCounts.append(int(repeatCount))
|
|
if testStability == 'True':
|
|
CiTestObj.testUnstable = True
|
|
HTML.testUnstable = True
|
|
CiTestObj.testMinStableId = xmlRoot.findtext('TestMinId',default='999999')
|
|
HTML.testMinStableId = CiTestObj.testMinStableId
|
|
logging.warning('Test is tagged as Unstable -- starting from TestID ' + str(CiTestObj.testMinStableId))
|
|
all_tests=xmlRoot.findall('testCase')
|
|
|
|
exclusion_tests=exclusion_tests.split()
|
|
requested_tests=requested_tests.split()
|
|
|
|
#check that exclusion tests are well formatted
|
|
#(6 digits or less than 6 digits followed by +)
|
|
for test in exclusion_tests:
|
|
if (not re.match('^[0-9]{6}$', test) and
|
|
not re.match('^[0-9]{1,5}\+$', test)):
|
|
logging.error('exclusion test is invalidly formatted: ' + test)
|
|
sys.exit(1)
|
|
else:
|
|
logging.info(test)
|
|
|
|
#check that requested tests are well formatted
|
|
#(6 digits or less than 6 digits followed by +)
|
|
#be verbose
|
|
for test in requested_tests:
|
|
if (re.match('^[0-9]{6}$', test) or
|
|
re.match('^[0-9]{1,5}\+$', test)):
|
|
logging.info('test group/case requested: ' + test)
|
|
else:
|
|
logging.error('requested test is invalidly formatted: ' + test)
|
|
sys.exit(1)
|
|
if (EPC.IPAddress != '') and (EPC.IPAddress != 'none'):
|
|
EPC.SetMmeIPAddress()
|
|
EPC.SetAmfIPAddress()
|
|
|
|
#get the list of tests to be done
|
|
todo_tests=[]
|
|
for test in requested_tests:
|
|
if (test_in_list(test, exclusion_tests)):
|
|
logging.info('test will be skipped: ' + test)
|
|
else:
|
|
#logging.info('test will be run: ' + test)
|
|
todo_tests.append(test)
|
|
|
|
signal.signal(signal.SIGUSR1, receive_signal)
|
|
|
|
HTML.CreateHtmlTabHeader()
|
|
|
|
# On CI bench w/ containers, we need to validate if IP routes are set
|
|
if EPC.IPAddress == '172.21.16.136':
|
|
CONTAINERS.CheckAndAddRoute('porcepix', EPC.IPAddress, EPC.UserName, EPC.Password)
|
|
if EPC.IPAddress == '172.21.16.137':
|
|
CONTAINERS.CheckAndAddRoute('nepes', EPC.IPAddress, EPC.UserName, EPC.Password)
|
|
if CONTAINERS.eNBIPAddress == '172.21.16.127':
|
|
CONTAINERS.CheckAndAddRoute('asterix', CONTAINERS.eNBIPAddress, CONTAINERS.eNBUserName, CONTAINERS.eNBPassword)
|
|
if CONTAINERS.eNB1IPAddress == '172.21.16.127':
|
|
CONTAINERS.CheckAndAddRoute('asterix', CONTAINERS.eNB1IPAddress, CONTAINERS.eNB1UserName, CONTAINERS.eNB1Password)
|
|
if CONTAINERS.eNBIPAddress == '172.21.16.128':
|
|
CONTAINERS.CheckAndAddRoute('obelix', CONTAINERS.eNBIPAddress, CONTAINERS.eNBUserName, CONTAINERS.eNBPassword)
|
|
if CONTAINERS.eNB1IPAddress == '172.21.16.128':
|
|
CONTAINERS.CheckAndAddRoute('obelix', CONTAINERS.eNB1IPAddress, CONTAINERS.eNB1UserName, CONTAINERS.eNB1Password)
|
|
if CONTAINERS.eNBIPAddress == '172.21.16.109' or CONTAINERS.eNBIPAddress == 'ofqot':
|
|
CONTAINERS.CheckAndAddRoute('ofqot', CONTAINERS.eNBIPAddress, CONTAINERS.eNBUserName, CONTAINERS.eNBPassword)
|
|
if CONTAINERS.eNBIPAddress == '172.21.16.137':
|
|
CONTAINERS.CheckAndAddRoute('nepes', CONTAINERS.eNBIPAddress, CONTAINERS.eNBUserName, CONTAINERS.eNBPassword)
|
|
if CONTAINERS.eNB1IPAddress == '172.21.16.137':
|
|
CONTAINERS.CheckAndAddRoute('nepes', CONTAINERS.eNB1IPAddress, CONTAINERS.eNB1UserName, CONTAINERS.eNB1Password)
|
|
|
|
CiTestObj.FailReportCnt = 0
|
|
RAN.prematureExit=True
|
|
HTML.startTime=int(round(time.time() * 1000))
|
|
while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.prematureExit:
|
|
RAN.prematureExit=False
|
|
# At every iteration of the retry loop, a separator will be added
|
|
# pass CiTestObj.FailReportCnt as parameter of HTML.CreateHtmlRetrySeparator
|
|
HTML.CreateHtmlRetrySeparator(CiTestObj.FailReportCnt)
|
|
for test_case_id in todo_tests:
|
|
if RAN.prematureExit:
|
|
break
|
|
for test in all_tests:
|
|
if RAN.prematureExit:
|
|
break
|
|
id = test.get('id')
|
|
if test_case_id != id:
|
|
continue
|
|
CiTestObj.testCase_id = id
|
|
HTML.testCase_id=CiTestObj.testCase_id
|
|
EPC.testCase_id=CiTestObj.testCase_id
|
|
CiTestObj.desc = test.findtext('desc')
|
|
HTML.desc=CiTestObj.desc
|
|
action = test.findtext('class')
|
|
if (CheckClassValidity(xml_class_list, action, id) == False):
|
|
continue
|
|
CiTestObj.ShowTestID()
|
|
GetParametersFromXML(action)
|
|
try:
|
|
if action == 'Build_eNB':
|
|
RAN.BuildeNB(HTML)
|
|
elif action == 'WaitEndBuild_eNB':
|
|
RAN.WaitBuildeNBisFinished(HTML)
|
|
elif action == 'Custom_Command':
|
|
RAN.CustomCommand(HTML)
|
|
if RAN.prematureExit:
|
|
CiTestObj.AutoTerminateeNB(HTML,RAN,EPC,CONTAINERS)
|
|
elif action == 'Initialize_eNB':
|
|
RAN.InitializeeNB(HTML, EPC)
|
|
if RAN.prematureExit:
|
|
CiTestObj.AutoTerminateeNB(HTML,RAN,EPC,CONTAINERS)
|
|
elif action == 'Terminate_eNB':
|
|
RAN.TerminateeNB(HTML, EPC)
|
|
elif action == 'Initialize_UE':
|
|
CiTestObj.InitializeUE(HTML)
|
|
elif action == 'Terminate_UE':
|
|
CiTestObj.TerminateUE(HTML)
|
|
elif action == 'Attach_UE':
|
|
CiTestObj.AttachUE(HTML, RAN, EPC, CONTAINERS)
|
|
elif action == 'Detach_UE':
|
|
CiTestObj.DetachUE(HTML)
|
|
elif action == 'DataDisable_UE':
|
|
CiTestObj.DataDisableUE(HTML)
|
|
elif action == 'DataEnable_UE':
|
|
CiTestObj.DataEnableUE(HTML)
|
|
elif action == 'CheckStatusUE':
|
|
CiTestObj.CheckStatusUE(HTML)
|
|
elif action == 'Build_OAI_UE':
|
|
CiTestObj.BuildOAIUE(HTML)
|
|
elif action == 'Initialize_OAI_UE':
|
|
CiTestObj.InitializeOAIUE(HTML,RAN,EPC,CONTAINERS)
|
|
elif action == 'Terminate_OAI_UE':
|
|
CiTestObj.TerminateOAIUE(HTML,RAN,EPC,CONTAINERS)
|
|
elif action == 'Ping':
|
|
CiTestObj.Ping(HTML,RAN,EPC,CONTAINERS)
|
|
elif action == 'Iperf':
|
|
CiTestObj.Iperf(HTML,RAN,EPC,CONTAINERS)
|
|
elif action == 'Initialize_HSS':
|
|
EPC.InitializeHSS(HTML)
|
|
elif action == 'Terminate_HSS':
|
|
EPC.TerminateHSS(HTML)
|
|
elif action == 'Initialize_MME':
|
|
EPC.InitializeMME(HTML)
|
|
elif action == 'Terminate_MME':
|
|
EPC.TerminateMME(HTML)
|
|
elif action == 'Initialize_SPGW':
|
|
EPC.InitializeSPGW(HTML)
|
|
elif action == 'Terminate_SPGW':
|
|
EPC.TerminateSPGW(HTML)
|
|
elif action == 'Initialize_5GCN':
|
|
EPC.Initialize5GCN(HTML)
|
|
elif action == 'Terminate_5GCN':
|
|
EPC.Terminate5GCN(HTML)
|
|
elif action == 'Deploy_EPC':
|
|
EPC.DeployEpc(HTML)
|
|
elif action == 'Undeploy_EPC':
|
|
EPC.UndeployEpc(HTML)
|
|
elif action == 'IdleSleep':
|
|
CiTestObj.IdleSleep(HTML)
|
|
elif action == 'Perform_X2_Handover':
|
|
CiTestObj.Perform_X2_Handover(HTML,RAN,EPC)
|
|
elif action == 'Build_PhySim':
|
|
HTML=ldpc.Build_PhySim(HTML,CONST)
|
|
if ldpc.exitStatus==1:
|
|
RAN.prematureExit = True
|
|
elif action == 'Run_CUDATest':
|
|
HTML=ldpc.Run_CUDATest(HTML,CONST,id)
|
|
if ldpc.exitStatus==1:
|
|
RAN.prematureExit = True
|
|
elif action == 'Run_T2Test':
|
|
HTML=ldpc.Run_T2Test(HTML,CONST,id)
|
|
if ldpc.exitStatus==1:
|
|
RAN.prematureExit = True
|
|
elif action == 'Run_NRulsimTest':
|
|
HTML=ldpc.Run_NRulsimTest(HTML,CONST,id)
|
|
if ldpc.exitStatus==1:
|
|
RAN.prematureExit = True
|
|
elif action == 'Pull_Cluster_Image':
|
|
if not CLUSTER.PullClusterImage(HTML,RAN):
|
|
RAN.prematureExit = True
|
|
elif action == 'Build_Cluster_Image':
|
|
if not CLUSTER.BuildClusterImage(HTML):
|
|
RAN.prematureExit = True
|
|
elif action == 'Build_Image':
|
|
success = CONTAINERS.BuildImage(HTML)
|
|
if not success:
|
|
RAN.prematureExit = True
|
|
elif action == 'Build_Run_Tests':
|
|
success = CONTAINERS.BuildRunTests(HTML)
|
|
if not success:
|
|
RAN.prematureExit = True
|
|
elif action == 'Build_Proxy':
|
|
success = CONTAINERS.BuildProxy(HTML)
|
|
if not success:
|
|
RAN.prematureExit = True
|
|
elif action == 'Push_Local_Registry':
|
|
success = CONTAINERS.Push_Image_to_Local_Registry(HTML)
|
|
if not success:
|
|
RAN.prematureExit = True
|
|
elif action == 'Pull_Local_Registry':
|
|
success = CONTAINERS.Pull_Image_from_Local_Registry(HTML)
|
|
if not success:
|
|
RAN.prematureExit = True
|
|
elif action == 'Clean_Test_Server_Images':
|
|
success = CONTAINERS.Clean_Test_Server_Images(HTML)
|
|
if not success:
|
|
RAN.prematureExit = True
|
|
elif action == 'Deploy_Object':
|
|
CONTAINERS.DeployObject(HTML, EPC)
|
|
if CONTAINERS.exitStatus==1:
|
|
CiTestObj.AutoTerminateeNB(HTML,RAN,EPC,CONTAINERS)
|
|
RAN.prematureExit = True
|
|
elif action == 'Undeploy_Object':
|
|
CONTAINERS.UndeployObject(HTML, RAN)
|
|
if CONTAINERS.exitStatus == 1:
|
|
CiTestObj.AutoTerminateeNB(HTML,RAN,EPC,CONTAINERS)
|
|
RAN.prematureExit = True
|
|
elif action == 'Cppcheck_Analysis':
|
|
SCA.CppCheckAnalysis(HTML)
|
|
elif action == 'LicenceAndFormattingCheck':
|
|
ret = SCA.LicenceAndFormattingCheck(HTML)
|
|
if ret != 0:
|
|
RAN.prematureExit = True
|
|
elif action == 'Deploy_Run_PhySim':
|
|
PHYSIM.Deploy_PhySim(HTML, RAN)
|
|
elif action == 'DeployGenObject':
|
|
CONTAINERS.DeployGenObject(HTML, RAN, CiTestObj)
|
|
if CONTAINERS.exitStatus==1:
|
|
RAN.prematureExit = True
|
|
elif action == 'UndeployGenObject':
|
|
CONTAINERS.UndeployGenObject(HTML, RAN, CiTestObj)
|
|
if CONTAINERS.exitStatus==1:
|
|
RAN.prematureExit = True
|
|
elif action == 'IperfFromContainer':
|
|
CONTAINERS.IperfFromContainer(HTML, RAN, CiTestObj)
|
|
if CONTAINERS.exitStatus==1:
|
|
RAN.prematureExit = True
|
|
elif action == 'StatsFromGenObject':
|
|
CONTAINERS.StatsFromGenObject(HTML)
|
|
elif action == 'Push_Images_To_Test_Servers':
|
|
logging.debug('To be implemented')
|
|
else:
|
|
sys.exit('Invalid class (action) from xml')
|
|
except Exception as e:
|
|
s = traceback.format_exc()
|
|
logging.error(f'while running CI, an exception occurred:\n{s}')
|
|
HTML.CreateHtmlTestRowQueue("N/A", 'KO', [f"CI test code encountered an exception:\n{s}"])
|
|
RAN.prematureExit = True
|
|
|
|
if RAN.prematureExit:
|
|
if CiTestObj.testCase_id == CiTestObj.testMinStableId:
|
|
logging.warning('Scenario has reached minimal stability point')
|
|
CiTestObj.testStabilityPointReached = True
|
|
HTML.testStabilityPointReached = True
|
|
CiTestObj.FailReportCnt += 1
|
|
if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.prematureExit:
|
|
logging.error('\u001B[1;37;41mScenario failed ' + str(CiTestObj.FailReportCnt) + ' time(s)\u001B[0m')
|
|
HTML.CreateHtmlTabFooter(False)
|
|
if CiTestObj.testUnstable and (CiTestObj.testStabilityPointReached or CiTestObj.testMinStableId == '999999'):
|
|
logging.warning('\u001B[1;30;43mScenario has reached minimal stability point -- Not a Failure\u001B[0m')
|
|
else:
|
|
sys.exit('Failed Scenario')
|
|
else:
|
|
logging.info('\u001B[1;37;42mScenario passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)\u001B[0m')
|
|
HTML.CreateHtmlTabFooter(True)
|
|
elif re.match('^LoadParams$', mode, re.IGNORECASE):
|
|
pass
|
|
else:
|
|
HELP.GenericHelp(CONST.Version)
|
|
sys.exit('Invalid mode')
|
|
sys.exit(0)
|