diff --git a/CMakeLists.txt b/CMakeLists.txt index 116b8a55d2..7da5bbc5e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,29 +140,6 @@ set (OPENAIR_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}) project (OpenAirInterface) -############################################## -# Base CUDA setting -############################################## -find_package(CUDA) -if (CUDA_FOUND) - message ("cuda include ${CUDA_INCLUDE_DIRS}") - message ("cuda library ${CUDA_LIBRARY_DIRS}") - - add_definitions("-L/usr/local/cuda/lib64") - - SET(CUDA_NVCC_FLAGS - "${CUDA_NVCC_FLAGS};-arch=sm_60;") - - # Disable warnings for CUDA - SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-lpthread;-w;-O3;--default-stream;per-thread;-I/usr/local/cuda/inc;-L/usr/local/cuda/lib -lcutil;-rdc=true;-lcudadevrt") - SET(CUDA_VERBOSE_BUILD ON) - - SET(CUDA_SEPARABLE_COMPILATION ON) - -else (CUDA_FOUND) - message ("No CUDA tool installed") -endif () - #################################################### # compilation flags ############################################# @@ -618,26 +595,19 @@ target_link_libraries(benetel_5g PRIVATE asn1_nr_rrc asn1_lte_rrc) # LDPC offload library ########################################################## -# there is no generic way to test for T1 Offload, it simply comes with the -# shared object -if (EXISTS "/usr/local/lib64/librte_pmd_hpac_sdfec_pmd.so") - set(T1_OFFLOAD_FOUND TRUE) -else() - set(T1_OFFLOAD_FOUND FALSE) +add_boolean_option(ENABLE_LDPC_T1 OFF "Build support for LDPC Offload to T1 library") +if (ENABLE_LDPC_T1) + pkg_check_modules(LIBDPDK_T1 REQUIRED libdpdk=20.05.0) + find_library(T1 NAMES rte_pmd_hpac_sdfec_pmd REQUIRED) + if (NOT T1) + message(FATAL_ERROR "Library rte_pmd_hpac_sdfec_pmd for T1 offload not found") + endif() + add_library(ldpc_t1 MODULE ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c) + set_target_properties(ldpc_t1 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API") + target_compile_options(ldpc_t1 PRIVATE ${LIBDPDK_T1_CFLAGS}) + target_link_libraries(ldpc_t1 ${LIBDPDK_T1_LDFLAGS} ${T1}) endif() -if(T1_OFFLOAD_FOUND) - message(STATUS "T1 Offload support detected") - set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib64/pkgconfig/") - pkg_search_module(LIBDPDK REQUIRED libdpdk=20.05.0) - add_library(ldpc_offload MODULE ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c) - set_target_properties(ldpc_offload PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API") - target_compile_options(ldpc_offload PRIVATE ${LIBDPDK_CFLAGS}) - target_link_libraries(ldpc_offload ${LIBDPDK_LDFLAGS} rte_pmd_hpac_sdfec_pmd "-Wl,-rpath /usr/local/lib64") -else() - message(STATUS "No T1 Offload support detected") -endif () - ########################################################## include_directories ("${OPENAIR_DIR}/radio/COMMON") @@ -1033,16 +1003,26 @@ add_library(ldpc_cl MODULE ${PHY_LDPC_CL_SRC} ) target_link_libraries(ldpc_cl OpenCL) add_dependencies(ldpc_cl nrLDPC_decoder_kernels_CL) -if (CUDA_FOUND) - cuda_add_library(ldpc_cuda MODULE ${PHY_LDPC_CUDA_SRC} ) + +############################################## +# Base CUDA setting +############################################## + +add_boolean_option(BUILD_CUDA False "Build support for CUDA") +if (ENABLE_LDPC_CUDA) + find_package(CUDA REQUIRED) + SET(CUDA_NVCC_FLAG "${CUDA_NVCC_FLAGS};-arch=sm_60;") + SET(CUDA_VERBOSE_BUILD ON) + cuda_add_library(ldpc_cuda MODULE ${PHY_LDPC_CUDA_SRC}) set_target_properties(ldpc_cuda PROPERTIES CUDA_SEPARABLE_COMPILATION ON) -# CUDA_ADD_CUFFT_TO_TARGET(ldpc_cuda) -endif (CUDA_FOUND) + if (NOT CUDA_FOUND) + message(FATAL_ERROR "no CUDA found") + endif() +endif() add_library(ldpc MODULE ${PHY_LDPC_OPTIM8SEGMULTI_SRC} ) target_link_libraries(ldpc PRIVATE ldpc_gen_HEADERS) - add_library(coding MODULE ${PHY_TURBOSRC} ) target_link_libraries(coding PRIVATE asn1_nr_rrc asn1_lte_rrc) @@ -2384,11 +2364,11 @@ target_link_libraries(nr-softmodem PRIVATE ${LIB_LMS_LIBRARIES}) target_link_libraries(nr-softmodem PRIVATE ${T_LIB}) target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc asn1_lte_rrc) -add_dependencies( nr-softmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc) +add_dependencies(nr-softmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc) -if(T1_OFFLOAD_FOUND) -add_dependencies( nr-softmodem ldpc_offload) -endif () +if (ENABLE_LDPC_T1) + add_dependencies(nr-softmodem ldpc_t1) +endif() # force the generation of ASN.1 so that we don't need to wait during the build target_link_libraries(nr-softmodem PRIVATE @@ -2451,10 +2431,10 @@ target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB}) target_link_libraries(nr-uesoftmodem PRIVATE asn1_nr_rrc asn1_lte_rrc) add_dependencies( nr-uesoftmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc ) -if (CUDA_FOUND) - add_dependencies( nr-uesoftmodem ldpc_cuda) - add_dependencies( nr-softmodem ldpc_cuda) -endif (CUDA_FOUND) +if (ENABLE_LDPC_CUDA) + add_dependencies(nr-uesoftmodem ldpc_cuda) + add_dependencies(nr-softmodem ldpc_cuda) +endif() # force the generation of ASN.1 so that we don't need to wait during the build target_link_libraries(nr-uesoftmodem PRIVATE @@ -2523,9 +2503,9 @@ add_executable(ldpctest ) add_dependencies( ldpctest ldpc_orig ldpc_optim ldpc_optim8seg ldpc ) -if (CUDA_FOUND) - add_dependencies( ldpctest ldpc_cuda) -endif (CUDA_FOUND) +if (ENABLE_LDPC_CUDA) + add_dependencies(ldpctest ldpc_cuda) +endif() target_link_libraries(ldpctest PRIVATE -Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON CONFIG_LIB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} dl @@ -2634,9 +2614,9 @@ add_executable(nr_ulsim ${SHLIB_LOADER_SOURCES} ) -if(T1_OFFLOAD_FOUND) -add_dependencies( nr_ulsim ldpc_offload) -endif () +if (ENABLE_LDPC_T1) + add_dependencies(nr_ulsim ldpc_t1) +endif() target_link_libraries(nr_ulsim PRIVATE -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON lte_rrc nr_rrc CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE x2ap SECU_CN ngap NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB -lz -Wl,--end-group diff --git a/ci-scripts/Jenkinsfile-push-registry b/ci-scripts/Jenkinsfile-push-registry index 273b3876be..d05c167f6f 100644 --- a/ci-scripts/Jenkinsfile-push-registry +++ b/ci-scripts/Jenkinsfile-push-registry @@ -77,7 +77,7 @@ pipeline { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.DH_Credentials}", usernameVariable: 'DH_Username', passwordVariable: 'DH_Password'] ]) { - def listOfImages = ["oai-enb", "oai-gnb", "oai-lte-ue", "oai-nr-ue"] + def listOfImages = ["oai-enb", "oai-gnb", "oai-lte-ue", "oai-nr-ue", "oai-nr-cuup"] // Logging in on both registries sh "docker login -u ${DH_Username} -p ${DH_Password} > /dev/null 2>&1" sh "docker login -u oaicicd -p oaicicd porcepix.sboai.cs.eurecom.fr > /dev/null 2>&1" diff --git a/ci-scripts/cls_cmd.py b/ci-scripts/cls_cmd.py index 12eb75e7da..8694502fe2 100644 --- a/ci-scripts/cls_cmd.py +++ b/ci-scripts/cls_cmd.py @@ -74,23 +74,22 @@ class Cmd(metaclass=abc.ABCMeta): class LocalCmd(Cmd): def __init__(self, d = None): self.cwd = d + if self.cwd is not None: + logging.debug(f'Working dir is {self.cwd}') self.cp = sp.CompletedProcess(args='', returncode=0, stdout='') def run(self, line, timeout=300, silent=False, reportNonZero=True): - if type(line) is str: - line = [s for s in line.split(' ') if len(s) > 0] if not silent: - logging.debug(' '.join(line)) + logging.info(line) try: - ret = sp.run(line, cwd=self.cwd, stdout=sp.PIPE, stderr=sp.STDOUT, timeout=timeout) + ret = sp.run(line, shell=True, cwd=self.cwd, stdout=sp.PIPE, stderr=sp.STDOUT, timeout=timeout) except Exception as e: ret = sp.CompletedProcess(args=line, returncode=255, stdout=f'Exception: {str(e)}'.encode('utf-8')) if ret.stdout is None: ret.stdout = b'' ret.stdout = ret.stdout.decode('utf-8').strip() if reportNonZero and ret.returncode != 0: - cmd = ' '.join(ret.args) - logging.warning(f'command "{cmd}" returned non-zero returncode {ret.returncode}: output:\n{ret.stdout}') + logging.warning(f'command "{ret.args}" returned non-zero returncode {ret.returncode}: output:\n{ret.stdout}') self.cp = ret return ret diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 324e718ba1..b1b147b145 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -38,6 +38,9 @@ import os import shutil import subprocess import time +import pyshark +import threading +import cls_cmd from multiprocessing import Process, Lock, SimpleQueue from zipfile import ZipFile @@ -62,7 +65,8 @@ def CreateWorkspace(sshSession, sourcePath, ranRepository, ranCommitID, ranTarge sshSession.command('mkdir -p ' + sourcePath, '\$', 5) sshSession.command('cd ' + sourcePath, '\$', 5) # Recent version of git (>2.20?) should handle missing .git extension # without problems - sshSession.command(f'git clone --filter=blob:none -n -b develop {ranRepository} .', '\$', 60) + baseBranch = re.sub('origin/', '', ranTargetBranch) + sshSession.command(f'git clone --filter=blob:none -n -b {baseBranch} {ranRepository} .', '\$', 60) if sshSession.getBefore().count('error') > 0 or sshSession.getBefore().count('error') > 0: sys.exit('error during clone') sshSession.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) @@ -287,6 +291,7 @@ class Containerize(): self.deployedContainers = [] self.tsharkStarted = False + self.displayedNewTags = False self.pingContName = '' self.pingOptions = '' self.pingLossThreshold = '' @@ -345,7 +350,7 @@ class Containerize(): self.dockerfileprefix = '.rhel8.2' self.cliBuildOptions = '--no-cache --disable-compression' - # we always build the ran-build image with all targets + # we always build the ran-build image with all targets imageNames = [('ran-build', 'build')] result = re.search('eNB', self.imageKind) # Creating a tupple with the imageName and the DockerFile prefix pattern on obelix @@ -547,14 +552,17 @@ class Containerize(): oldRanCommidID = self.ranCommitID oldRanRepository = self.ranRepository oldRanAllowMerge = self.ranAllowMerge + oldRanTargetBranch = self.ranTargetBranch self.ranCommitID = self.proxyCommit self.ranRepository = 'https://github.com/EpiSci/oai-lte-5g-multi-ue-proxy.git' self.ranAllowMerge = False + self.ranTargetBranch = 'master' CreateWorkspace(mySSH, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge) # to prevent accidentally overwriting data that might be used later self.ranCommitID = oldRanCommidID self.ranRepository = oldRanRepository self.ranAllowMerge = oldRanAllowMerge + self.ranTargetBranch = oldRanTargetBranch # Let's remove any previous run artifacts if still there mySSH.command(self.cli + ' image prune --force', '\$', 30) @@ -571,6 +579,7 @@ class Containerize(): # Note: at this point, OAI images are flattened, but we cannot do this # here, as the flatten script is not in the proxy repo mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' proxy:' + tag, '\$', 5) + mySSH.command(self.cli + ' image prune --force || true','\$', 15) if mySSH.getBefore().count('o such image') != 0: logging.error('\u001B[1m Build of L2sim proxy failed\u001B[0m') mySSH.close() @@ -730,60 +739,42 @@ class Containerize(): sys.exit('Insufficient Parameter') if lIpAddr != 'none': logging.debug('Pulling images onto server: ' + lIpAddr) - mySSH = SSH.SSHConnection() - mySSH.open(lIpAddr, lUserName, lPassWord) + myCmd = cls_cmd.RemoteCmd(lIpAddr) else: logging.debug('Pulling images locally') + myCmd = cls_cmd.LocalCmd() cmd = 'docker login -u oaicicd -p oaicicd porcepix.sboai.cs.eurecom.fr' - if lIpAddr != 'none': - mySSH.command(cmd, '\$', 5) - response = mySSH.getBefore() - else: - logging.info(cmd) - response = subprocess.check_output(cmd, shell=True, universal_newlines=True, stderr=subprocess.STDOUT) - if re.search('Login Succeeded', response) is None: + response = myCmd.run(cmd) + if response.returncode != 0: msg = 'Could not log into local registry' logging.error(msg) - if lIpAddr != 'none': - mySSH.close() + myCmd.close() HTML.CreateHtmlTestRow(msg, 'KO', CONST.ALL_PROCESSES_OK) return False for image in self.imageToPull: tagToUse = self.ImageTagToUse(image) cmd = f'docker pull {tagToUse}' - if lIpAddr != 'none': - mySSH.command(cmd, '\$', 120) - response = mySSH.getBefore() - else: - logging.info(cmd) - response = subprocess.check_output(cmd, shell=True, universal_newlines=True) - if re.search('Status: Downloaded newer image for |Status: Image is up to date for', response) is None: + response = myCmd.run(cmd, timeout=120) + if response.returncode != 0: logging.debug(response) msg = f'Could not pull {image} from local registry : {tagToUse}' logging.error(msg) - if lIpAddr != 'none': - mySSH.close() + myCmd.close() HTML.CreateHtmlTestRow('msg', 'KO', CONST.ALL_PROCESSES_OK) return False cmd = 'docker logout porcepix.sboai.cs.eurecom.fr' - if lIpAddr != 'none': - mySSH.command(cmd, '\$', 5) - response = mySSH.getBefore() - else: - logging.info(cmd) - response = subprocess.check_output(cmd, shell=True, universal_newlines=True) - if re.search('Removing login credentials', response) is None: + response = myCmd.run(cmd) + if response.returncode != 0: msg = 'Could not log off from local registry' logging.error(msg) - mySSH.close() + myCmd.close() HTML.CreateHtmlTestRow(msg, 'KO', CONST.ALL_PROCESSES_OK) return False - if lIpAddr != 'none': - mySSH.close() + myCmd.close() HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) return True @@ -810,22 +801,17 @@ class Containerize(): sys.exit('Insufficient Parameter') if lIpAddr != 'none': logging.debug('Removing test images from server: ' + lIpAddr) - mySSH = SSH.SSHConnection() - mySSH.open(lIpAddr, lUserName, lPassWord) + myCmd = cls_cmd.RemoteCmd(lIpAddr) else: logging.debug('Removing test images locally') + myCmd = cls_cmd.LocalCmd() imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup'] for image in imageNames: - cmd = f'docker rmi {self.ImageTagToUse(image)} || true' - if lIpAddr != 'none': - mySSH.command(cmd, '\$', 5) - else: - logging.info(cmd) - subprocess.run(cmd, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + cmd = f'docker rmi {self.ImageTagToUse(image)}' + myCmd.run(cmd, reportNonZero=False) - if lIpAddr != 'none': - mySSH.close() + myCmd.close() HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) return True @@ -865,7 +851,6 @@ class Containerize(): mySSH.command('sed -i -e "s/CI_MME_IP_ADDR/' + localMmeIpAddr + '/" ci-docker-compose.yml', '\$', 2) # Currently support only one - mySSH.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 15) svcName = self.services[self.eNB_instance] if svcName == '': logging.warning('no service name given: starting all services in ci-docker-compose.yml!') @@ -922,7 +907,7 @@ class Containerize(): if healthyNb == 1: cnt = 0 while (cnt < 20): - mySSH.command('docker logs ' + containerName + ' | egrep --text --color=never -i "wait|sync|Starting"', '\$', 30) + mySSH.command('docker logs ' + containerName + ' | egrep --text --color=never -i "wait|sync|Starting"', '\$', 30) result = re.search('got sync|Starting F1AP at CU', mySSH.getBefore()) if result is None: time.sleep(6) @@ -1048,54 +1033,58 @@ class Containerize(): def DeployGenObject(self, HTML, RAN, UE): self.exitStatus = 0 logging.debug('\u001B[1m Checking Services to deploy\u001B[0m') - cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose config --services' - logging.info(cmd) - try: - listServices = subprocess.check_output(cmd, shell=True, universal_newlines=True) - except Exception as e: + # Implicitly we are running locally + myCmd = cls_cmd.LocalCmd(d = self.yamlPath[0]) + cmd = 'docker-compose config --services' + listServices = myCmd.run(cmd) + if listServices.returncode != 0: + myCmd.close() self.exitStatus = 1 HTML.CreateHtmlTestRow('SVC not Found', 'KO', CONST.ALL_PROCESSES_OK) return for reqSvc in self.services[0].split(' '): - res = re.search(reqSvc, listServices) + res = re.search(reqSvc, listServices.stdout) if res is None: logging.error(reqSvc + ' not found in specified docker-compose') self.exitStatus = 1 if (self.exitStatus == 1): + myCmd.close() HTML.CreateHtmlTestRow('SVC not Found', 'KO', CONST.ALL_PROCESSES_OK) return - cmd = 'cd ' + self.yamlPath[0] + ' && cp docker-compose.y*ml docker-compose-ci.yml' - subprocess.run(cmd, shell=True) + cmd = 'cp docker-compose.y*ml docker-compose-ci.yml' + myCmd.run(cmd, silent=self.displayedNewTags) imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup'] for image in imageNames: tagToUse = self.ImageTagToUse(image) - cmd = f'cd {self.yamlPath[0]} && sed -i -e "s@{image}:develop@{tagToUse}@" docker-compose-ci.yml' - logging.debug(cmd) - subprocess.run(cmd, shell=True) + cmd = f'sed -i -e "s@oaisoftwarealliance/{image}:develop@{tagToUse}@" docker-compose-ci.yml' + myCmd.run(cmd, silent=self.displayedNewTags) + self.displayedNewTags = True - cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml up -d ' + self.services[0] - logging.info(cmd) - try: - deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100) - except Exception as e: + cmd = f'docker-compose -f docker-compose-ci.yml up -d {self.services[0]}' + deployStatus = myCmd.run(cmd, timeout=100) + if deployStatus.returncode != 0: + myCmd.close() self.exitStatus = 1 logging.error('Could not deploy') HTML.CreateHtmlTestRow('Could not deploy', 'KO', CONST.ALL_PROCESSES_OK) return logging.debug('\u001B[1m Checking if all deployed healthy\u001B[0m') - cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml ps -a' + cmd = 'docker-compose -f docker-compose-ci.yml ps -a' count = 0 healthy = 0 + restarting = 0 newContainers = [] while (count < 10): count += 1 containerStatus = [] - deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30) + deployStatus = myCmd.run(cmd, 30, silent=True) healthy = 0 - for state in deployStatus.split('\n'): - res = re.search('Name|----------', state) + restarting = 0 + for state in deployStatus.stdout.split('\n'): + state = state.strip() + res = re.search('Name|NAME|----------', state) if res is not None: continue if len(state) == 0: @@ -1110,23 +1099,32 @@ class Containerize(): if not found: newContainers.append(cName) self.deployedContainers.append(cName) - if re.search('Up \(healthy\)', state) is not None: + if re.search('\(healthy\)', state) is not None: healthy += 1 - if re.search('rfsim4g-db-init.*Exit 0', state) is not None: - subprocess.check_output('docker rm -f rfsim4g-db-init || true', shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30) - containerStatus.append(state) - if healthy == self.nb_healthy[0]: + if re.search('rfsim4g-db-init.*Exit 0', state) is not None or re.search('rfsim4g-db-init.*Exited \(0\)', state) is not None: + myCmd.run('docker rm -f rfsim4g-db-init', timeout=30, silent=True, reportNonZero=False) + if re.search('l2sim4g-db-init.*Exit 0', state) is not None or re.search('l2sim4g-db-init.*Exited \(0\)', state) is not None: + myCmd.run('docker rm -f l2sim4g-db-init', timeout=30, silent=True, reportNonZero=False) + if re.search('Restarting', state) is None: + containerStatus.append(state) + else: + restarting += 1 + if healthy == self.nb_healthy[0] and restarting == 0: count = 100 else: time.sleep(10) imagesInfo = '' for newCont in newContainers: + if newCont == 'rfsim4g-db-init': + continue cmd = 'docker inspect -f "{{.Config.Image}}" ' + newCont - imageName = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30) - imageName = str(imageName).strip() + imageInspect = myCmd.run(cmd, timeout=30, silent=True) + imageName = str(imageInspect.stdout).strip() cmd = 'docker image inspect --format "{{.RepoTags}}\t{{.Size}} bytes\t{{.Created}}\t{{.Id}}" ' + imageName - imagesInfo += subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30) + imageInspect = myCmd.run(cmd, 30, silent=True) + imagesInfo += imageInspect.stdout.strip() + myCmd.close() html_queue = SimpleQueue() html_cell = '
\n'
@@ -1158,48 +1156,71 @@ class Containerize():
self.UndeployGenObject(HTML, RAN, UE)
self.exitStatus = 1
- def CaptureOnDockerNetworks(self):
- cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml config | grep com.docker.network.bridge.name | sed -e "s@^.*name: @@"'
- networkNames = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
+ # pyshark livecapture launches 2 processes:
+ # * One using dumpcap -i lIfs -w - (ie redirecting the packets to STDOUT)
+ # * One using tshark -i - -w loFile (ie capturing from STDIN from previous process)
+ # but in fact the packets are read by the following loop before being in fact
+ # really written to loFile.
+ # So it is mandatory to keep the loop
+ def LaunchPySharkCapture(self, lIfs, lFilter, loFile):
+ capture = pyshark.LiveCapture(interface=lIfs, bpf_filter=lFilter, output_file=loFile, debug=False)
+ for packet in capture.sniff_continuously():
+ pass
+ def CaptureOnDockerNetworks(self):
+ myCmd = cls_cmd.LocalCmd(d = self.yamlPath[0])
+ cmd = 'docker-compose -f docker-compose-ci.yml config | grep com.docker.network.bridge.name | sed -e "s@^.*name: @@"'
+ networkNames = myCmd.run(cmd, silent=True)
+ myCmd.close()
# Allow only: control plane RAN (SCTP), HTTP of control in CN (port 80), PFCP traffic (port 8805), MySQL (port 3306)
- cmd = 'sudo nohup tshark -f "sctp or port 80 or port 8805 or icmp or port 3306"'
- for name in networkNames.split('\n'):
+ capture_filter = 'sctp or port 80 or port 8805 or icmp or port 3306'
+ interfaces = []
+ iInterfaces = ''
+ for name in networkNames.stdout.split('\n'):
if re.search('rfsim', name) is not None or re.search('l2sim', name) is not None:
- cmd += ' -i ' + name
- cmd += ' -w /tmp/capture_'
+ interfaces.append(name)
+ iInterfaces += f'-i {name} '
ymlPath = self.yamlPath[0].split('/')
- cmd += ymlPath[1] + '.pcap > /tmp/tshark.log 2>&1 &'
- logging.info(cmd)
- networkNames = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
+ output_file = f'/tmp/capture_{ymlPath[1]}.pcap'
self.tsharkStarted = True
+ # On old systems (ubuntu 18), pyshark live-capture is buggy.
+ # Going back to old method
+ if sys.version_info < (3, 7):
+ cmd = f'nohup tshark -f "{capture_filter}" {iInterfaces} -w {output_file} > /tmp/tshark.log 2>&1 &'
+ myCmd = cls_cmd.LocalCmd()
+ myCmd.run(cmd, timeout=5, reportNonZero=False)
+ myCmd.close()
+ return
+ x = threading.Thread(target = self.LaunchPySharkCapture, args = (interfaces,capture_filter,output_file,))
+ x.daemon = True
+ x.start()
def UndeployGenObject(self, HTML, RAN, UE):
self.exitStatus = 0
+ # Implicitly we are running locally
ymlPath = self.yamlPath[0].split('/')
logPath = '../cmake_targets/log/' + ymlPath[1]
+ myCmd = cls_cmd.LocalCmd(d = self.yamlPath[0])
- cmd = 'cd ' + self.yamlPath[0] + ' && cp docker-compose.y*ml docker-compose-ci.yml'
- logging.info(cmd)
- subprocess.run(cmd, shell=True)
+ cmd = 'cp docker-compose.y*ml docker-compose-ci.yml'
+ myCmd.run(cmd, silent=self.displayedNewTags)
imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup']
for image in imageNames:
tagToUse = self.ImageTagToUse(image)
- cmd = f'cd {self.yamlPath[0]} && sed -i -e "s@{image}:develop@{tagToUse}@" docker-compose-ci.yml'
- subprocess.run(cmd, shell=True)
+ cmd = f'sed -i -e "s@oaisoftwarealliance/{image}:develop@{tagToUse}@" docker-compose-ci.yml'
+ myCmd.run(cmd, silent=self.displayedNewTags)
+ self.displayedNewTags = True
# check which containers are running for log recovery later
- cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml ps --all'
- logging.info(cmd)
- deployStatusLogs = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30)
+ cmd = 'docker-compose -f docker-compose-ci.yml ps --all'
+ deployStatusLogs = myCmd.run(cmd, timeout=30)
# Stop the containers to shut down objects
logging.debug('\u001B[1m Stopping containers \u001B[0m')
- cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml stop -t3'
- logging.info(cmd)
- try:
- deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100)
- except Exception as e:
+ cmd = 'docker-compose -f docker-compose-ci.yml stop -t3'
+ deployStatus = myCmd.run(cmd, timeout=100)
+ if deployStatus.returncode != 0:
+ myCmd.close()
self.exitStatus = 1
logging.error('Could not stop containers')
HTML.CreateHtmlTestRow('Could not stop', 'KO', CONST.ALL_PROCESSES_OK)
@@ -1207,8 +1228,12 @@ class Containerize():
return
anyLogs = False
- for state in deployStatusLogs.split('\n'):
- res = re.search('Name|----------', state)
+ logging.debug('Working dir is now . (ie ci-scripts)')
+ myCmd2 = cls_cmd.LocalCmd()
+ myCmd2.run(f'mkdir -p {logPath}')
+ myCmd2.cd(logPath)
+ for state in deployStatusLogs.stdout.split('\n'):
+ res = re.search('Name|NAME|----------', state)
if res is not None:
continue
if len(state) == 0:
@@ -1217,36 +1242,26 @@ class Containerize():
if res is not None:
anyLogs = True
cName = res.group('container_name')
- cmd = 'cd ' + self.yamlPath[0] + ' && docker logs ' + cName + ' > ' + cName + '.log 2>&1'
- logging.info(cmd)
- subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30)
+ cmd = f'docker logs {cName} > {cName}.log 2>&1'
+ myCmd2.run(cmd, timeout=30, reportNonZero=False)
if re.search('magma-mme', cName) is not None:
- cmd = 'cd ' + self.yamlPath[0] + ' && docker cp -L ' + cName + ':/var/log/mme.log ' + cName + '-full.log'
- logging.info(cmd)
- subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30)
+ cmd = f'docker cp -L {cName}:/var/log/mme.log {cName}-full.log'
+ myCmd2.run(cmd, timeout=30, reportNonZero=False)
fullStatus = True
if anyLogs:
- cmd = 'mkdir -p '+ logPath + ' && cp ' + self.yamlPath[0] + '/*.log ' + logPath
- logging.info(cmd)
- deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
-
# Analyzing log file(s)!
listOfPossibleRanContainers = ['enb', 'gnb', 'cu', 'du']
for container in listOfPossibleRanContainers:
- filenames = self.yamlPath[0] + '/*-oai-' + container + '.log'
- cmd = 'ls ' + filenames
- containerStatus = True
- try:
- lsStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
- filenames = str(lsStatus).strip()
- except:
- containerStatus = False
- if not containerStatus:
+ filenames = './*-oai-' + container + '.log'
+ cmd = f'ls {filenames}'
+ lsStatus = myCmd2.run(cmd, silent=True, reportNonZero=False)
+ if lsStatus.returncode != 0:
continue
+ filenames = str(lsStatus.stdout).strip()
for filename in filenames.split('\n'):
logging.debug('\u001B[1m Analyzing xNB logfile ' + filename + ' \u001B[0m')
- logStatus = RAN.AnalyzeLogFile_eNB(filename, HTML, self.ran_checkers)
+ logStatus = RAN.AnalyzeLogFile_eNB(f'{logPath}/{filename}', HTML, self.ran_checkers)
if (logStatus < 0):
fullStatus = False
self.exitStatus = 1
@@ -1256,49 +1271,42 @@ class Containerize():
listOfPossibleUeContainers = ['lte-ue*', 'nr-ue*']
for container in listOfPossibleUeContainers:
- filenames = self.yamlPath[0] + '/*-oai-' + container + '.log'
- cmd = 'ls ' + filenames
- containerStatus = True
- try:
- lsStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
- filenames = str(lsStatus).strip()
- except:
- containerStatus = False
- if not containerStatus:
+ filenames = './*-oai-' + container + '.log'
+ cmd = f'ls {filenames}'
+ lsStatus = myCmd2.run(cmd, silent=True, reportNonZero=False)
+ if lsStatus.returncode != 0:
continue
+ filenames = str(lsStatus.stdout).strip()
for filename in filenames.split('\n'):
logging.debug('\u001B[1m Analyzing UE logfile ' + filename + ' \u001B[0m')
- logStatus = UE.AnalyzeLogFile_UE(filename, HTML, RAN)
+ logStatus = UE.AnalyzeLogFile_UE(f'{logPath}/{filename}', HTML, RAN)
if (logStatus < 0):
fullStatus = False
HTML.CreateHtmlTestRow('UE log Analysis', 'KO', logStatus)
else:
HTML.CreateHtmlTestRow('UE log Analysis', 'OK', CONST.ALL_PROCESSES_OK)
- cmd = 'rm ' + self.yamlPath[0] + '/*.log'
- logging.info(cmd)
- deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
if self.tsharkStarted:
self.tsharkStarted = True
+ cmd = 'killall tshark'
+ myCmd2.run(cmd, reportNonZero=False)
+ cmd = 'killall dumpcap'
+ myCmd2.run(cmd, reportNonZero=False)
+ time.sleep(5)
ymlPath = self.yamlPath[0].split('/')
- cmd = 'sudo chmod 666 /tmp/capture_' + ymlPath[1] + '.pcap'
- logging.info(cmd)
- copyStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
- cmd = 'cp /tmp/capture_' + ymlPath[1] + '.pcap ' + logPath
- logging.info(cmd)
- copyStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
- cmd = 'sudo rm /tmp/capture_' + ymlPath[1] + '.pcap'
- logging.info(cmd)
- copyStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
+ # The working dir is still logPath
+ cmd = f'mv /tmp/capture_{ymlPath[1]}.pcap .'
+ myCmd2.run(cmd, timeout=100, reportNonZero=False)
self.tsharkStarted = False
+ myCmd2.close()
logging.debug('\u001B[1m Undeploying \u001B[0m')
- cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml down'
- logging.info(cmd)
- try:
- deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100)
- except Exception as e:
+ logging.debug(f'Working dir is back {self.yamlPath[0]}')
+ cmd = 'docker-compose -f docker-compose-ci.yml down'
+ deployStatus = myCmd.run(cmd, timeout=100)
+ if deployStatus.returncode != 0:
+ myCmd.close()
self.exitStatus = 1
logging.error('Could not undeploy')
HTML.CreateHtmlTestRow('Could not undeploy', 'KO', CONST.ALL_PROCESSES_OK)
@@ -1307,9 +1315,9 @@ class Containerize():
self.deployedContainers = []
# Cleaning any created tmp volume
- cmd = 'docker volume prune --force || true'
- logging.info(cmd)
- deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100)
+ cmd = 'docker volume prune --force'
+ deployStatus = myCmd.run(cmd, timeout=100, reportNonZero=False)
+ myCmd.close()
if fullStatus:
HTML.CreateHtmlTestRow('n/a', 'OK', CONST.ALL_PROCESSES_OK)
@@ -1324,13 +1332,13 @@ class Containerize():
logPath = '../cmake_targets/log/' + ymlPath[1]
# if the containers are running, recover the logs!
- cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml ps --all'
- logging.info(cmd)
- deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30)
+ myCmd = cls_cmd.LocalCmd(d = self.yamlPath[0])
+ cmd = 'docker-compose -f docker-compose-ci.yml ps --all'
+ deployStatus = myCmd.run(cmd, timeout=30)
cmd = 'docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}" '
anyLogs = False
- for state in deployStatus.split('\n'):
- res = re.search('Name|----------', state)
+ for state in deployStatus.stdout.split('\n'):
+ res = re.search('Name|NAME|----------', state)
if res is not None:
continue
if len(state) == 0:
@@ -1341,11 +1349,11 @@ class Containerize():
cmd += res.group('container_name') + ' '
message = ''
if anyLogs:
- logging.info(cmd)
- stats = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30)
- for statLine in stats.split('\n'):
+ stats = myCmd.run(cmd, timeout=30)
+ for statLine in stats.stdout.split('\n'):
logging.debug(statLine)
message += statLine + '\n'
+ myCmd.close()
html_queue = SimpleQueue()
html_cell = '\n' + message + '
'
@@ -1353,18 +1361,18 @@ class Containerize():
HTML.CreateHtmlTestRowQueue(self.pingOptions, 'OK', 1, html_queue)
def PingFromContainer(self, HTML, RAN, UE):
+ myCmd = cls_cmd.LocalCmd()
self.exitStatus = 0
ymlPath = self.yamlPath[0].split('/')
logPath = '../cmake_targets/log/' + ymlPath[1]
- cmd = 'mkdir -p ' + logPath
- deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
+ cmd = f'mkdir -p {logPath}'
+ myCmd.run(cmd, silent=True)
- cmd = 'docker exec ' + self.pingContName + ' /bin/bash -c "ping ' + self.pingOptions + '" 2>&1 | tee ' + logPath + '/ping_' + HTML.testCase_id + '.log || true'
+ cmd = f'docker exec {self.pingContName} /bin/bash -c "ping {self.pingOptions}" 2>&1 | tee {logPath}/ping_{HTML.testCase_id}.log'
+ pingStatus = myCmd.run(cmd, timeout=100, reportNonZero=False)
+ myCmd.close()
- logging.info(cmd)
- deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100)
-
- result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', deployStatus)
+ result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', pingStatus.stdout)
if result is None:
self.PingExit(HTML, RAN, UE, False, 'Packet Loss Not Found')
return
@@ -1374,7 +1382,7 @@ class Containerize():
self.PingExit(HTML, RAN, UE, False, 'Packet Loss is 100%')
return
- result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', deployStatus)
+ result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', pingStatus.stdout)
if result is None:
self.PingExit(HTML, RAN, UE, False, 'Ping RTT_Min RTT_Avg RTT_Max Not Found!')
return
@@ -1427,39 +1435,37 @@ class Containerize():
self.exitStatus = 1
def IperfFromContainer(self, HTML, RAN, UE):
+ myCmd = cls_cmd.LocalCmd()
self.exitStatus = 0
ymlPath = self.yamlPath[0].split('/')
logPath = '../cmake_targets/log/' + ymlPath[1]
- cmd = 'mkdir -p ' + logPath
- logStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
+ cmd = f'mkdir -p {logPath}'
+ myCmd.run(cmd, silent=True)
# Start the server process
cmd = f'docker exec -d {self.svrContName} /bin/bash -c "nohup iperf {self.svrOptions} > /tmp/iperf_server.log 2>&1"'
- logging.info(cmd)
- subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
+ myCmd.run(cmd)
time.sleep(3)
# Start the client process
cmd = f'docker exec {self.cliContName} /bin/bash -c "iperf {self.cliOptions}" 2>&1 | tee {logPath}/iperf_client_{HTML.testCase_id}.log'
- logging.info(cmd)
- clientStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100)
+ clientStatus = myCmd.run(cmd, timeout=100)
# Stop the server process
cmd = f'docker exec {self.svrContName} /bin/bash -c "pkill iperf"'
- logging.info(cmd)
- subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10)
+ myCmd.run(cmd)
time.sleep(3)
serverStatusFilename = f'{logPath}/iperf_server_{HTML.testCase_id}.log'
cmd = f'docker cp {self.svrContName}:/tmp/iperf_server.log {serverStatusFilename}'
- logging.info(cmd)
- subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30)
+ myCmd.run(cmd, timeout=60)
+ myCmd.close()
# clientStatus was retrieved above. The serverStatus was
# written in the background, then copied to the local machine
with open(serverStatusFilename, 'r') as f:
serverStatus = f.read()
- (iperfStatus, msg) = AnalyzeIperf(self.cliOptions, clientStatus, serverStatus)
+ (iperfStatus, msg) = AnalyzeIperf(self.cliOptions, clientStatus.stdout, serverStatus)
if iperfStatus:
logging.info('\u001B[1m Iperf Test PASS\u001B[0m')
else:
@@ -1595,4 +1601,3 @@ class Containerize():
if result is None:
mySSH.command('echo ' + password + ' | sudo -S iptables -P FORWARD ACCEPT', '\$', 10)
mySSH.close()
-
diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py
index 328785f8d1..51e43109a0 100644
--- a/ci-scripts/cls_oaicitest.py
+++ b/ci-scripts/cls_oaicitest.py
@@ -453,17 +453,6 @@ class OaiCiTest():
UE_prefix = 'NR '
SSH = sshconnection.SSHConnection()
SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
- # b2xx_fx3_utils reset procedure
- SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 180)
- result = re.search('type: b200', SSH.getBefore())
- if result is not None:
- logging.debug('Found a B2xx device --> resetting it')
- SSH.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10)
- # Reloading FGPA bin firmware
- SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 180)
- result = re.search('type: n3xx', str(SSH.getBefore()))
- if result is not None:
- logging.debug('Found a N3xx device --> resetting it')
SSH.command('cd ' + self.UESourceCodePath, '\$', 5)
# Initialize_OAI_UE_args usually start with -C and followed by the location in repository
SSH.command('source oaienv', '\$', 5)
diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py
index 8ee4a0a5e6..64074fdd6a 100644
--- a/ci-scripts/epc.py
+++ b/ci-scripts/epc.py
@@ -43,7 +43,7 @@ from multiprocessing import Process, Lock, SimpleQueue
#-----------------------------------------------------------
# OAI Testing modules
#-----------------------------------------------------------
-import sshconnection as SSH
+import sshconnection as SSH
import helpreadme as HELP
import constants as CONST
@@ -66,8 +66,8 @@ class EPCManagement():
self.mmeConfFile = 'mme.conf'
self.yamlPath = ''
self.isMagmaUsed = False
- self.cfgDeploy = '--type start-mini --fqdn yes --scenario 1 --capture /tmp/oai-cn5g-v1.3.pcap' #from xml, 'mini' is default normal for docker-network.py
- self.cfgUnDeploy = '--type stop-mini --fqdn yes --scenario 1' #from xml, 'mini' is default normal for docker-network.py
+ self.cfgDeploy = '--type start-mini --scenario 1 --capture /tmp/oai-cn5g-v1.5.pcap' #from xml, 'mini' is default normal for docker-network.py
+ self.cfgUnDeploy = '--type stop-mini --scenario 1' #from xml, 'mini' is default normal for docker-network.py
#-----------------------------------------------------------
@@ -253,18 +253,18 @@ class EPCManagement():
logging.debug('Starting OAI CN5G')
mySSH.command('if [ -d ' + self.SourceCodePath + '/scripts ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/scripts ; fi', '\$', 5)
mySSH.command('mkdir -p ' + self.SourceCodePath + '/scripts', '\$', 5)
- mySSH.command('cd /opt/oai-cn5g-fed-v1.4/docker-compose', '\$', 5)
+ mySSH.command('cd /opt/oai-cn5g-fed-v1.5/docker-compose', '\$', 5)
mySSH.command('python3 ./core-network.py '+self.cfgDeploy, '\$', 60)
if re.search('start-mini-as-ue', self.cfgDeploy):
dFile = 'docker-compose-mini-nrf-asue.yaml'
else:
dFile = 'docker-compose-mini-nrf.yaml'
- mySSH.command('docker-compose -p 5gcn -f ' + dFile + ' ps -a', '\$', 60)
+ mySSH.command('docker-compose -f ' + dFile + ' ps -a', '\$', 60)
if mySSH.getBefore().count('Up (healthy)') != 6:
logging.error('Not all container healthy')
else:
logging.debug('OK --> all containers are healthy')
- mySSH.command('docker-compose -p 5gcn -f ' + dFile + ' config | grep --colour=never image', '\$', 10)
+ mySSH.command('docker-compose -f ' + dFile + ' config | grep --colour=never image', '\$', 10)
listOfImages = mySSH.getBefore()
for imageLine in listOfImages.split('\\r\\n'):
res1 = re.search('image: (?P[a-zA-Z0-9\-/]+):(?P[a-zA-Z0-9\-]+)', str(imageLine))
@@ -537,11 +537,11 @@ class EPCManagement():
mySSH.command('docker logs ' + c + ' > ' + self.SourceCodePath + '/logs/' + c + '.log', '\$', 5)
logging.debug('Terminating OAI CN5G')
- mySSH.command('cd /opt/oai-cn5g-fed-v1.4/docker-compose', '\$', 5)
+ mySSH.command('cd /opt/oai-cn5g-fed-v1.5/docker-compose', '\$', 5)
mySSH.command('python3 ./core-network.py '+self.cfgUnDeploy, '\$', 60)
mySSH.command('docker volume prune --force || true', '\$', 60)
time.sleep(2)
- mySSH.command('tshark -r /tmp/oai-cn5g-v1.3.pcap | egrep --colour=never "Tracking area update" ','\$', 30)
+ mySSH.command('tshark -r /tmp/oai-cn5g-v1.5.pcap | egrep --colour=never "Tracking area update" ','\$', 30)
result = re.search('Tracking area update request', mySSH.getBefore())
if result is not None:
message = 'UE requested ' + str(mySSH.getBefore().count('Tracking area update request')) + 'Tracking area update request(s)'
@@ -828,7 +828,7 @@ class EPCManagement():
mySSH.command('zip mme.log.zip mme_check_run.*', '\$', 60)
elif re.match('OAICN5G', self.Type, re.IGNORECASE):
mySSH.command('cd ' + self.SourceCodePath + '/logs','\$', 5)
- mySSH.command('cp -f /tmp/oai-cn5g-v1.3.pcap .','\$', 30)
+ mySSH.command('cp -f /tmp/oai-cn5g-v1.5.pcap .','\$', 30)
mySSH.command('zip mme.log.zip oai-amf.log oai-nrf.log oai-cn5g*.pcap','\$', 30)
mySSH.command('mv mme.log.zip ' + self.SourceCodePath + '/scripts','\$', 30)
elif re.match('OAI', self.Type, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE):
diff --git a/ci-scripts/main.py b/ci-scripts/main.py
index 322b6a5c72..fd3f1f773a 100644
--- a/ci-scripts/main.py
+++ b/ci-scripts/main.py
@@ -70,6 +70,7 @@ import subprocess
from multiprocessing import Process, Lock, SimpleQueue
logging.basicConfig(
level=logging.DEBUG,
+ stream=sys.stdout,
format="[%(asctime)s] %(levelname)8s: %(message)s"
)
@@ -498,6 +499,9 @@ def GetParametersFromXML(action):
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')
else:
logging.warning(f"unknown action {action} from option-parsing point-of-view")
@@ -879,6 +883,9 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
RAN.BuildeNB(HTML)
elif action == 'WaitEndBuild_eNB':
RAN.WaitBuildeNBisFinished(HTML)
+ elif action == 'Custom_Command':
+ logging.info(f"Executing custom command")
+ RAN.CustomCommand(HTML)
elif action == 'Initialize_eNB':
check_eNB = False
check_OAI_UE = False
diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py
index fd6a073f21..8628d5f3d8 100644
--- a/ci-scripts/ran.py
+++ b/ci-scripts/ran.py
@@ -38,6 +38,7 @@ import os
import time
from multiprocessing import Process, Lock, SimpleQueue
import yaml
+import cls_cmd
#-----------------------------------------------------------
@@ -96,6 +97,8 @@ class RANManagement():
#checkers from xml
self.ran_checkers={}
self.cmd_prefix = '' # prefix before {lte,nr}-softmodem
+ self.node = ''
+ self.command = ''
#-----------------------------------------------------------
@@ -259,6 +262,21 @@ class RANManagement():
mySSH.close()
self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)], HTML)
+ def CustomCommand(self, HTML):
+ if self.node == '' or self.node == "localhost":
+ cmd = cls_cmd.LocalCmd()
+ else:
+ cmd = cls_cmd.RemoteCmd(self.node)
+ ret = cmd.run(self.command)
+ cmd.close()
+ logging.debug(f'CustomCommand: {self.command} returnCode: {ret.returncode} output: {ret.stdout}')
+ html_queue = SimpleQueue()
+ status = 'OK'
+ if ret.returncode != 0:
+ html_queue.put(ret.stdout)
+ status = 'Warning'
+ HTML.CreateHtmlTestRow(self.command, status, 1, html_queue)
+
def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId, HTML):
HTML.testCase_id=testcaseId
@@ -347,17 +365,6 @@ class RANManagement():
cwd = os.getcwd()
mySSH.copyout(lIpAddr,lUserName,lPassWord, cwd + "/active_net_interfaces.awk", "/tmp")
- #reboot USRP if requested in xml
- if self.USRPIPAddress!='':
- logging.debug('USRP '+ self.USRPIPAddress +': reboot request')
- mySSH.open(lIpAddr, lUserName, lPassWord)
- cmd2usrp='ssh root@'+self.USRPIPAddress+' reboot'
- mySSH.command2(cmd2usrp,1)
- mySSH.close()
- logging.debug('Waiting for USRP to be ready')
- time.sleep(120)
-
-
if (self.pStatus < 0):
HTML.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' ' + self.Initialize_eNB_args, 'KO', self.pStatus)
HTML.CreateHtmlTabFooter(False)
@@ -419,16 +426,6 @@ class RANManagement():
result = re.search('^rru|^rcc|^du.band', str(config_file))
if result is not None:
rruCheck = True
- # do not reset board twice in IF4.5 case
- result = re.search('^rru|^enb|^du.band', str(config_file))
- if result is not None:
- mySSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 180)
- result = re.search('type: b200', mySSH.getBefore())
- if result is not None:
- logging.debug('Found a B2xx device --> resetting it')
- mySSH.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10)
- # Reloading FGPA bin firmware
- mySSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 180)
# Make a copy and adapt to EPC / eNB IP addresses
mySSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5)
localMmeIpAddr = EPC.MmeIPAddress
diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml
index b4dabb1654..93e3bc9fb0 100755
--- a/ci-scripts/xml_class_list.yml
+++ b/ci-scripts/xml_class_list.yml
@@ -51,3 +51,4 @@
- Push_Local_Registry
- Pull_Local_Registry
- Clean_Test_Server_Images
+ - Custom_Command
diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml
index ce9a19fde3..698c620329 100644
--- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml
+++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml
@@ -27,12 +27,15 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1.xml
Test-FDD-05MHz-TM1
tasks
+100000
111110
+300000
040101
030101
000001
040301 000001 040501 040603 040604 040605 040606 040607 040641 040642 040643 040644 040401 040201
030201
+200000
@@ -42,7 +45,24 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1.xml
0
oai-enb
-
+
+ Custom_Command
+ To reset cpupower
+ hutch
+ sudo cpupower idle-set -D 0
+
+
+ Custom_Command
+ To reset cpupower
+ hutch
+ sudo cpupower idle-set -E
+
+
+ Custom_Command
+ To reset USRP
+ hutch
+ sudo -S b2xx_fx3_utils --reset-device
+
Deploy_Object
Deploy eNB (FDD/Band7/5MHz/B200) in a container
diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml
index 8ead87d703..66d0c982ec 100644
--- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml
+++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_no_rrc_activity.xml
@@ -27,11 +27,13 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1_rrc_inactivity_no_flexran.xm
Test-FDD-05MHz-TM1-RRC-Inactivity
tasks
+100000
111110
040101
030102
000010 040301 040502 000011 040302 000001 000012 040303 000002 000013 040503 040401 040201
030201
+200000
@@ -41,6 +43,18 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1_rrc_inactivity_no_flexran.xm
0
oai-enb
+
+ Custom_Command
+ To reset cpupower
+ hutch
+ sudo cpupower idle-set -D 0
+
+
+ Custom_Command
+ To reset cpupower
+ hutch
+ sudo cpupower idle-set -E
+
Deploy_Object
diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml
index ce3161c94c..07f23ff2f0 100644
--- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml
+++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml
@@ -28,12 +28,14 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml
Test-FDD-10MHz-TM1
tasks
+100000
111110
040101
030111
000001
040301 040511 040613 040614 040615 040651 040652 040653 040654 040401 040201
030201
+200000
@@ -43,6 +45,18 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml
0
oai-enb
+
+ Custom_Command
+ To reset cpupower
+ hutch
+ sudo cpupower idle-set -D 0
+
+
+ Custom_Command
+ To reset cpupower
+ hutch
+ sudo cpupower idle-set -E
+
Deploy_Object
diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml
index 4d09bada08..caa888e4a8 100644
--- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml
+++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml
@@ -27,11 +27,13 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml
Test-FDD-10MHz-CDRX-TM1
tasks
+100000
111110
040101
030112
040301 040512 040612 040650 040401 040201
030201
+200000
@@ -41,6 +43,18 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml
0
oai-enb
+
+ Custom_Command
+ To reset cpupower
+ hutch
+ sudo cpupower idle-set -D 0
+
+
+ Custom_Command
+ To reset cpupower
+ hutch
+ sudo cpupower idle-set -E
+
Deploy_Object
diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml
index 092ee208d1..e57e40cb1f 100644
--- a/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml
+++ b/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml
@@ -27,12 +27,14 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml
Test-FDD-20MHz-TM1
tasks
+100000
111110
040101
030121
000001
040301 040521 040623 040624 040625 040662 040401 040201
030201
+200000
@@ -42,6 +44,18 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml
0
oai-enb
+
+ Custom_Command
+ To reset cpupower
+ hutch
+ sudo cpupower idle-set -D 0
+
+
+ Custom_Command
+ To reset cpupower
+ hutch
+ sudo cpupower idle-set -E
+
Deploy_Object
diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml
index fa191cd163..9f3bedba9e 100644
--- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml
+++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml
@@ -27,11 +27,13 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm1.xml
Test-TDD-05MHz-TM1
tasks
+100000
111110
040101
030104
040301 040501 040602 040601 040603 040604 040605 040642 040641 040643 040644 040645 040401 040201
030201
+200000
@@ -41,6 +43,18 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm1.xml
0
oai-enb
+
+ Custom_Command
+ To reset cpupower
+ starsky
+ sudo cpupower idle-set -D 0
+
+
+ Custom_Command
+ To reset cpupower
+ starsky
+ sudo cpupower idle-set -E
+
Deploy_Object
diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm2.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm2.xml
index 69997c5586..d8f87b4741 100644
--- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm2.xml
+++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm2.xml
@@ -27,11 +27,13 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm2.xml
Test-TDD-05MHz-TM2
tasks
+100000
111110
040101
030105
040301 040502 040606 040608 040646 040648 040401 040201
030201
+200000
@@ -41,7 +43,18 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm2.xml
0
oai-enb
-
+
+ Custom_Command
+ To reset cpupower
+ starsky
+ sudo cpupower idle-set -D 0
+
+
+ Custom_Command
+ To reset cpupower
+ starsky
+ sudo cpupower idle-set -E
+
Deploy_Object
Deploy eNB (TDD/Band40/5MHz/B200) in a container
diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml
index ada6945aad..fe47e7c958 100644
--- a/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml
+++ b/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml
@@ -27,11 +27,13 @@ Replaces xml_files/enb_usrp210_band40_test_10mhz_tm1.xml
Test-TDD-10MHz-TM1
tasks
+100000
111110
040101
030114
040301 040511 040612 040611 040613 040614 040615 040652 040651 040653 040654 040655 040401 040201
030201
+200000
@@ -41,7 +43,18 @@ Replaces xml_files/enb_usrp210_band40_test_10mhz_tm1.xml
0
oai-enb
-
+
+ Custom_Command
+ To reset cpupower
+ starsky
+ sudo cpupower idle-set -D 0
+
+
+ Custom_Command
+ To reset cpupower
+ starsky
+ sudo cpupower idle-set -E
+
Deploy_Object
Deploy eNB (TDD/Band40/10MHz/B200) in a container
diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml
index ec3de1a5ae..51c4f95137 100644
--- a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml
+++ b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1.xml
@@ -27,11 +27,13 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1.xml
Test-TDD-20MHz-TM1
tasks
+100000
111110
040101
030124
040301 040521 040622 040621 040623 040662 040401 040201
030201
+200000
@@ -41,7 +43,18 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1.xml
0
oai-enb
-
+
+ Custom_Command
+ To reset cpupower
+ starsky
+ sudo cpupower idle-set -D 0
+
+
+ Custom_Command
+ To reset cpupower
+ starsky
+ sudo cpupower idle-set -E
+
Deploy_Object
Deploy eNB (TDD/Band40/20MHz/B200) in a container
diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml
index b5ff90e112..57ebb79fac 100644
--- a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml
+++ b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml
@@ -27,11 +27,13 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml
Test-TDD-20MHz-TM1-Default-Scheduler
tasks
+100000
111110
040101
030125
040301 040522 040627 040626 040628 040629 040630 040667 040666 040668 040669 040670 040401 040201
030201
+200000
@@ -41,7 +43,18 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml
0
oai-enb
-
+
+ Custom_Command
+ To reset cpupower
+ starsky
+ sudo cpupower idle-set -D 0
+
+
+ Custom_Command
+ To reset cpupower
+ starsky
+ sudo cpupower idle-set -E
+
Deploy_Object
Deploy eNB (TDD/Band40/20MHz/B200) in a container
diff --git a/ci-scripts/xml_files/container_nsa_b200_quectel.xml b/ci-scripts/xml_files/container_nsa_b200_quectel.xml
index 3734c91229..397e6aadbd 100644
--- a/ci-scripts/xml_files/container_nsa_b200_quectel.xml
+++ b/ci-scripts/xml_files/container_nsa_b200_quectel.xml
@@ -26,6 +26,9 @@
tasks
1
+ 200000
+ 100000
+ 500000
111110
111111
000001
@@ -47,6 +50,8 @@
000001
030202
030201
+ 300000
+ 600000
@@ -69,7 +74,36 @@
Initialize Quectel
idefix
-
+
+ Custom_Command
+ To reset USRP
+ nepes
+ sudo -S b2xx_fx3_utils --reset-device
+
+
+ Custom_Command
+ To reset cpupower - nepes
+ nepes
+ sudo cpupower idle-set -D 0
+
+
+ Custom_Command
+ To reset cpupower - nepes
+ nepes
+ sudo cpupower idle-set -E
+
+
+ Custom_Command
+ To reset cpupower - obelix
+ obelix
+ sudo cpupower idle-set -D 0
+
+
+ Custom_Command
+ To reset cpupower - obelix
+ obelix
+ sudo cpupower idle-set -E
+
Terminate_UE
diff --git a/ci-scripts/xml_files/container_sa_b200_quectel.xml b/ci-scripts/xml_files/container_sa_b200_quectel.xml
index 53cfbf80cb..4f0e01c692 100644
--- a/ci-scripts/xml_files/container_sa_b200_quectel.xml
+++ b/ci-scripts/xml_files/container_sa_b200_quectel.xml
@@ -26,6 +26,7 @@
tasks
1
+ 100000
111111
010002
030101
@@ -39,6 +40,7 @@
010002
000001
030201
+ 200000