diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py index c1a13eb9bf..cbf4159da2 100644 --- a/ci-scripts/args_parse.py +++ b/ci-scripts/args_parse.py @@ -47,6 +47,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,CONTAINERS,HELP,SCA,PHYSIM,CLUSTER): py_param_file_present = False py_params={} + force_local = False while len(argvs) > 1: myArgv = argvs.pop(1) # 0th is this file's name @@ -54,6 +55,9 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,CONTAINERS,HELP,SCA,PHYSIM,CLUSTER): if re.match('^\-\-help$', myArgv, re.IGNORECASE): HELP.GenericHelp(CONST.Version) sys.exit(0) + if re.match('^\-\-local$', myArgv, re.IGNORECASE): + force_local = True + #--apply= as parameters file, to replace inline parameters elif re.match('^\-\-Apply=(.+)$', myArgv, re.IGNORECASE): @@ -271,4 +275,4 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,CONTAINERS,HELP,SCA,PHYSIM,CLUSTER): HELP.GenericHelp(CONST.Version) sys.exit('Invalid Parameter: ' + myArgv) - return py_param_file_present, py_params, mode + return py_param_file_present, py_params, mode, force_local diff --git a/ci-scripts/cls_cmd.py b/ci-scripts/cls_cmd.py index 8784b70831..b338a6938f 100644 --- a/ci-scripts/cls_cmd.py +++ b/ci-scripts/cls_cmd.py @@ -217,6 +217,8 @@ class RemoteCmd(Cmd): return client def _lookup_ssh_config(hostname): + if is_local(hostname): + raise ValueError("Using localhost as SSH target is not allowed: use LocalCmd instead.") ssh_config = paramiko.SSHConfig() user_config_file = os.path.expanduser("~/.ssh/config") if os.path.exists(user_config_file): diff --git a/ci-scripts/helpreadme.py b/ci-scripts/helpreadme.py index 9ecba905ac..e1640fc899 100644 --- a/ci-scripts/helpreadme.py +++ b/ci-scripts/helpreadme.py @@ -43,6 +43,8 @@ def GenericHelp(vers): print(' InitiateHtml, FinalizeHtml') print(' TerminateeNB, TerminateHSS, TerminateMME, TerminateSPGW') print(' LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf') + print(' --local Force local execution: rewrites the test xml script before running to always execute on localhost. Assumes') + print(' images are available locally, will not remove any images and will run inside the current repo directory') def GitSrvHelp(repository,branch,commit,mergeallow,targetbranch): print(' --ranRepository=[OAI RAN Repository URL] -- ' + repository) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index bba0f3f57f..7a625eaa7d 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -212,13 +212,17 @@ def ExecuteActionWithParam(action): 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(' ') - if test.findtext('nodes'): - CiTestObj.nodes = test.findtext('nodes').split(' ') - if len(CiTestObj.ue_ids) != len(CiTestObj.nodes): - logging.error('Number of Nodes are not equal to the total number of UEs') - sys.exit("Mismatch in number of Nodes and UIs") + if force_local: + # Change all execution targets to localhost + CiTestObj.nodes = ['localhost'] * len(CiTestObj.ue_ids) else: - CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) + if test.findtext('nodes'): + CiTestObj.nodes = test.findtext('nodes').split(' ') + if len(CiTestObj.ue_ids) != len(CiTestObj.nodes): + logging.error('Number of Nodes are not equal to the total number of UEs') + sys.exit("Mismatch in number of Nodes and UIs") + else: + CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) if action == 'Initialize_UE': success = CiTestObj.InitializeUE(HTML) elif action == 'Attach_UE': @@ -238,13 +242,17 @@ def ExecuteActionWithParam(action): CiTestObj.ping_args = test.findtext('ping_args') CiTestObj.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') CiTestObj.ue_ids = test.findtext('id').split(' ') - if test.findtext('nodes'): - CiTestObj.nodes = test.findtext('nodes').split(' ') - if len(CiTestObj.ue_ids) != len(CiTestObj.nodes): - logging.error('Number of Nodes are not equal to the total number of UEs') - sys.exit("Mismatch in number of Nodes and UIs") + if force_local: + # Change all execution targets to localhost + CiTestObj.nodes = ['localhost'] * len(CiTestObj.ue_ids) else: - CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) + if test.findtext('nodes'): + CiTestObj.nodes = test.findtext('nodes').split(' ') + if len(CiTestObj.ue_ids) != len(CiTestObj.nodes): + logging.error('Number of Nodes are not equal to the total number of UEs') + sys.exit("Mismatch in number of Nodes and UIs") + else: + CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) ping_rttavg_threshold = test.findtext('ping_rttavg_threshold') or '' success = CiTestObj.Ping(HTML,EPC,CONTAINERS) @@ -252,15 +260,19 @@ def ExecuteActionWithParam(action): CiTestObj.iperf_args = test.findtext('iperf_args') CiTestObj.ue_ids = test.findtext('id').split(' ') CiTestObj.svr_id = test.findtext('svr_id') or None - if test.findtext('nodes'): - CiTestObj.nodes = test.findtext('nodes').split(' ') - if len(CiTestObj.ue_ids) != len(CiTestObj.nodes): - logging.error('Number of Nodes are not equal to the total number of UEs') - sys.exit("Mismatch in number of Nodes and UIs") + if force_local: + # Change all execution targets to localhost + CiTestObj.nodes = ['localhost'] * len(CiTestObj.ue_ids) else: - CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) + if test.findtext('nodes'): + CiTestObj.nodes = test.findtext('nodes').split(' ') + if len(CiTestObj.ue_ids) != len(CiTestObj.nodes): + logging.error('Number of Nodes are not equal to the total number of UEs') + sys.exit("Mismatch in number of Nodes and UIs") + else: + CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) if test.findtext('svr_node'): - CiTestObj.svr_node = test.findtext('svr_node') + CiTestObj.svr_node = test.findtext('svr_node') if not force_local else 'localhost' 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' @@ -356,6 +368,9 @@ def ExecuteActionWithParam(action): elif action == 'Undeploy_Object': success = CONTAINERS.UndeployObject(HTML, RAN) elif action == 'Create_Workspace': + if force_local: + # Do not create a working directory when running locally. Current repo directory will be used + return True success = CONTAINERS.Create_Workspace(HTML) elif action == 'Run_Physim': @@ -375,6 +390,9 @@ def ExecuteActionWithParam(action): success = CONTAINERS.Push_Image_to_Local_Registry(HTML, svr_id) elif action == 'Pull_Local_Registry' or action == 'Clean_Test_Server_Images': + if force_local: + # Do not pull or remove images when running locally. User is supposed to handle image creation & cleanup + return True svr_id = test.findtext('svr_id') images = test.findtext('images').split() # hack: for FlexRIC, we need to overwrite the tag to use @@ -463,7 +481,9 @@ CLUSTER = cls_cluster.Cluster() #----------------------------------------------------------- import args_parse -py_param_file_present, py_params, mode = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,CONTAINERS,HELP,SCA,PHYSIM,CLUSTER) +# Force local execution, move all execution targets to localhost +force_local = False +py_param_file_present, py_params, mode, force_local = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,CONTAINERS,HELP,SCA,PHYSIM,CLUSTER) diff --git a/ci-scripts/run_locally.sh b/ci-scripts/run_locally.sh new file mode 100755 index 0000000000..c8e9a289f0 --- /dev/null +++ b/ci-scripts/run_locally.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -e +SHORT_COMMIT_SHA=$(git rev-parse --short=8 HEAD) +COMMIT_SHA=$(git rev-parse HEAD) +CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) +REPO_PATH=$(dirname $(realpath $0))/../ +TESTCASE=$1 + +if [ $# -eq 0 ] + then + echo "Provide a testcase as an argument" + exit 1 +fi + +# The script assumes you've build the following images: +# +# docker build . -f docker/Dockerfile.gNB.ubuntu22 -t oai-gnb +# docker build . -f docker/Dockerfile.nrUE.ubuntu22 -t oai-nr-ue +# +# The images above depend on the following images: +# +# docker build . -f docker/Dockerfile.build.ubuntu22 -t ran-build +# dokcer build . -f docker/Dockerfile.base.ubuntu22 -t ran-base + +docker tag oai-nr-ue oai-ci/oai-nr-ue:develop-${SHORT_COMMIT_SHA} +docker tag oai-gnb oai-ci/oai-gnb:develop-${SHORT_COMMIT_SHA} + +python3 main.py --mode=TesteNB --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \ + --ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \ + --ranTargetBranch=NONE --eNBIPAddress=NONE --eNBUserName=NONE --eNBPassword=NONE \ + --eNBSourceCodePath=NONE --EPCIPAddress=NONE --EPCType=OAI --eNBPassword=NONE \ + --eNBSourceCodePath=${REPO_PATH} --EPCIPAddress=NONE \ + --EPCUserName=NONE --EPCPassword=NONE --EPCSourceCodePath=NONE \ + --XMLTestFile=xml_files/${TESTCASE} --local