mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Allow XML test cases to specify one or more files with timing stats that define which container log paths to collect and analyze. AnalyzeRTStatsObject loops over the provided list, falling back to the default gNB files (nrL1_stats.log, nrMAC_stats.log) when none are specified. Assisted-by: Claude:claude-sonnet-4-6 Signed-off-by: Jaroslava Fiedlerova <jaroslava.fiedlerova@openairinterface.org>
151 lines
5.2 KiB
Python
151 lines
5.2 KiB
Python
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
|
|
|
#---------------------------------------------------------------------
|
|
# Python for CI of OAI-eNB + COTS-UE
|
|
#
|
|
# Required Python Version
|
|
# Python 3.x
|
|
#
|
|
# Required Python Package
|
|
# pexpect
|
|
#---------------------------------------------------------------------
|
|
|
|
#-----------------------------------------------------------
|
|
# Import
|
|
#-----------------------------------------------------------
|
|
import re # reg
|
|
import logging
|
|
import os
|
|
import time
|
|
|
|
#-----------------------------------------------------------
|
|
# OAI Testing modules
|
|
#-----------------------------------------------------------
|
|
import cls_cmd
|
|
import cls_analysis
|
|
from cls_ci_helper import archiveArtifact
|
|
|
|
#-----------------------------------------------------------
|
|
# Class Declaration
|
|
#-----------------------------------------------------------
|
|
class RANManagement():
|
|
|
|
def __init__(self):
|
|
|
|
self.repository = ''
|
|
self.branch = ''
|
|
self.merge = False
|
|
self.targetBranch = ''
|
|
self.workspace = ''
|
|
self.Initialize_eNB_args = ''
|
|
self.imageKind = ''
|
|
self.eNBOptions = ['', '', '']
|
|
self.eNBstatuses = [-1, -1, -1]
|
|
self.runtime_stats= ''
|
|
self.cmd_prefix = '' # prefix before {lte,nr}-softmodem
|
|
self.node = ''
|
|
self.command = ''
|
|
|
|
|
|
#-----------------------------------------------------------
|
|
# RAN management functions
|
|
#-----------------------------------------------------------
|
|
|
|
def InitializeeNB(self, ctx, node, HTML):
|
|
if not node:
|
|
raise ValueError(f"{node=}")
|
|
logging.debug('Starting eNB/gNB on server: ' + node)
|
|
|
|
lSourcePath = self.workspace
|
|
cmd = cls_cmd.getConnection(node)
|
|
|
|
# Initialize_eNB_args usually start with -O and followed by the location in repository
|
|
full_config_file = self.Initialize_eNB_args.replace('-O ','')
|
|
extra_options = ''
|
|
extIdx = full_config_file.find('.conf')
|
|
if (extIdx <= 0):
|
|
raise ValueError(f"no config file in {self.Initialize_eNB_args}")
|
|
extra_options = full_config_file[extIdx + 5:]
|
|
full_config_file = full_config_file[:extIdx + 5]
|
|
config_path, config_file = os.path.split(full_config_file)
|
|
|
|
logfile = f'{lSourcePath}/cmake_targets/enb.log'
|
|
cmd.cd(f"{lSourcePath}/cmake_targets/") # important: set wd so nrL1_stats.log etc are logged here
|
|
cmd.run(f'sudo -E stdbuf -o0 {self.cmd_prefix} {lSourcePath}/cmake_targets/ran_build/build/nr-softmodem -O {lSourcePath}/{full_config_file} {extra_options} > {logfile} 2>&1 &')
|
|
|
|
if extra_options != '':
|
|
self.eNBOptions = extra_options
|
|
|
|
enbDidSync = False
|
|
for _ in range(10):
|
|
time.sleep(5)
|
|
ret = cmd.run(f'grep --text -E --color=never -i "wait|sync|Starting|Started" {logfile}', reportNonZero=False)
|
|
result = re.search('got sync|Starting F1AP at CU', ret.stdout)
|
|
if result is not None:
|
|
enbDidSync = True
|
|
break
|
|
if not enbDidSync:
|
|
cmd.run(f'sudo killall -9 nr-softmodem') # in case it did not stop automatically
|
|
archiveArtifact(cmd, ctx, logfile)
|
|
|
|
cmd.close()
|
|
|
|
msg = f'{self.cmd_prefix} nr-softmodem -O {config_file} {extra_options}'
|
|
if enbDidSync:
|
|
logging.debug('\u001B[1m Initialize eNB/gNB Completed\u001B[0m')
|
|
HTML.CreateHtmlTestRowQueue(msg, 'OK', [])
|
|
else:
|
|
logging.error('\u001B[1;37;41m eNB/gNB logging system did not show got sync! \u001B[0m')
|
|
HTML.CreateHtmlTestRowQueue(msg, 'KO', [])
|
|
|
|
return enbDidSync
|
|
|
|
def TerminateeNB(self, ctx, node, HTML, to_analyze):
|
|
logging.debug('Stopping eNB/gNB on server: ' + node)
|
|
lSourcePath = self.workspace
|
|
cmd = cls_cmd.getConnection(node)
|
|
ret = cmd.run('ps -aux | grep --color=never -e softmodem | grep -v grep')
|
|
result = re.search('-softmodem', ret.stdout)
|
|
if result is not None:
|
|
cmd.run('sudo -S killall --signal SIGINT -r .*-softmodem')
|
|
time.sleep(6)
|
|
|
|
ret = cmd.run('ps -aux | grep --color=never -e softmodem | grep -v grep')
|
|
result = re.search('-softmodem', ret.stdout)
|
|
if result is not None:
|
|
cmd.run('sudo -S killall --signal SIGKILL -r .*-softmodem')
|
|
time.sleep(5)
|
|
HTML.CreateHtmlTestRowQueue(node, 'OK', ['Undeployment successful'])
|
|
|
|
# see InitializeeNB()
|
|
logfile = f'{lSourcePath}/cmake_targets/enb.log'
|
|
logdir = os.path.dirname(logfile)
|
|
|
|
file = archiveArtifact(cmd, ctx, logfile)
|
|
cmd.close()
|
|
if file is None:
|
|
logging.debug('\u001B[1;37;41m Could not copy xNB logfile to analyze it! \u001B[0m')
|
|
msg = 'Could not copy xNB logfile to analyze it!'
|
|
HTML.CreateHtmlTestRowQueue('N/A', 'KO', [msg])
|
|
return False
|
|
|
|
logging.debug('\u001B[1m Analyzing xNB logfile \u001B[0m ' + file)
|
|
service_desc = {}
|
|
service_desc["nr-softmodem"] = {'returncode': 0, 'logfile': file}
|
|
success = cls_analysis.AnalyzeServices(HTML, service_desc, to_analyze)
|
|
return success
|
|
|
|
def AnalyzeRTStats(self, HTML, node, ctx, thresholds):
|
|
logging.info(f'Analyzing realtime stats from server: {node}')
|
|
lSourcePath = self.workspace
|
|
|
|
logdir = f'{lSourcePath}/cmake_targets'
|
|
with cls_cmd.getConnection(node) as cmd:
|
|
l1_file = archiveArtifact(cmd, ctx, f"{logdir}/nrL1_stats.log")
|
|
mac_file = archiveArtifact(cmd, ctx, f"{logdir}/nrMAC_stats.log")
|
|
|
|
logging.info(f"check against thresholds from {thresholds}")
|
|
success, datalog_rt_stats = cls_analysis.Analysis.analyze_rt_stats(thresholds, [l1_file, mac_file])
|
|
HTML.CreateHtmlDataLogTable(datalog_rt_stats)
|
|
return success
|