main.py 31 KB
Newer Older
Raphael Defosseux's avatar
Raphael Defosseux committed
1
#/*
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# * 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
# */
21 22 23 24 25 26 27 28 29 30
#---------------------------------------------------------------------
# Python for CI of OAI-eNB + COTS-UE
#
#   Required Python Version
#     Python 3.x
#
#   Required Python Package
#     pexpect
#---------------------------------------------------------------------

31 32 33 34 35 36 37


#-----------------------------------------------------------
# Import Components
#-----------------------------------------------------------

import helpreadme as HELP
38 39
import constants as CONST

40

41 42 43 44 45
import cls_oaicitest            #main class for OAI CI test framework
import cls_physim               #class PhySim for physical simulators build and test
import cls_cots_ue              #class CotsUe for Airplane mode control
import cls_containerize         #class Containerize for all container-based operations on RAN/UE objects
import cls_static_code_analysis #class for static code analysis
hardy's avatar
hardy committed
46
import cls_ci_ueinfra			#class defining the multi Ue infrastrucure
47
import cls_physim1          #class PhySim for physical simulators deploy and run
48

49 50 51 52 53
import sshconnection 
import epc
import ran
import html

54

55
#-----------------------------------------------------------
56
# Import Libs
57 58 59
#-----------------------------------------------------------
import sys		# arg
import re		# reg
60
import pexpect	# pexpect
61 62
import time		# sleep
import os
63
import subprocess
64 65 66 67
import xml.etree.ElementTree as ET
import logging
import datetime
import signal
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
68
from multiprocessing import Process, Lock, SimpleQueue
69
logging.basicConfig(
70 71
	level=logging.DEBUG,
	format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s"
72 73
)

74

75

76 77 78 79 80 81 82

#-----------------------------------------------------------
# General Functions
#-----------------------------------------------------------



83
def CheckClassValidity(xml_class_list,action,id):
84 85 86 87 88 89
	if action not in xml_class_list:
		logging.debug('ERROR: test-case ' + id + ' has unlisted class ' + action + ' ##CHECK xml_class_list.yml')
		resp=False
	else:
		resp=True
	return resp
90

91 92 93

#assigning parameters to object instance attributes (even if the attributes do not exist !!)
def AssignParams(params_dict):
94

95
	for key,value in params_dict.items():
96
		setattr(CiTestObj, key, value)
97 98 99 100 101 102
		setattr(RAN, key, value)
		setattr(HTML, key, value)
		setattr(ldpc, key, value)



103
def GetParametersFromXML(action):
104
	if action == 'Build_eNB' or action == 'Build_Image':
105
		RAN.Build_eNB_args=test.findtext('Build_eNB_args')
106
		CONTAINERS.imageKind=test.findtext('kind')
107 108
		forced_workspace_cleanup = test.findtext('forced_workspace_cleanup')
		if (forced_workspace_cleanup is None):
109
			RAN.Build_eNB_forced_workspace_cleanup=False
110
			CONTAINERS.forcedWorkspaceCleanup=False
111 112
		else:
			if re.match('true', forced_workspace_cleanup, re.IGNORECASE):
113
				RAN.Build_eNB_forced_workspace_cleanup=True
114
				CONTAINERS.forcedWorkspaceCleanup=True
115
			else:
116 117
				RAN.Build_eNB_forced_workspace_cleanup=True
				CONTAINERS.forcedWorkspaceCleanup=False
118 119 120
		eNB_instance=test.findtext('eNB_instance')
		if (eNB_instance is None):
			RAN.eNB_instance=0
121
			CONTAINERS.eNB_instance=0
122 123
		else:
			RAN.eNB_instance=int(eNB_instance)
124
			CONTAINERS.eNB_instance=int(eNB_instance)
125 126 127
		eNB_serverId=test.findtext('eNB_serverId')
		if (eNB_serverId is None):
			RAN.eNB_serverId[RAN.eNB_instance]='0'
128
			CONTAINERS.eNB_serverId[RAN.eNB_instance]='0'
129 130
		else:
			RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId
131
			CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]=eNB_serverId
132 133
		xmlBgBuildField = test.findtext('backgroundBuild')
		if (xmlBgBuildField is None):
134
			RAN.backgroundBuild=False
135 136
		else:
			if re.match('true', xmlBgBuildField, re.IGNORECASE):
137
				RAN.backgroundBuild=True
138
			else:
139
				RAN.backgroundBuild=False
140

141
	elif action == 'WaitEndBuild_eNB':
142
		RAN.Build_eNB_args=test.findtext('Build_eNB_args')
143 144
		eNB_instance=test.findtext('eNB_instance')
		if (eNB_instance is None):
Raphael Defosseux's avatar
Raphael Defosseux committed
145
			RAN.eNB_instance=0
146 147
		else:
			RAN.eNB_instance=int(eNB_instance)
148 149 150 151 152
		eNB_serverId=test.findtext('eNB_serverId')
		if (eNB_serverId is None):
			RAN.eNB_serverId[RAN.eNB_instance]='0'
		else:
			RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId
153

154
	elif action == 'Initialize_eNB':
155
		RAN.Initialize_eNB_args=test.findtext('Initialize_eNB_args')
156 157 158 159 160
		eNB_instance=test.findtext('eNB_instance')
		if (eNB_instance is None):
			RAN.eNB_instance=0
		else:
			RAN.eNB_instance=int(eNB_instance)
161 162 163 164 165
		eNB_serverId=test.findtext('eNB_serverId')
		if (eNB_serverId is None):
			RAN.eNB_serverId[RAN.eNB_instance]='0'
		else:
			RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId
hardy's avatar
hardy committed
166 167 168 169
			
		#local variable air_interface
		air_interface = test.findtext('air_interface')		
		if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']):
170
			RAN.air_interface[RAN.eNB_instance] = 'lte-softmodem'
hardy's avatar
hardy committed
171
		elif (air_interface.lower() in ['nr','lte']):
172
			RAN.air_interface[RAN.eNB_instance] = air_interface.lower() +'-softmodem'
hardy's avatar
hardy committed
173
		else :
174
			RAN.air_interface[RAN.eNB_instance] = 'ocp-enb'
175

176
	elif action == 'Terminate_eNB':
177
		eNB_instance=test.findtext('eNB_instance')
178
		if (eNB_instance is None):
179 180 181
			RAN.eNB_instance=0
		else:
			RAN.eNB_instance=int(eNB_instance)
182 183 184 185 186 187
		eNB_serverId=test.findtext('eNB_serverId')
		if (eNB_serverId is None):
			RAN.eNB_serverId[RAN.eNB_instance]='0'
		else:
			RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId

hardy's avatar
hardy committed
188 189 190
		#local variable air_interface
		air_interface = test.findtext('air_interface')		
		if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']):
191
			RAN.air_interface[RAN.eNB_instance] = 'lte-softmodem'
hardy's avatar
hardy committed
192
		elif (air_interface.lower() in ['nr','lte']):
193
			RAN.air_interface[RAN.eNB_instance] = air_interface.lower() +'-softmodem'
hardy's avatar
hardy committed
194
		else :
195
			RAN.air_interface[RAN.eNB_instance] = 'ocp-enb'
196

197 198 199 200 201 202 203
	elif action == 'Initialize_UE':
		ue_id = test.findtext('id')
		if (ue_id is None):
			CiTestObj.ue_id = ""
		else:
			CiTestObj.ue_id = ue_id

204 205 206 207 208 209
	elif action == 'Detach_UE':
		ue_id = test.findtext('id')
		if (ue_id is None):
			CiTestObj.ue_id = ""
		else:
			CiTestObj.ue_id = ue_id
210

211
	elif action == 'Attach_UE':
212 213
		nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach')
		if (nbMaxUEtoAttach is None):
214
			CiTestObj.nbMaxUEtoAttach = -1
215
		else:
216
			CiTestObj.nbMaxUEtoAttach = int(nbMaxUEtoAttach)
217

218
	elif action == 'CheckStatusUE':
219 220
		expectedNBUE = test.findtext('expectedNbOfConnectedUEs')
		if (expectedNBUE is None):
221
			CiTestObj.expectedNbOfConnectedUEs = -1
222
		else:
223
			CiTestObj.expectedNbOfConnectedUEs = int(expectedNBUE)
224

225
	elif action == 'Build_OAI_UE':
226
		CiTestObj.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args')
227 228 229
		CiTestObj.clean_repository = test.findtext('clean_repository')
		if (CiTestObj.clean_repository == 'false'):
			CiTestObj.clean_repository = False
230
		else:
231
			CiTestObj.clean_repository = True
Boris Djalal's avatar
Boris Djalal committed
232

233
	elif action == 'Initialize_OAI_UE':
234
		CiTestObj.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args')
235 236 237 238 239
		UE_instance = test.findtext('UE_instance')
		if (UE_instance is None):
			CiTestObj.UE_instance = 0
		else:
			CiTestObj.UE_instance = UE_instance
hardy's avatar
hardy committed
240 241 242 243
			
		#local variable air_interface
		air_interface = test.findtext('air_interface')		
		if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']):
244
			CiTestObj.air_interface = 'lte-uesoftmodem'
hardy's avatar
hardy committed
245
		elif (air_interface.lower() in ['nr','lte']):
246
			CiTestObj.air_interface = air_interface.lower() +'-uesoftmodem'
hardy's avatar
hardy committed
247
		else :
248 249
			#CiTestObj.air_interface = 'ocp-enb'
			logging.error('OCP UE -- NOT SUPPORTED')
Boris Djalal's avatar
Boris Djalal committed
250

251
	elif action == 'Terminate_OAI_UE':
252 253
		UE_instance=test.findtext('UE_instance')
		if (UE_instance is None):
254
			CiTestObj.UE_instance = '0'
255 256
		else:
			CiTestObj.UE_instance = int(UE_instance)
257 258 259 260 261 262 263 264 265 266
		
		#local variable air_interface
		air_interface = test.findtext('air_interface')		
		if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']):
			CiTestObj.air_interface = 'lte-uesoftmodem'
		elif (air_interface.lower() in ['nr','lte']):
			CiTestObj.air_interface = air_interface.lower() +'-uesoftmodem'
		else :
			#CiTestObj.air_interface = 'ocp-enb'
			logging.error('OCP UE -- NOT SUPPORTED')
Boris Djalal's avatar
Boris Djalal committed
267

268
	elif (action == 'Ping') or (action == 'Ping_CatM_module'):
269 270
		CiTestObj.ping_args = test.findtext('ping_args')
		CiTestObj.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold')
271 272 273 274 275
		ue_id = test.findtext('id')
		if (ue_id is None):
			CiTestObj.ue_id = ""
		else:
			CiTestObj.ue_id = ue_id
276

277
	elif action == 'Iperf':
278
		CiTestObj.iperf_args = test.findtext('iperf_args')
279 280 281 282 283 284
		ue_id = test.findtext('id')
		if (ue_id is None):
			CiTestObj.ue_id = ""
		else:
			CiTestObj.ue_id = ue_id
		CiTestObj.iperf_direction = test.findtext('direction')#used for modules only	
285 286 287 288
		CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold')
		CiTestObj.iperf_profile = test.findtext('iperf_profile')
		if (CiTestObj.iperf_profile is None):
			CiTestObj.iperf_profile = 'balanced'
289
		else:
290 291 292
			if CiTestObj.iperf_profile != 'balanced' and CiTestObj.iperf_profile != 'unbalanced' and CiTestObj.iperf_profile != 'single-ue':
				logging.debug('ERROR: test-case has wrong profile ' + CiTestObj.iperf_profile)
				CiTestObj.iperf_profile = 'balanced'
293 294 295
		CiTestObj.iperf_options = test.findtext('iperf_options')
		if (CiTestObj.iperf_options is None):
			CiTestObj.iperf_options = 'check'
296
		else:
297 298 299
			if CiTestObj.iperf_options != 'check' and CiTestObj.iperf_options != 'sink':
				logging.debug('ERROR: test-case has wrong option ' + CiTestObj.iperf_options)
				CiTestObj.iperf_options = 'check'
300

301
	elif action == 'IdleSleep':
302 303
		string_field = test.findtext('idle_sleep_time_in_sec')
		if (string_field is None):
304
			CiTestObj.idle_sleep_time = 5
305
		else:
306
			CiTestObj.idle_sleep_time = int(string_field)
307

308
	elif action == 'Perform_X2_Handover':
309 310
		string_field = test.findtext('x2_ho_options')
		if (string_field is None):
311
			CiTestObj.x2_ho_options = 'network'
312 313 314
		else:
			if string_field != 'network':
				logging.error('ERROR: test-case has wrong option ' + string_field)
315
				CiTestObj.x2_ho_options = 'network'
316
			else:
317
				CiTestObj.x2_ho_options = string_field
318

319
	elif action == 'Build_PhySim':
320
		ldpc.buildargs  = test.findtext('physim_build_args')
Remi Hardy's avatar
Remi Hardy committed
321 322 323 324 325 326 327 328
		forced_workspace_cleanup = test.findtext('forced_workspace_cleanup')
		if (forced_workspace_cleanup is None):
			ldpc.forced_workspace_cleanup=False
		else:
			if re.match('true', forced_workspace_cleanup, re.IGNORECASE):
				ldpc.forced_workspace_cleanup=True
			else:
				ldpc.forced_workspace_cleanup=False
329

330 331 332 333 334
	elif action == 'Initialize_MME':
		string_field = test.findtext('option')
		if (string_field is not None):
			EPC.mmeConfFile = string_field

335 336 337 338 339
	elif action == 'Deploy_EPC':
		string_field = test.findtext('parameters')
		if (string_field is not None):
			EPC.yamlPath = string_field

340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
	elif action == 'Deploy_Object' or action == 'Undeploy_Object':
		eNB_instance=test.findtext('eNB_instance')
		if (eNB_instance is None):
			CONTAINERS.eNB_instance=0
		else:
			CONTAINERS.eNB_instance=int(eNB_instance)
		eNB_serverId=test.findtext('eNB_serverId')
		if (eNB_serverId is None):
			CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]='0'
		else:
			CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]=eNB_serverId
		string_field = test.findtext('yaml_path')
		if (string_field is not None):
			CONTAINERS.yamlPath[CONTAINERS.eNB_instance] = string_field


356
	else: # ie action == 'Run_PhySim':
357
		ldpc.runargs = test.findtext('physim_run_args')
358
		
359

360 361 362 363 364 365 366 367 368 369 370 371
#check if given test is in list
#it is in list if one of the strings in 'list' is at the beginning of 'test'
def test_in_list(test, list):
	for check in list:
		check=check.replace('+','')
		if (test.startswith(check)):
			return True
	return False

def receive_signal(signum, frame):
	sys.exit(1)

372 373 374 375 376





377
#-----------------------------------------------------------
378
# MAIN PART
379
#-----------------------------------------------------------
380 381 382

#loading xml action list from yaml
import yaml
383
xml_class_list_file='xml_class_list.yml'
hardy's avatar
hardy committed
384
if (os.path.isfile(xml_class_list_file)):
385 386 387
	yaml_file=xml_class_list_file
elif (os.path.isfile('ci-scripts/'+xml_class_list_file)):
	yaml_file='ci-scripts/'+xml_class_list_file
388 389 390
else:
	logging.error("XML action list yaml file cannot be found")
	sys.exit("XML action list yaml file cannot be found")
Remi Hardy's avatar
Remi Hardy committed
391

392 393 394 395 396
with open(yaml_file,'r') as f:
    # The FullLoader parameter handles the conversion-$
    #from YAML scalar values to Python dictionary format$
    xml_class_list = yaml.load(f,Loader=yaml.FullLoader)

hardy's avatar
hardy committed
397

hardy's avatar
hardy committed
398 399 400 401 402 403 404 405 406 407

#loading UE infrastructure from yaml
ue_infra_file='ci_ueinfra.yaml'
if (os.path.isfile(ue_infra_file)):
	yaml_file=ue_infra_file
elif (os.path.isfile('ci-scripts/'+ue_infra_file)):
	yaml_file='ci-scripts/'+ue_infra_file
else:
	logging.error("UE infrastructure yaml file cannot be found")
	sys.exit("UE infrastructure file cannot be found")
408
InfraUE=cls_ci_ueinfra.InfraUE() #initialize UE infrastructure class
hardy's avatar
hardy committed
409
InfraUE.Get_UE_Infra(yaml_file) #read the UE infra, filename is hardcoded and unique for the moment but should be passed as parameter from the test suite
410 411


412

413
mode = ''
414

415
CiTestObj = cls_oaicitest.OaiCiTest()
416 417 418 419 420
 
SSH = sshconnection.SSHConnection()
EPC = epc.EPCManagement()
RAN = ran.RANManagement()
HTML = html.HTMLManagement()
421
CONTAINERS = cls_containerize.Containerize()
422
SCA = cls_static_code_analysis.StaticCodeAnalysis()
423
PHYSIM = cls_physim1.PhySim()
424

425 426
ldpc=cls_physim.PhySim()    #create an instance for LDPC test using GPU or CPU build

427

428
#-----------------------------------------------------------
429
# Parsing Command Line Arguments
430 431
#-----------------------------------------------------------

432
import args_parse
Mohammed Ismail's avatar
Mohammed Ismail committed
433
py_param_file_present, py_params, mode = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP,SCA,PHYSIM)
434

435

436

437
#-----------------------------------------------------------
438
# TEMPORARY params management (UNUSED)
439 440 441
#-----------------------------------------------------------
#temporary solution for testing:
if py_param_file_present == True:
442 443
	AssignParams(py_params)

444

445 446 447
#-----------------------------------------------------------
# COTS UE instanciation
#-----------------------------------------------------------
448 449 450
#COTS_UE instanciation and ADB server init
#ue id and ue mode are retrieved from xml
COTS_UE=cls_cots_ue.CotsUe(CiTestObj.ADBIPAddress, CiTestObj.ADBUserName,CiTestObj.ADBPassword)
451 452


453
#-----------------------------------------------------------
454
# mode amd XML class (action) analysis
455
#-----------------------------------------------------------
456
cwd = os.getcwd()
457

458
if re.match('^TerminateeNB$', mode, re.IGNORECASE):
459
	if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '':
460
		HELP.GenericHelp(CONST.Version)
461
		sys.exit('Insufficient Parameter')
Raphael Defosseux's avatar
Raphael Defosseux committed
462
	RAN.eNB_instance=0
463
	RAN.eNB_serverId[0]='0'
464
	RAN.eNBSourceCodePath='/tmp/'
465
	RAN.TerminateeNB(HTML, EPC)
466
elif re.match('^TerminateUE$', mode, re.IGNORECASE):
467
	if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''):
468
		HELP.GenericHelp(CONST.Version)
469 470
		sys.exit('Insufficient Parameter')
	signal.signal(signal.SIGUSR1, receive_signal)
471
	CiTestObj.TerminateUE(HTML,COTS_UE)
Boris Djalal's avatar
Boris Djalal committed
472
elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE):
473
	if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '':
474
		HELP.GenericHelp(CONST.Version)
Boris Djalal's avatar
Boris Djalal committed
475 476
		sys.exit('Insufficient Parameter')
	signal.signal(signal.SIGUSR1, receive_signal)
477
	CiTestObj.TerminateOAIUE(HTML,RAN,COTS_UE,EPC)
478
elif re.match('^TerminateHSS$', mode, re.IGNORECASE):
479
	if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '':
480
		HELP.GenericHelp(CONST.Version)
481
		sys.exit('Insufficient Parameter')
482
	EPC.TerminateHSS(HTML)
483
elif re.match('^TerminateMME$', mode, re.IGNORECASE):
484
	if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '':
485
		HELP.GenericHelp(CONST.Version)
486
		sys.exit('Insufficient Parameter')
487
	EPC.TerminateMME(HTML)
488
elif re.match('^TerminateSPGW$', mode, re.IGNORECASE):
489
	if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath== '':
490
		HELP.GenericHelp(CONST.Version)
491
		sys.exit('Insufficient Parameter')
492
	EPC.TerminateSPGW(HTML)
493
elif re.match('^LogCollectBuild$', mode, re.IGNORECASE):
494
	if (RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''):
495
		HELP.GenericHelp(CONST.Version)
496
		sys.exit('Insufficient Parameter')
497
	CiTestObj.LogCollectBuild(RAN)
498
elif re.match('^LogCollecteNB$', mode, re.IGNORECASE):
499
	if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '':
500
		HELP.GenericHelp(CONST.Version)
501
		sys.exit('Insufficient Parameter')
502
	RAN.LogCollecteNB()
503
elif re.match('^LogCollectHSS$', mode, re.IGNORECASE):
504
	if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '':
505
		HELP.GenericHelp(CONST.Version)
506
		sys.exit('Insufficient Parameter')
507
	EPC.LogCollectHSS()
508
elif re.match('^LogCollectMME$', mode, re.IGNORECASE):
509
	if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '':
510
		HELP.GenericHelp(CONST.Version)
511
		sys.exit('Insufficient Parameter')
512
	EPC.LogCollectMME()
513
elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE):
514
	if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '':
515
		HELP.GenericHelp(CONST.Version)
516
		sys.exit('Insufficient Parameter')
517
	EPC.LogCollectSPGW()
518
elif re.match('^LogCollectPing$', mode, re.IGNORECASE):
519
	if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '':
520
		HELP.GenericHelp(CONST.Version)
521
		sys.exit('Insufficient Parameter')
522
	CiTestObj.LogCollectPing(EPC)
523
elif re.match('^LogCollectIperf$', mode, re.IGNORECASE):
524
	if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '':
525
		HELP.GenericHelp(CONST.Version)
526
		sys.exit('Insufficient Parameter')
527
	CiTestObj.LogCollectIperf(EPC)
Boris Djalal's avatar
Boris Djalal committed
528
elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE):
529
	if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '':
530
		HELP.GenericHelp(CONST.Version)
531
		sys.exit('Insufficient Parameter')
532
	CiTestObj.LogCollectOAIUE()
533
elif re.match('^InitiateHtml$', mode, re.IGNORECASE):
534
	if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''):
535
		HELP.GenericHelp(CONST.Version)
536 537
		sys.exit('Insufficient Parameter')
	count = 0
538
	foundCount = 0
539
	while (count < HTML.nbTestXMLfiles):
540
		#xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[count]
541
		xml_test_file = sys.path[0] + "/" + CiTestObj.testXMLfiles[count]
542
		if (os.path.isfile(xml_test_file)):
543 544 545 546
			try:
				xmlTree = ET.parse(xml_test_file)
			except:
				print("Error while parsing file: " + xml_test_file)
547
			xmlRoot = xmlTree.getroot()
548 549 550
			HTML.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count)))
			HTML.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='test-tab-' + str(count)))
			HTML.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign'))
551
			foundCount += 1
552
		count += 1
553 554
	if foundCount != HTML.nbTestXMLfiles:
		HTML.nbTestXMLfiles=foundCount
555 556 557 558 559 560
	
	if (CiTestObj.ADBIPAddress != 'none'):
		terminate_ue_flag = False
		CiTestObj.GetAllUEDevices(terminate_ue_flag)
		CiTestObj.GetAllCatMDevices(terminate_ue_flag)
		HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices))
561 562
		HTML.htmlNb_Smartphones=len(CiTestObj.UEDevices)
		HTML.htmlNb_CATM_Modules=len(CiTestObj.CatMDevices)
563
	HTML.CreateHtmlHeader(CiTestObj.ADBIPAddress)
564
elif re.match('^FinalizeHtml$', mode, re.IGNORECASE):
565 566 567 568
	logging.debug('\u001B[1m----------------------------------------\u001B[0m')
	logging.debug('\u001B[1m  Creating HTML footer \u001B[0m')
	logging.debug('\u001B[1m----------------------------------------\u001B[0m')

569 570
	CiTestObj.RetrieveSystemVersion('eNB',HTML,RAN)
	CiTestObj.RetrieveSystemVersion('UE',HTML,RAN)
571
	HTML.CreateHtmlFooter(CiTestObj.finalStatus)
572
elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE):
573
	logging.debug('\u001B[1m----------------------------------------\u001B[0m')
574
	logging.debug('\u001B[1m  Starting Scenario: ' + CiTestObj.testXMLfiles[0] + '\u001B[0m')
575
	logging.debug('\u001B[1m----------------------------------------\u001B[0m')
576
	if re.match('^TesteNB$', mode, re.IGNORECASE):
577
		if RAN.eNBIPAddress == '' or RAN.ranRepository == '' or RAN.ranBranch == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '' or EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '':
578
			HELP.GenericHelp(CONST.Version)
579 580
			if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '' or EPC.Type == '':
				HELP.EPCSrvHelp(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath, EPC.Type)
581 582 583 584
			if RAN.ranRepository == '':
				HELP.GitSrvHelp(RAN.ranRepository, RAN.ranBranch, RAN.ranCommitID, RAN.ranAllowMerge, RAN.ranTargetBranch)
			if RAN.eNBIPAddress == ''  or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '':
				HELP.eNBSrvHelp(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath)
585 586
			sys.exit('Insufficient Parameter')

587 588 589
		if (EPC.IPAddress!= '') and (EPC.IPAddress != 'none'):
			SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, cwd + "/tcp_iperf_stats.awk", "/tmp")
			SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, cwd + "/active_net_interfaces.awk", "/tmp")
590
	else:
591 592
		if CiTestObj.UEIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '':
			HELP.GenericHelp(CONST.Version)
593
			sys.exit('UE: Insufficient Parameter')
594

595
	#read test_case_list.xml file
596
	# if no parameters for XML file, use default value
597
	if (HTML.nbTestXMLfiles != 1):
598
		xml_test_file = cwd + "/test_case_list.xml"
599
	else:
600
		xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[0]
601 602 603 604 605 606

	xmlTree = ET.parse(xml_test_file)
	xmlRoot = xmlTree.getroot()

	exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='')
	requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='')
607 608 609
	if (HTML.nbTestXMLfiles == 1):
		HTML.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0'))
		HTML.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0'))
610
		repeatCount = xmlRoot.findtext('repeatCount',default='1')
611
		testStability = xmlRoot.findtext('TestUnstable',default='False')
612
		CiTestObj.repeatCounts.append(int(repeatCount))
613 614 615 616 617 618
		if testStability == 'True':
			CiTestObj.testUnstable = True
			HTML.testUnstable = True
			CiTestObj.testMinStableId = xmlRoot.findtext('TestMinId',default='999999')
			HTML.testMinStableId = CiTestObj.testMinStableId
			logging.debug('Test is tagged as Unstable -- starting from TestID ' + str(CiTestObj.testMinStableId))
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
	all_tests=xmlRoot.findall('testCase')

	exclusion_tests=exclusion_tests.split()
	requested_tests=requested_tests.split()

	#check that exclusion tests are well formatted
	#(6 digits or less than 6 digits followed by +)
	for test in exclusion_tests:
		if     (not re.match('^[0-9]{6}$', test) and
				not re.match('^[0-9]{1,5}\+$', test)):
			logging.debug('ERROR: exclusion test is invalidly formatted: ' + test)
			sys.exit(1)
		else:
			logging.debug(test)

	#check that requested tests are well formatted
	#(6 digits or less than 6 digits followed by +)
	#be verbose
	for test in requested_tests:
		if     (re.match('^[0-9]{6}$', test) or
				re.match('^[0-9]{1,5}\+$', test)):
			logging.debug('INFO: test group/case requested: ' + test)
		else:
			logging.debug('ERROR: requested test is invalidly formatted: ' + test)
			sys.exit(1)
644
	if (EPC.IPAddress != '') and (EPC.IPAddress != 'none'):
645
		CiTestObj.CheckFlexranCtrlInstallation(RAN,EPC,CONTAINERS)
646
		EPC.SetMmeIPAddress()
647 648 649 650 651 652 653

	#get the list of tests to be done
	todo_tests=[]
	for test in requested_tests:
		if    (test_in_list(test, exclusion_tests)):
			logging.debug('INFO: test will be skipped: ' + test)
		else:
654
			#logging.debug('INFO: test will be run: ' + test)
655
			todo_tests.append(test)
656

657
	signal.signal(signal.SIGUSR1, receive_signal)
658

659 660 661 662 663 664 665 666
	if (CiTestObj.ADBIPAddress != 'none'):
		terminate_ue_flag = False
		CiTestObj.GetAllUEDevices(terminate_ue_flag)
		CiTestObj.GetAllCatMDevices(terminate_ue_flag)
	else:
		CiTestObj.UEDevices.append('OAI-UE')
	HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices))
	HTML.CreateHtmlTabHeader()
667

668
	CiTestObj.FailReportCnt = 0
669
	RAN.prematureExit=True
670
	HTML.startTime=int(round(time.time() * 1000))
671 672
	while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.prematureExit:
		RAN.prematureExit=False
673
		# At every iteratin of the retry loop, a separator will be added
674 675
		# pass CiTestObj.FailReportCnt as parameter of HTML.CreateHtmlRetrySeparator
		HTML.CreateHtmlRetrySeparator(CiTestObj.FailReportCnt)
676
		for test_case_id in todo_tests:
677
			if RAN.prematureExit:
678
				break
679
			for test in all_tests:
680
				if RAN.prematureExit:
681
					break
682 683 684
				id = test.get('id')
				if test_case_id != id:
					continue
685
				CiTestObj.testCase_id = id
686 687
				HTML.testCase_id=CiTestObj.testCase_id
				EPC.testCase_id=CiTestObj.testCase_id
688
				CiTestObj.desc = test.findtext('desc')
689
				HTML.desc=CiTestObj.desc
690
				action = test.findtext('class')
691
				if (CheckClassValidity(xml_class_list, action, id) == False):
692
					continue
693
				CiTestObj.ShowTestID()
694 695
				GetParametersFromXML(action)
				if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE':
696
					if (CiTestObj.ADBIPAddress != 'none'):
697 698
						#in these cases, having no devices is critical, GetAllUEDevices function has to manage it as a critical error, reason why terminate_ue_flag is set to True
						terminate_ue_flag = True 
699 700 701 702 703
						# Now we stop properly the test-suite --> clean reporting
						status = CiTestObj.GetAllUEDevices(terminate_ue_flag)
						if not status:
							RAN.prematureExit = True
							break
704
				if action == 'Build_eNB':
Raphael Defosseux's avatar
Raphael Defosseux committed
705
					RAN.BuildeNB(HTML)
706
				elif action == 'WaitEndBuild_eNB':
Raphael Defosseux's avatar
Raphael Defosseux committed
707
					RAN.WaitBuildeNBisFinished(HTML)
708
				elif action == 'Initialize_eNB':
709 710
					check_eNB = False
					check_OAI_UE = False
711
					RAN.pStatus=CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC)
Raphael Defosseux's avatar
Raphael Defosseux committed
712
					RAN.InitializeeNB(HTML, EPC)
713
				elif action == 'Terminate_eNB':
Raphael Defosseux's avatar
Raphael Defosseux committed
714
					RAN.TerminateeNB(HTML, EPC)
715
				elif action == 'Initialize_UE':
hardy's avatar
hardy committed
716
					CiTestObj.InitializeUE(HTML,RAN, EPC, COTS_UE, InfraUE)
717
				elif action == 'Terminate_UE':
718
					CiTestObj.TerminateUE(HTML,COTS_UE)
719
				elif action == 'Attach_UE':
720
					CiTestObj.AttachUE(HTML,RAN,EPC,COTS_UE)
721
				elif action == 'Detach_UE':
722
					CiTestObj.DetachUE(HTML,RAN,EPC,COTS_UE,InfraUE)
723
				elif action == 'DataDisable_UE':
724
					CiTestObj.DataDisableUE(HTML)
725
				elif action == 'DataEnable_UE':
726
					CiTestObj.DataEnableUE(HTML)
727
				elif action == 'CheckStatusUE':
728
					CiTestObj.CheckStatusUE(HTML,RAN,EPC,COTS_UE)
729
				elif action == 'Build_OAI_UE':
730
					CiTestObj.BuildOAIUE(HTML)
731
				elif action == 'Initialize_OAI_UE':
732
					CiTestObj.InitializeOAIUE(HTML,RAN,EPC,COTS_UE)
733
				elif action == 'Terminate_OAI_UE':
Raphael Defosseux's avatar
Raphael Defosseux committed
734
					CiTestObj.TerminateOAIUE(HTML,RAN,COTS_UE,EPC)
735
				elif action == 'Initialize_CatM_module':
736
					CiTestObj.InitializeCatM(HTML)
737
				elif action == 'Terminate_CatM_module':
738
					CiTestObj.TerminateCatM(HTML)
739
				elif action == 'Attach_CatM_module':
Raphael Defosseux's avatar
Raphael Defosseux committed
740
					CiTestObj.AttachCatM(HTML,RAN,COTS_UE,EPC)
741
				elif action == 'Detach_CatM_module':
742
					CiTestObj.TerminateCatM(HTML)
743
				elif action == 'Ping_CatM_module':
Raphael Defosseux's avatar
Raphael Defosseux committed
744
					CiTestObj.PingCatM(HTML,RAN,EPC,COTS_UE,EPC)
745
				elif action == 'Ping':
746
					CiTestObj.Ping(HTML,RAN,EPC,COTS_UE, InfraUE)
747
				elif action == 'Iperf':
748
					CiTestObj.Iperf(HTML,RAN,EPC,COTS_UE, InfraUE)
749
				elif action == 'Reboot_UE':
750
					CiTestObj.RebootUE(HTML,RAN,EPC)
751
				elif action == 'Initialize_HSS':
Raphael Defosseux's avatar
Raphael Defosseux committed
752
					EPC.InitializeHSS(HTML)
753
				elif action == 'Terminate_HSS':
Raphael Defosseux's avatar
Raphael Defosseux committed
754
					EPC.TerminateHSS(HTML)
755
				elif action == 'Initialize_MME':
Raphael Defosseux's avatar
Raphael Defosseux committed
756
					EPC.InitializeMME(HTML)
757
				elif action == 'Terminate_MME':
Raphael Defosseux's avatar
Raphael Defosseux committed
758
					EPC.TerminateMME(HTML)
759
				elif action == 'Initialize_SPGW':
Raphael Defosseux's avatar
Raphael Defosseux committed
760
					EPC.InitializeSPGW(HTML)
761
				elif action == 'Terminate_SPGW':
Raphael Defosseux's avatar
Raphael Defosseux committed
762
					EPC.TerminateSPGW(HTML)
763
				elif action == 'Deploy_EPC':
Raphael Defosseux's avatar
Raphael Defosseux committed
764
					EPC.DeployEpc(HTML)
765
				elif action == 'Undeploy_EPC':
Raphael Defosseux's avatar
Raphael Defosseux committed
766
					EPC.UndeployEpc(HTML)
767
				elif action == 'Initialize_FlexranCtrl':
768
					CiTestObj.InitializeFlexranCtrl(HTML,RAN,EPC)
769
				elif action == 'Terminate_FlexranCtrl':
770
					CiTestObj.TerminateFlexranCtrl(HTML,RAN,EPC)
771
				elif action == 'IdleSleep':
772
					CiTestObj.IdleSleep(HTML)
773
				elif action == 'Perform_X2_Handover':
774
					CiTestObj.Perform_X2_Handover(HTML,RAN,EPC)
775 776 777 778
				elif action == 'Build_PhySim':
					HTML=ldpc.Build_PhySim(HTML,CONST)
					if ldpc.exitStatus==1:sys.exit()
				elif action == 'Run_PhySim':
Remi Hardy's avatar
Remi Hardy committed
779
					HTML=ldpc.Run_PhySim(HTML,CONST,id)
780
				elif action == 'Build_Image':
Raphael Defosseux's avatar
Raphael Defosseux committed
781
					CONTAINERS.BuildImage(HTML)
782
				elif action == 'Deploy_Object':
Raphael Defosseux's avatar
Raphael Defosseux committed
783
					CONTAINERS.DeployObject(HTML, EPC)
784
				elif action == 'Undeploy_Object':
Raphael Defosseux's avatar
Raphael Defosseux committed
785
					CONTAINERS.UndeployObject(HTML, RAN)
786 787
				elif action == 'Cppcheck_Analysis':
					SCA.CppCheckAnalysis(HTML)
788 789
				elif action == 'Deploy_Run_PhySim':
					PHYSIM.Deploy_PhySim(HTML)
790
				else:
791
					sys.exit('Invalid class (action) from xml')
792 793 794 795 796
				if not RAN.prematureExit:
					if CiTestObj.testCase_id == CiTestObj.testMinStableId:
						logging.debug('Scenario has reached minimal stability point')
						CiTestObj.testStabilityPointReached = True
						HTML.testStabilityPointReached = True
797
		CiTestObj.FailReportCnt += 1
798
	if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.prematureExit:
799
		logging.debug('Scenario failed ' + str(CiTestObj.FailReportCnt) + ' time(s)')
800
		HTML.CreateHtmlTabFooter(False)
801 802 803 804
		if CiTestObj.testUnstable and (CiTestObj.testStabilityPointReached or CiTestObj.testMinStableId == '999999'):
			logging.debug('Scenario has reached minimal stability point -- Not a Failure')
		else:
			sys.exit('Failed Scenario')
805
	else:
806
		logging.info('Scenario passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)')
807
		HTML.CreateHtmlTabFooter(True)
808 809
elif re.match('^LoadParams$', mode, re.IGNORECASE):
	pass
810
else:
811
	HELP.GenericHelp(CONST.Version)
812
	sys.exit('Invalid mode')
813
sys.exit(0)