From 9ea7df92107184e10a33ecd749dba77d46ce5d1f Mon Sep 17 00:00:00 2001 From: Remi Hardy <remi.hardy@openairinterface.org> Date: Thu, 3 Dec 2020 22:12:54 +0100 Subject: [PATCH] func + log update of fr1 nsa test --- ci-scripts/build_fr1_from_yaml.py | 83 ++++++++++ ci-scripts/build_fr1_template.yaml | 46 ++++++ ci-scripts/ran.py | 183 ++++++++++++++++++++++- ci-scripts/xml_files/fr1_ran_ue_proc.xml | 39 ++++- 4 files changed, 347 insertions(+), 4 deletions(-) create mode 100755 ci-scripts/build_fr1_from_yaml.py create mode 100755 ci-scripts/build_fr1_template.yaml diff --git a/ci-scripts/build_fr1_from_yaml.py b/ci-scripts/build_fr1_from_yaml.py new file mode 100755 index 00000000000..a5492df6f6b --- /dev/null +++ b/ci-scripts/build_fr1_from_yaml.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Jul 7 23:04:51 2020 + +@author: hardy +""" + + + +import yaml +import sys +import subprocess + + + +def main(): + f_yaml=sys.argv[1] + f_sh=sys.argv[2] + #filename='py_params_template.yaml' + with open(f_yaml,'r') as file: + # The FullLoader parameter handles the conversion from YAML + # scalar values to Python the dictionary format + print('Loading '+f_yaml) + params = yaml.load(file,Loader=yaml.FullLoader) + + + with open(f_sh,'w') as f: + f.write('#!/bin/sh\n') + for i in range (0, len(params['steps'])): + step=params['steps'][i].split(',') + mode=step[0] + f_xml=step[1] + line='python3 main.py ' + \ + '--mode='+ mode + ' ' + \ + '--ranRepository=' + params['ranRepository'] + ' ' + \ + '--ranBranch=' + params['ranBranch'] + ' ' + \ + '--ranCommitID=' + params['ranCommitID'] + ' ' + \ + '--ranAllowMerge=' + params['ranAllowMerge'] + ' ' + \ + '--ranTargetBranch=' + params['ranTargetBranch'] + ' ' + \ + \ + '--ADBIPAddress=' + params['ADB']['ADBIPAddress'] + ' ' + \ + '--ADBUserName=' + params['ADB']['ADBUserName'] + ' ' + \ + '--ADBPassword=' + params['ADB']['ADBPassword'] + ' ' + \ + \ + '--UEIPAddress=' + params['UE']['UEIPAddress'] + ' ' + \ + '--UEUserName=' + params['UE']['UEUserName'] + ' ' + \ + '--UEPassword=' + params['UE']['UEPassword'] + ' ' + \ + '--UESourceCodePath=' + params['UE']['UESourceCodePath'] + ' ' + \ + \ + '--EPCIPAddress=' + params['EPC']['EPCIPAddress'] + ' ' + \ + '--EPCUserName=' + params['EPC']['EPCUserName'] + ' ' + \ + '--EPCPassword=' + params['EPC']['EPCPassword'] + ' ' + \ + '--EPCSourceCodePath=' + params['EPC']['EPCSourceCodePath'] + ' ' + \ + '--EPCType=' + params['EPC']['EPCType'] + ' ' + \ + \ + '--eNBIPAddress=' + params['RAN'][0]['eNBIPAddress'] + ' ' + \ + '--eNBUserName=' + params['RAN'][0]['eNBUserName'] + ' ' + \ + '--eNBPassword=' + params['RAN'][0]['eNBPassword'] + ' ' + \ + '--eNBSourceCodePath=' + params['RAN'][0]['eNBSourceCodePath'] + ' ' + \ + \ + '--eNB1IPAddress=' + params['RAN'][1]['eNB1IPAddress'] + ' ' + \ + '--eNB1UserName=' + params['RAN'][1]['eNB1UserName'] + ' ' + \ + '--eNB1Password=' + params['RAN'][1]['eNB1Password'] + ' ' + \ + '--eNB1SourceCodePath=' + params['RAN'][1]['eNB1SourceCodePath'] + ' ' + if mode!="InitiateHtml": + line+='--XMLTestFile=' + f_xml + #if mode is InitiateHTML we have a special processing to mention all xml files from the list + #loop starting at 1 to avoid the xml file mentioned with InitiateHtml in yaml file (file is none) + else: + for i in range (1, len(params['steps'])): + step=params['steps'][i].split(',') + f_xml=step[1] + line+='--XMLTestFile=' + f_xml+' ' + line+='\n' + print(line) + f.write(line) + subprocess.call(['chmod','777',f_sh]) + +if __name__ == "__main__": + main() + + diff --git a/ci-scripts/build_fr1_template.yaml b/ci-scripts/build_fr1_template.yaml new file mode 100755 index 00000000000..3aace262f5e --- /dev/null +++ b/ci-scripts/build_fr1_template.yaml @@ -0,0 +1,46 @@ + +ranRepository : https://gitlab.eurecom.fr/oai/openairinterface5g.git +ranBranch : BRANCH_NAME +ranCommitID : COMMIT_ID +ranAllowMerge : 'true' +ranTargetBranch : develop + +steps: + - InitiateHtml,none + - TesteNB,xml_files/fr1_multi_node_build.xml + - TesteNB,xml_files/fr1_epc_start.xml + - TesteNB,xml_files/fr1_ran_ue_proc.xml #ue toggle, nodes initialize, ue toggle, ping, nodes terminate + - TesteNB,xml_files/fr1_epc_closure.xml + + +ADB: #on Caracal + ADBIPAddress : 192.168.18.196 + ADBUserName : oaici + ADBPassword : KkexF6CErOi1fNuebCPsuIVK + +RAN: + - eNBIPAddress : 192.168.18.199 #eNB on Minimassive + eNBUserName : oaicicd + eNBPassword : HzB*nkryaITdVd08TKlT#2Z5a!7M#~qn + eNBSourceCodePath : /tmp/CI-FR1-eNB + - eNB1IPAddress : 192.168.18.198 #gNB on Mozart + eNB1UserName : oaicicd + eNB1Password : 7zkDOFgh@w3HvRBMPTMh@BAx + eNB1SourceCodePath : /tmp/CI-FR1-gNB + + +EPC: #on Nikaia + EPCIPAddress : 192.168.18.99 + EPCUserName : nikaia + EPCPassword : linux + EPCSourceCodePath : /tmp/CI-FR1-EPC + EPCType : ltebox + + +UE: + UEIPAddress : none + UEUserName : none + UEPassword : none + UESourceCodePath : none + + diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index f78417e22cb..369a4bb95c5 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -77,6 +77,7 @@ class RANManagement(): self.backgroundBuildTestId = ['', '', ''] self.Build_eNB_forced_workspace_cleanup = False self.Initialize_eNB_args = '' + self.imageKind = '' self.air_interface = ['', '', ''] #changed from 'lte' to '' may lead to side effects in main self.eNB_instance = 0 self.eNB_serverId = ['', '', ''] @@ -320,6 +321,174 @@ class RANManagement(): self.htmlObj.CreateHtmlTabFooter(False) sys.exit(1) + def BuildImage(self): + if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + if self.eNB_serverId[self.eNB_instance] == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + logging.debug('Building on server: ' + lIpAddr) + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + + imageNames = [] + result = re.search('eNB', self.imageKind) + if result is not None: + imageNames.append(('oai-enb', 'eNB')) + else: + result = re.search('gNB', self.imageKind) + if result is not None: + imageNames.append(('oai-gnb', 'gNB')) + else: + result = re.search('all', self.imageKind) + if result is not None: + imageNames.append(('oai-enb', 'eNB')) + imageNames.append(('oai-gnb', 'gNB')) + if len(imageNames) == 0: + imageNames.append(('oai-enb', 'eNB')) + # Workaround for some servers, we need to erase completely the workspace + if self.Build_eNB_forced_workspace_cleanup: + mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15) + if self.htmlObj is not None: + self.testCase_id = self.htmlObj.testCase_id + else: + self.testCase_id = '000000' + # on RedHat/CentOS .git extension is mandatory + result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) + if result is not None: + full_ran_repo_name = self.ranRepository + else: + full_ran_repo_name = self.ranRepository + '.git' + mySSH.command('mkdir -p ' + lSourcePath, '\$', 5) + mySSH.command('cd ' + lSourcePath, '\$', 5) + mySSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) + # Raphael: here add a check if git clone or git fetch went smoothly + mySSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + mySSH.command('git config user.name "OAI Jenkins"', '\$', 5) + + mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) + mySSH.command('mkdir -p cmake_targets/log', '\$', 5) + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) + # if the branch is not develop, then it is a merge request and we need to do + # the potential merge. Note that merge conflicts should already been checked earlier + imageTag = 'develop' + if (self.ranAllowMerge): + imageTag = 'ci-temp' + if self.ranTargetBranch == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + mySSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + self.ranTargetBranch) + mySSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + # Let's remove any previous run artifacts if still there + mySSH.command('docker image prune --force', '\$', 5) + mySSH.command('docker image rm ran-build:' + imageTag, '\$', 5) + for image,pattern in imageNames: + mySSH.command('docker image rm ' + image + ':' + imageTag, '\$', 5) + # Build the shared image + mySSH.command('docker build --target ran-build --tag ran-build:' + imageTag + ' --file docker/Dockerfile.ran.ubuntu18 --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > cmake_targets/log/ran-build.log 2>&1', '\$', 800) + # Build the target image(s) + previousImage='ran-build:' + imageTag + danglingShaOnes=[] + for image,pattern in imageNames: + mySSH.command('docker build --target ' + image + ' --tag ' + image + ':' + imageTag + ' --file docker/Dockerfile.' + pattern + '.ubuntu18 . > cmake_targets/log/' + image + '.log 2>&1', '\$', 600) + # Retrieving the dangling image(s) for the log collection + mySSH.command('docker images --filter "dangling=true" --filter "since=' + previousImage + '" -q | sed -e "s#^#sha=#"', '\$', 5) + result = re.search('sha=(?P<imageShaOne>[a-zA-Z0-9\-\_]+)', mySSH.getBefore()) + if result is not None: + danglingShaOnes.append((image, result.group('imageShaOne'))) + previousImage=image + ':' + imageTag + + imageTag = 'ci-temp' + # First verify if images were properly created. + status = True + mySSH.command('docker image inspect --format=\'Size = {{.Size}} bytes\' ran-build:' + imageTag, '\$', 5) + if mySSH.getBefore().count('No such object') != 0: + logging.error('Could not build properly ran-build') + status = False + else: + result = re.search('Size = (?P<size>[0-9\-]+) bytes', mySSH.getBefore()) + if result is not None: + imageSize = float(result.group('size')) + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m ran-build size is ' + ('%.0f' % imageSize) + ' kbytes\u001B[0m') + else: + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m ran-build size is ' + ('%.0f' % imageSize) + ' Mbytes\u001B[0m') + else: + imageSize = imageSize / 1000 + logging.debug('\u001B[1m ran-build size is ' + ('%.3f' % imageSize) + ' Gbytes\u001B[0m') + else: + logging.debug('ran-build size is unknown') + for image,pattern in imageNames: + mySSH.command('docker image inspect --format=\'Size = {{.Size}} bytes\' ' + image + ':' + imageTag, '\$', 5) + if mySSH.getBefore().count('No such object') != 0: + logging.error('Could not build properly ' + image) + status = False + else: + result = re.search('Size = (?P<size>[0-9\-]+) bytes', mySSH.getBefore()) + if result is not None: + imageSize = float(result.group('size')) + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m ' + image + ' size is ' + ('%.0f' % imageSize) + ' kbytes\u001B[0m') + else: + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m ' + image + ' size is ' + ('%.0f' % imageSize) + ' Mbytes\u001B[0m') + else: + imageSize = imageSize / 1000 + logging.debug('\u001B[1m ' + image + ' size is ' + ('%.3f' % imageSize) + ' Gbytes\u001B[0m') + else: + logging.debug('ran-build size is unknown') + if not status: + mySSH.close() + logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) + self.htmlObj.CreateHtmlTabFooter(False) + sys.exit(1) + + # Recover build logs, for the moment only possible when build is successful + mySSH.command('docker create --name test ran-build:' + imageTag, '\$', 5) + mySSH.command('mkdir -p cmake_targets/log/ran-build', '\$', 5) + mySSH.command('docker cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/ran-build', '\$', 5) + mySSH.command('docker rm -f test', '\$', 5) + for image,shaone in danglingShaOnes: + mySSH.command('mkdir -p cmake_targets/log/' + image, '\$', 5) + mySSH.command('docker create --name test ' + shaone, '\$', 5) + mySSH.command('docker cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/' + image, '\$', 5) + mySSH.command('docker rm -f test', '\$', 5) + mySSH.command('docker image prune --force', '\$', 5) + mySSH.command('cd cmake_targets', '\$', 5) + mySSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) + mySSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) + mySSH.close() + + logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m') + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow(self.imageKind, 'OK', CONST.ALL_PROCESSES_OK) + def InitializeeNB(self): if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress @@ -716,7 +885,9 @@ class RANManagement(): NSA_RAPROC_PUSCH_check = 0 #dlsch and ulsch statistics (dictionary) dlsch_ulsch_stats = {} - + #count L1 thread not ready msg + L1_thread_not_ready_cnt = 0 + for line in enb_log_file.readlines(): # Runtime statistics result = re.search('Run time:' ,str(line)) @@ -881,6 +1052,10 @@ class RANManagement(): if result is not None: #remove 1- all useless char before relevant info (ulsch or dlsch) 2- trailing char dlsch_ulsch_stats[k]=re.sub(r'^.*\]\s+', r'' , line.rstrip()) + #count L1 thread not ready msg + result = re.search('\[PHY\]\s+L1_thread isn\'t ready', str(line)) + if result is not None: + L1_thread_not_ready_cnt += 1 enb_log_file.close() logging.debug(' File analysis completed') if (self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb'): @@ -910,6 +1085,12 @@ class RANManagement(): htmlMsg = statMsg+'\n' logging.debug(statMsg) htmleNBFailureMsg += htmlMsg + #L1 thread not ready log + if L1_thread_not_ready_cnt != 0: + statMsg = '[PHY] L1 thread is not ready msg count = '+str(L1_thread_not_ready_cnt) + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg #ulsch and dlsch statistics if len(dlsch_ulsch_stats)!=0: #check if dictionary is not empty statMsg='' diff --git a/ci-scripts/xml_files/fr1_ran_ue_proc.xml b/ci-scripts/xml_files/fr1_ran_ue_proc.xml index 330fb27f21b..5730630ddd4 100644 --- a/ci-scripts/xml_files/fr1_ran_ue_proc.xml +++ b/ci-scripts/xml_files/fr1_ran_ue_proc.xml @@ -32,9 +32,16 @@ 000001 050000 050001 + 050002 + 050002 + 000001 + 060000 + 060001 + 000001 + 010002 + 000001 070001 070000 - 010002 010003 </TestCaseRequestedList> <TestCaseExclusionList></TestCaseExclusionList> @@ -89,16 +96,42 @@ <class>Ping</class> <desc>Ping: 20pings in 20sec</desc> <ping_args>-c 20</ping_args> - <ping_packetloss_threshold>50</ping_packetloss_threshold> + <ping_packetloss_threshold>90</ping_packetloss_threshold> </testCase> <testCase id="050001"> <class>Ping</class> <desc>Ping: 5pings in 1sec</desc> <ping_args>-c 5 -i 0.2</ping_args> - <ping_packetloss_threshold>50</ping_packetloss_threshold> + <ping_packetloss_threshold>90</ping_packetloss_threshold> + </testCase> + + <testCase id="050002"> + <class>Ping</class> + <desc>Ping: 100pings in 20sec</desc> + <ping_args>-c 100 -i 0.2</ping_args> + <ping_packetloss_threshold>90</ping_packetloss_threshold> </testCase> + + <testCase id="060000"> + <class>Iperf</class> + <desc>iperf (DL/10Kbps/UDP)(30 sec)(single-ue profile)</desc> + <iperf_args>-u -b 10K -t 30 -i 1</iperf_args> + <iperf_packetloss_threshold>90</iperf_packetloss_threshold> + <iperf_profile>single-ue</iperf_profile> + </testCase> + + <testCase id="060001"> + <class>Iperf</class> + <desc>iperf (UL/10Kbps/UDP)(30 sec)(single-ue profile)</desc> + <iperf_args>-u -b 10K -t 30 -i 1 -R</iperf_args> + <iperf_packetloss_threshold>90</iperf_packetloss_threshold> + <iperf_profile>single-ue</iperf_profile> + </testCase> + + + <testCase id="070000"> <class>Terminate_eNB</class> <desc>Terminate eNB</desc> -- GitLab