# * 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 #----------------------------------------------------------- import sys # arg import re # reg import logging import os import time import subprocess from multiprocessing import Process, Lock, SimpleQueue #----------------------------------------------------------- # Class Declaration #----------------------------------------------------------- class HTMLManagement(): def __init__(self): self.htmlHeaderCreated = False self.htmlFooterCreated = False self.htmlTabRefs = [] self.htmlTabNames = [] self.htmlTabIcons = [] self.testXMLfiles = [] #----------------------------------------------------------- # Setters and Getters #----------------------------------------------------------- def SetreseNB(self,rsenb): self.reseNB = rsenb def SetresUE(self,rsue): self.resUE = rsue def Setdesc(self, dsc): self.desc = dsc def SetstartTime(self, sttime): self.startTime = sttime def SettestCase_id(self, tcid): self.testCase_id = tcid def SetranRepository(self, repository): self.ranRepository = repository def GetranRepository(self): return self.ranRepository def SetranAllowMerge(self, merge): self.ranAllowMerge = merge def GetranAllowMerge(self): return self.ranAllowMerge def SetranBranch(self, branch): self.ranBranch = branch def GetranBranch(self): return self.ranBranch def SetranCommitID(self, commitid): self.ranCommitID = commitid def GetranCommitID(self): return self.ranCommitID def SetranTargetBranch(self, tbranch): self.ranTargetBranch = tbranch def GetranTargetBranch(self): return self.ranTargetBranch def SethtmlUEConnected(self, nbUEs): self.htmlUEConnected = nbUEs def SethtmlNb_Smartphones(self, nbUEs): self.htmlNb_Smartphones = nbUEs def SethtmlNb_CATM_Modules(self, nbUEs): self.htmlNb_CATM_Modules = nbUEs def SetnbTestXMLfiles(self, nb): self.nbTestXMLfiles = nb def SettestXMLfiles(self, xmlFile): self.testXMLfiles.append(xmlFile) def SethtmlTabRefs(self, tabRef): self.htmlTabRefs.append(tabRef) def SethtmlTabNames(self, tabName): self.htmlTabNames.append(tabName) def SethtmlTabIcons(self, tabIcon): self.htmlTabIcons.append(tabIcon) #----------------------------------------------------------- # HTML structure creation functions #----------------------------------------------------------- def CreateHtmlHeader(self, ADBIPAddress): if (not self.htmlHeaderCreated): logging.debug('\u001B[1m----------------------------------------\u001B[0m') logging.debug('\u001B[1m Creating HTML header \u001B[0m') logging.debug('\u001B[1m----------------------------------------\u001B[0m') self.htmlFile = open('test_results.html', 'w') self.htmlFile.write('\n') self.htmlFile.write('\n') self.htmlFile.write('\n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID\n') self.htmlFile.write('\n') self.htmlFile.write('
\n') self.htmlFile.write('
\n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write('
\n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID\n') self.htmlFile.write('
\n') self.htmlFile.write('
\n') self.htmlFile.write('
TEMPLATE_STAGE_NAME
\n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') if (self.ranAllowMerge): self.htmlFile.write(' \n') else: self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') if (self.ranAllowMerge): self.htmlFile.write(' \n') else: self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') if (self.ranAllowMerge): self.htmlFile.write(' \n') else: self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') if self.ranAllowMerge != '': commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True) commit_message = commit_message.strip() self.htmlFile.write(' \n') if (self.ranAllowMerge): self.htmlFile.write(' \n') else: self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') if (self.ranAllowMerge): self.htmlFile.write(' \n') self.htmlFile.write(' \n') if (self.ranTargetBranch == ''): self.htmlFile.write(' \n') else: self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write('
Build Start Time (UTC) TEMPLATE_BUILD_TIME
GIT Repository ' + self.ranRepository + '
Job Trigger Merge-RequestPush to Branch
Source Branch Branch' + self.ranBranch + '
Source Commit ID Commit ID ' + self.ranCommitID + '
Source Commit Message Commit Message ' + commit_message + '
Target Branch develop' + self.ranTargetBranch + '
\n') if (ADBIPAddress != 'none'): self.htmlFile.write('

' + str(self.htmlNb_Smartphones) + ' UE(s) is(are) connected to ADB bench server

\n') self.htmlFile.write('

' + str(self.htmlNb_CATM_Modules) + ' CAT-M UE(s) is(are) connected to bench server

\n') else: self.htmlUEConnected = 1 self.htmlFile.write('

1 OAI UE(s) is(are) connected to CI bench

\n') self.htmlFile.write('
\n') self.htmlFile.write(' \n') self.htmlFile.write('
\n') self.htmlFile.close() def CreateHtmlTabHeader(self): if (not self.htmlHeaderCreated): if (not os.path.isfile('test_results.html')): self.CreateHtmlHeader('none') self.htmlFile = open('test_results.html', 'a') if (self.nbTestXMLfiles == 1): self.htmlFile.write('
\n') self.htmlFile.write('

Test Summary for ' + self.testXMLfiles[0] + '

\n') else: self.htmlFile.write('
\n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') i = 0 while (i < self.htmlUEConnected): self.htmlFile.write(' \n') i += 1 self.htmlFile.write(' \n') self.htmlFile.close() self.htmlHeaderCreated = True def CreateHtmlTabFooter(self, passStatus): if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): self.htmlFile = open('test_results.html', 'a') self.htmlFile.write(' \n') self.htmlFile.write(' \n') if passStatus: self.htmlFile.write(' \n') else: self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write('
Relative Time (ms)Test IdTest DescTest OptionsTest StatusUE' + str(i) + ' Status
Final Tab StatusPASS FAIL
\n') self.htmlFile.write('
\n') self.htmlFile.close() time.sleep(1) if passStatus: cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" subprocess.run(cmd, shell=True) else: cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" subprocess.run(cmd, shell=True) self.htmlFooterCreated = False def CreateHtmlFooter(self, passStatus): if (os.path.isfile('test_results.html')): logging.debug('\u001B[1m----------------------------------------\u001B[0m') logging.debug('\u001B[1m Creating HTML footer \u001B[0m') logging.debug('\u001B[1m----------------------------------------\u001B[0m') self.htmlFile = open('test_results.html', 'a') self.htmlFile.write('
\n') self.htmlFile.write('

\n') self.htmlFile.write(' \n') # GP machines = [ 'eNB', 'UE' ] # GP for machine in machines: #GP This needs to move back to main and be called before CreateHtmlFooter res = self.reseNB if res != -1: self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') res = self.resUE if res != -1: self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') if passStatus: self.htmlFile.write(' \n') else: self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write('
' + str('eNB') + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '
' + str('UE') + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '
Final StatusPASS FAIL
\n') self.htmlFile.write('

\n') self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') self.htmlFile.write('
\n') self.htmlFile.write('\n') self.htmlFile.close() def CreateHtmlRetrySeparator(self, cntnumfails): if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): self.htmlFile = open('test_results.html', 'a') self.htmlFile.write(' \n') self.htmlFile.write(' Try Run #' + str(cntnumfails) + '\n') self.htmlFile.write(' \n') self.htmlFile.close() def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): self.htmlFile = open('test_results.html', 'a') currentTime = int(round(time.time() * 1000)) - self.startTime self.htmlFile.write(' \n') self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') self.htmlFile.write(' ' + self.testCase_id + '\n') self.htmlFile.write(' ' + self.desc + '\n') self.htmlFile.write(' ' + str(options) + '\n') if (str(status) == 'OK'): self.htmlFile.write(' ' + str(status) + '\n') elif (str(status) == 'KO'): if (processesStatus == 0): self.htmlFile.write(' ' + str(status) + '\n') elif (processesStatus == ENB_PROCESS_FAILED): self.htmlFile.write(' KO - eNB process not found\n') elif (processesStatus == OAI_UE_PROCESS_FAILED): self.htmlFile.write(' KO - OAI UE process not found\n') elif (processesStatus == ENB_PROCESS_SEG_FAULT) or (processesStatus == OAI_UE_PROCESS_SEG_FAULT): self.htmlFile.write(' KO - ' + machine + ' process ended in Segmentation Fault\n') elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION): self.htmlFile.write(' KO - ' + machine + ' process ended in Assertion\n') elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE): self.htmlFile.write(' KO - ' + machine + ' process faced Real Time issue(s)\n') elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): self.htmlFile.write(' OK?\n') elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): self.htmlFile.write(' KO - ' + machine + ' Slave RRU could not synch\n') elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): self.htmlFile.write(' KO - UE could not sync\n') elif (processesStatus == HSS_PROCESS_FAILED): self.htmlFile.write(' KO - HSS process not found\n') elif (processesStatus == MME_PROCESS_FAILED): self.htmlFile.write(' KO - MME process not found\n') elif (processesStatus == SPGW_PROCESS_FAILED): self.htmlFile.write(' KO - SPGW process not found\n') elif (processesStatus == UE_IP_ADDRESS_ISSUE): self.htmlFile.write(' KO - Could not retrieve UE IP address\n') else: self.htmlFile.write(' ' + str(status) + '\n') else: self.htmlFile.write(' ' + str(status) + '\n') if (len(str(self.htmleNBFailureMsg)) > 2): cellBgColor = 'white' result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg) if result is not None: cellBgColor = 'red' else: result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg) if result is not None: cellBgColor = 'orange' self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') self.htmleNBFailureMsg = '' elif (len(str(self.htmlUEFailureMsg)) > 2): cellBgColor = 'white' result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg) if result is not None: cellBgColor = 'red' else: result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg) if result is not None: cellBgColor = 'orange' self.htmlFile.write('
' + self.htmlUEFailureMsg + '
\n') self.htmlUEFailureMsg = '' else: i = 0 while (i < self.htmlUEConnected): self.htmlFile.write(' -\n') i += 1 self.htmlFile.write(' \n') self.htmlFile.close() def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue): if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): self.htmlFile = open('test_results.html', 'a') currentTime = int(round(time.time() * 1000)) - self.startTime addOrangeBK = False self.htmlFile.write(' \n') self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') self.htmlFile.write(' ' + self.testCase_id + '\n') self.htmlFile.write(' ' + self.desc + '\n') self.htmlFile.write(' ' + str(options) + '\n') if (str(status) == 'OK'): self.htmlFile.write(' ' + str(status) + '\n') elif (str(status) == 'KO'): self.htmlFile.write(' ' + str(status) + '\n') else: addOrangeBK = True self.htmlFile.write(' ' + str(status) + '\n') i = 0 while (i < self.htmlUEConnected): if (i < ue_status): if (not ue_queue.empty()): if (addOrangeBK): self.htmlFile.write(' ' + str(ue_queue.get()).replace('white', 'orange') + '\n') else: self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') else: self.htmlFile.write(' -\n') else: self.htmlFile.write(' -\n') i += 1 self.htmlFile.write(' \n') self.htmlFile.close()