main.py 160 KB
Newer Older
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 31 32 33 34 35
#---------------------------------------------------------------------
# Python for CI of OAI-eNB + COTS-UE
#
#   Required Python Version
#     Python 3.x
#
#   Required Python Package
#     pexpect
#---------------------------------------------------------------------

#-----------------------------------------------------------
# Version
#-----------------------------------------------------------
Version = '0.1'

36 37 38 39 40 41 42 43 44
#-----------------------------------------------------------
# Constants
#-----------------------------------------------------------
ALL_PROCESSES_OK = 0
ENB_PROCESS_FAILED = -1
ENB_PROCESS_OK = +1
ENB_PROCESS_SEG_FAULT = -11
ENB_PROCESS_ASSERTION = -12
ENB_PROCESS_REALTIME_ISSUE = -13
45
ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14
46 47 48
UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20
UE_PROCESS_COULD_NOT_SYNC = -21
UE_PROCESS_ASSERTION = -22
49 50 51 52 53 54 55 56
HSS_PROCESS_FAILED = -2
HSS_PROCESS_OK = +2
MME_PROCESS_FAILED = -3
MME_PROCESS_OK = +3
SPGW_PROCESS_FAILED = -4
SPGW_PROCESS_OK = +4
UE_IP_ADDRESS_ISSUE = -5

57 58 59
#-----------------------------------------------------------
# Import
#-----------------------------------------------------------
Boris Djalal's avatar
Boris Djalal committed
60
import sys		# arg
61 62 63 64
import re		# reg
import pexpect		# pexpect
import time		# sleep
import os
65
import subprocess
66 67 68 69
import xml.etree.ElementTree as ET
import logging
import datetime
import signal
Boris Djalal's avatar
Test  
Boris Djalal committed
70
#import platform
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
71
from multiprocessing import Process, Lock, SimpleQueue
72
logging.basicConfig(
73 74
	level=logging.DEBUG,
	format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s"
75 76 77 78 79 80 81 82 83 84
)

#-----------------------------------------------------------
# Class Declaration
#-----------------------------------------------------------
class SSHConnection():
	def __init__(self):
		self.eNBIPAddress = ''
		self.eNBRepository = ''
		self.eNBBranch = ''
Raphael Defosseux's avatar
Raphael Defosseux committed
85
		self.eNB_AllowMerge = False
86
		self.eNBCommitID = ''
87
		self.eNBTargetBranch = ''
88 89 90 91 92 93 94 95 96 97 98 99
		self.eNBUserName = ''
		self.eNBPassword = ''
		self.eNBSourceCodePath = ''
		self.EPCIPAddress = ''
		self.EPCUserName = ''
		self.EPCPassword = ''
		self.EPCSourceCodePath = ''
		self.EPCType = ''
		self.ADBIPAddress = ''
		self.ADBUserName = ''
		self.ADBPassword = ''
		self.testCase_id = ''
100 101
		self.testXMLfiles = []
		self.nbTestXMLfiles = 0
102 103 104
		self.desc = ''
		self.Build_eNB_args = ''
		self.Initialize_eNB_args = ''
Boris Djalal's avatar
WIP.  
Boris Djalal committed
105
		self.air_interface = 'lte'
106
		self.eNBLogFile = ''
107
		self.eNB_instance = ''
108 109
		self.eNBOptions = ''
		self.rruOptions = ''
110 111 112 113
		self.ping_args = ''
		self.ping_packetloss_threshold = ''
		self.iperf_args = ''
		self.iperf_packetloss_threshold = ''
114
		self.iperf_profile = ''
115
		self.nbMaxUEtoAttach = -1
116
		self.UEDevices = []
117
		self.CatMDevices = []
118
		self.UEIPAddresses = []
Raphael Defosseux's avatar
Raphael Defosseux committed
119 120 121
		self.htmlFile = ''
		self.htmlHeaderCreated = False
		self.htmlFooterCreated = False
122
		self.htmlUEConnected = -1
123
		self.htmleNBFailureMsg = ''
124 125 126 127 128 129
		self.picocom_closure = False
		self.idle_sleep_time = 0
		self.htmlTabRefs = []
		self.htmlTabNames = []
		self.htmlTabIcons = []
		self.finalStatus = False
130 131 132 133 134 135 136 137 138 139 140 141 142 143
		self.OsVersion = ''
		self.KernelVersion = ''
		self.UhdVersion = ''
		self.UsrpBoard = ''
		self.CpuNb = ''
		self.CpuModel = ''
		self.CpuMHz = ''
		self.UEIPAddress = ''
		self.UEUserName = ''
		self.UEPassword = ''
		self.UE_instance = ''
		self.UESourceCodePath = ''
		self.Build_OAI_UE_args = ''
		self.Initialize_OAI_UE_args = ''
Boris Djalal's avatar
WIP.  
Boris Djalal committed
144 145
		self.Initialize_OAI_eNB_args = ''
		self.clean_repository = True
146
		self.eNBOsVersion = ''
147
		
148
	def open(self, ipaddress, username, password):
149
		print('begin open ssh')
150 151
		print('ipaddress: ' + ipaddress)
		print('username: ' + username)
Boris Djalal's avatar
Test  
Boris Djalal committed
152 153
		if password == 'null':
			print('password is null')
154 155 156 157 158
		count = 0
		connect_status = False
		while count < 4:
			self.ssh = pexpect.spawn('ssh', [username + '@' + ipaddress], timeout = 5)
			self.sshresponse = self.ssh.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', 'Last login', pexpect.EOF, pexpect.TIMEOUT])
159
			if self.sshresponse == 0:
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
				self.ssh.sendline('yes')
				self.ssh.expect('password:')
				self.ssh.sendline(password)
				self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT])
				if self.sshresponse == 0:
					count = 10
					connect_status = True
				else:
					logging.debug('self.sshresponse = ' + str(self.sshresponse))
			elif self.sshresponse == 1:
				self.ssh.sendline(password)
				self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT])
				if self.sshresponse == 0:
					count = 10
					connect_status = True
				else:
					logging.debug('self.sshresponse = ' + str(self.sshresponse))
			elif self.sshresponse == 2:
				# Checking if we are really on the remote client defined by its IP address
				self.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:"', '\$', 5)
				result = re.search(str(ipaddress), str(self.ssh.before))
				if result is None:
					self.close()
				else:
					count = 10
					connect_status = True
186
			else:
187 188
				# debug output
				logging.debug(str(self.ssh.before))
189
				logging.debug('self.sshresponse = ' + str(self.sshresponse))
Raphael Defosseux's avatar
Raphael Defosseux committed
190 191 192
			# adding a tempo when failure
			if not connect_status:
				time.sleep(1)
193 194
			count += 1
		if connect_status:
195 196
			pass
		else:
197
			sys.exit('SSH Connection Failed')
198

199 200 201 202 203 204
	def command(self, commandline, expectedline, timeout):
		logging.debug(commandline)
		self.ssh.timeout = timeout
		self.ssh.sendline(commandline)
		self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT])
		if self.sshresponse == 0:
Raphael Defosseux's avatar
Raphael Defosseux committed
205
			return 0
206 207 208 209 210 211 212
		elif self.sshresponse == 1:
			logging.debug('\u001B[1;37;41m Unexpected EOF \u001B[0m')
			logging.debug('Expected Line : ' + expectedline)
			sys.exit(self.sshresponse)
		elif self.sshresponse == 2:
			logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m')
			logging.debug('Expected Line : ' + expectedline)
213
			result = re.search('ping |iperf |picocom', str(commandline))
Raphael Defosseux's avatar
Raphael Defosseux committed
214
			if result is None:
215
				logging.debug(str(self.ssh.before))
Raphael Defosseux's avatar
Raphael Defosseux committed
216 217 218
				sys.exit(self.sshresponse)
			else:
				return -1
219 220 221 222
		else:
			logging.debug('\u001B[1;37;41m Unexpected Others \u001B[0m')
			logging.debug('Expected Line : ' + expectedline)
			sys.exit(self.sshresponse)
223

224 225 226 227 228 229 230
	def close(self):
		self.ssh.timeout = 5
		self.ssh.sendline('exit')
		self.sshresponse = self.ssh.expect([pexpect.EOF, pexpect.TIMEOUT])
		if self.sshresponse == 0:
			pass
		elif self.sshresponse == 1:
231 232
			if not self.picocom_closure:
				logging.debug('\u001B[1;37;41m Unexpected TIMEOUT during closing\u001B[0m')
233
		else:
234
			logging.debug('\u001B[1;37;41m Unexpected Others during closing\u001B[0m')
235

236
	def copyin(self, ipaddress, username, password, source, destination):
237 238
		count = 0
		copy_status = False
Raphael Defosseux's avatar
Raphael Defosseux committed
239
		logging.debug('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination)
240 241 242
		while count < 10:
			scp_spawn = pexpect.spawn('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination, timeout = 100)
			scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT])
Raphael Defosseux's avatar
Raphael Defosseux committed
243
			if scp_response == 0:
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
				scp_spawn.sendline('yes')
				scp_spawn.expect('password:')
				scp_spawn.sendline(password)
				scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT])
				if scp_response == 0:
					count = 10
					copy_status = True
				else:
					logging.debug('1 - scp_response = ' + str(scp_response))
			elif scp_response == 1:
				scp_spawn.sendline(password)
				scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT])
				if scp_response == 0 or scp_response == 3:
					count = 10
					copy_status = True
				else:
					logging.debug('2 - scp_response = ' + str(scp_response))
			elif scp_response == 2:
				count = 10
				copy_status = True
Raphael Defosseux's avatar
Raphael Defosseux committed
264
			else:
265 266 267 268 269 270 271
				logging.debug('3 - scp_response = ' + str(scp_response))
			# adding a tempo when failure
			if not copy_status:
				time.sleep(1)
			count += 1
		if copy_status:
			return 0
Raphael Defosseux's avatar
Raphael Defosseux committed
272
		else:
273
			return -1
Raphael Defosseux's avatar
Raphael Defosseux committed
274

275
	def copyout(self, ipaddress, username, password, source, destination):
276 277
		count = 0
		copy_status = False
278
		logging.debug('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination)
279 280 281
		while count < 4:
			scp_spawn = pexpect.spawn('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination, timeout = 100)
			scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT])
282
			if scp_response == 0:
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
				scp_spawn.sendline('yes')
				scp_spawn.expect('password:')
				scp_spawn.sendline(password)
				scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT])
				if scp_response == 0:
					count = 10
					copy_status = True
				else:
					logging.debug('1 - scp_response = ' + str(scp_response))
			elif scp_response == 1:
				scp_spawn.sendline(password)
				scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT])
				if scp_response == 0 or scp_response == 3:
					count = 10
					copy_status = True
				else:
					logging.debug('2 - scp_response = ' + str(scp_response))
			elif scp_response == 2:
				count = 10
				copy_status = True
303
			else:
304 305 306 307 308 309
				logging.debug('3 - scp_response = ' + str(scp_response))
			# adding a tempo when failure
			if not copy_status:
				time.sleep(1)
			count += 1
		if copy_status:
310 311 312 313
			pass
		else:
			sys.exit('SCP failed')

314
	def BuildeNB(self):
Boris Djalal's avatar
Boris Djalal committed
315
		return()	
316 317 318 319 320 321
		if self.eNBIPAddress == '' or self.eNBRepository == '' or self.eNBBranch == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.eNBSourceCodePath == '':
			Usage()
			sys.exit('Insufficient Parameter')
		self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
		self.command('mkdir -p ' + self.eNBSourceCodePath, '\$', 5)
		self.command('cd ' + self.eNBSourceCodePath, '\$', 5)
322 323
		self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.eNBRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600)
		# Raphael: here add a check if git clone or git fetch went smoothly
324 325
		self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5)
		self.command('git config user.name "OAI Jenkins"', '\$', 5)
Boris Djalal's avatar
Boris Djalal committed
326
		##self.command('echo ' + self.eNBPassword + ' | sudo -S git clean -x -d -ff', '\$', 30)
327 328 329 330 331
		# if the commit ID is provided use it to point to it
		if self.eNBCommitID != '':
			self.command('git checkout -f ' + self.eNBCommitID, '\$', 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
Raphael Defosseux's avatar
Raphael Defosseux committed
332
		if (self.eNB_AllowMerge):
333 334 335 336 337 338
			if self.eNBTargetBranch == '':
				if (self.eNBBranch != 'develop') and (self.eNBBranch != 'origin/develop'):
					self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5)
			else:
				logging.debug('Merging with the target branch: ' + self.eNBTargetBranch)
				self.command('git merge --ff origin/' + self.eNBTargetBranch + ' -m "Temporary merge for CI"', '\$', 5)
339 340
		self.command('source oaienv', '\$', 5)
		self.command('cd cmake_targets', '\$', 5)
341 342
		self.command('mkdir -p log', '\$', 5)
		self.command('chmod 777 log', '\$', 5)
343
		# no need to remove in log (git clean did the trick)
344
		self.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee -a compile_oai_enb.log', 'Bypassing the Tests', 600)
345 346 347
		self.command('mkdir -p build_log_' + self.testCase_id, '\$', 5)
		self.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5)
		self.command('mv compile_oai_enb.log ' + 'build_log_' + self.testCase_id, '\$', 5)
348
		self.close()
349
		self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK)
350

351
	def BuildOAIUE(self):
Boris Djalal's avatar
Boris Djalal committed
352
		return()
Boris Djalal's avatar
Boris Djalal committed
353
		if self.UEIPAddress == '' or self.eNBRepository == '' or self.eNBBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '':
354 355 356 357 358 359 360 361 362
			Usage()
			sys.exit('Insufficient Parameter')
		self.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
		self.command('mkdir -p ' + self.UESourceCodePath, '\$', 5)
		self.command('cd ' + self.UESourceCodePath, '\$', 5)
		self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.eNBRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600)
		# here add a check if git clone or git fetch went smoothly
		self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5)
		self.command('git config user.name "OAI Jenkins"', '\$', 5)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
363
		if self.clean_repository:
Boris Djalal's avatar
Boris Djalal committed
364 365
			pass
			##self.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30)
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
		# if the commit ID is provided use it to point to it
		if self.eNBCommitID != '':
			self.command('git checkout -f ' + self.eNBCommitID, '\$', 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
		if (self.eNB_AllowMerge):
			if self.eNBTargetBranch == '':
				if (self.eNBBranch != 'develop') and (self.eNBBranch != 'origin/develop'):
					self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5)
			else:
				logging.debug('Merging with the target branch: ' + self.eNBTargetBranch)
				self.command('git merge --ff origin/' + self.eNBTargetBranch + ' -m "Temporary merge for CI"', '\$', 5)
		self.command('source oaienv', '\$', 5)
		self.command('cd cmake_targets', '\$', 5)
		self.command('mkdir -p log', '\$', 5)
		self.command('chmod 777 log', '\$', 5)
		# no need to remove in log (git clean did the trick)
		self.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee -a compile_oai_ue.log', 'Bypassing the Tests', 600)
		self.command('mkdir -p build_log_' + self.testCase_id, '\$', 5)
		self.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5)
		self.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5)
		self.close()
		self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE')


391 392 393 394 395 396 397
	def InitializeHSS(self):
		if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '':
			Usage()
			sys.exit('Insufficient Parameter')
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
		if re.match('OAI', self.EPCType, re.IGNORECASE):
			logging.debug('Using the OAI EPC HSS')
398
			self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
399 400
			self.command('source oaienv', '\$', 5)
			self.command('cd scripts', '\$', 5)
401
			self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35)
402 403
		else:
			logging.debug('Using the ltebox simulated HSS')
404 405 406 407
			self.command('if [ -d ' + self.EPCSourceCodePath + '/scripts ]; then echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5)
			self.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5)
			self.command('cd /opt/hss_sim0609', '\$', 5)
			self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5)
408
			#to use daemon on CentOS we need to source the function
Boris Djalal's avatar
Test  
Boris Djalal committed
409 410 411
			#linux_distro = platform.linux_distribution()[0]
			#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
				#self.command('source /etc/init.d/functions', '\$', 5)
412 413
			self.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real  ', '\$', 5)
		self.close()
414
		self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK)
415

416 417 418 419 420 421
	def InitializeMME(self):
		if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '':
			Usage()
			sys.exit('Insufficient Parameter')
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
		if re.match('OAI', self.EPCType, re.IGNORECASE):
422
			self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
423 424
			self.command('source oaienv', '\$', 5)
			self.command('cd scripts', '\$', 5)
425
			self.command('stdbuf -o0 hostname', '\$', 5)
426 427 428 429 430
			result = re.search('hostname\\\\r\\\\n(?P<host_name>[a-zA-Z0-9\-\_]+)\\\\r\\\\n', str(self.ssh.before))
			if result is None:
				logging.debug('\u001B[1;37;41m Hostname Not Found! \u001B[0m')
				sys.exit(1)
			host_name = result.group('host_name')
431
			self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + self.testCase_id + '.log &', 'MME app initialization complete', 100)
432
		else:
433
			self.command('cd /opt/ltebox/tools', '\$', 5)
434 435
			self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_mme', '\$', 5)
		self.close()
436
		self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK)
437 438 439

	def InitializeSPGW(self):
		if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '':
440 441
			Usage()
			sys.exit('Insufficient Parameter')
442 443
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
		if re.match('OAI', self.EPCType, re.IGNORECASE):
444
			self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
445 446
			self.command('source oaienv', '\$', 5)
			self.command('cd scripts', '\$', 5)
447
			self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + self.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30)
448
		else:
449
			self.command('cd /opt/ltebox/tools', '\$', 5)
450 451
			self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_xGw', '\$', 5)
		self.close()
452
		self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK)
453 454 455

	def InitializeeNB(self):
		if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.eNBSourceCodePath == '':
456 457 458
			Usage()
			sys.exit('Insufficient Parameter')
		initialize_eNB_flag = True
Raphael Defosseux's avatar
Raphael Defosseux committed
459 460 461
		pStatus = self.CheckProcessExist(initialize_eNB_flag)
		if (pStatus < 0):
			self.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', pStatus)
462
			self.CreateHtmlTabFooter(False)
Raphael Defosseux's avatar
Raphael Defosseux committed
463
			sys.exit(1)
464 465 466 467 468 469 470 471 472 473 474 475
		# If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB
		result = re.search('T_stdout', str(self.Initialize_eNB_args))
		if result is not None:
			self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
			self.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5)
			result = re.search('interfaceToUse=(?P<eth_interface>[a-zA-Z0-9\-\_]+)done', str(self.ssh.before))
			if result is not None:
				eth_interface = result.group('eth_interface')
				logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m')
				self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/enb_' + self.testCase_id + '_s1log.pcap', '\$', 5)
				self.command('echo $USER; nohup sudo tshark -f "host ' + self.eNBIPAddress +'" -i ' + eth_interface + ' -w /tmp/enb_' + self.testCase_id + '_s1log.pcap > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5)
			self.close()
476 477
		self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
		self.command('cd ' + self.eNBSourceCodePath, '\$', 5)
478 479
		# Initialize_eNB_args usually start with -O and followed by the location in repository
		full_config_file = self.Initialize_eNB_args.replace('-O ','')
480
		extra_options = ''
481 482 483
		extIdx = full_config_file.find('.conf')
		if (extIdx > 0):
			extra_options = full_config_file[extIdx + 5:]
484 485 486 487 488 489 490 491
			# if tracer options is on, compiling and running T Tracer
			result = re.search('T_stdout', str(extra_options))
			if result is not None:
				logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m')
				self.command('cd common/utils/T/tracer', '\$', 5)
				self.command('make', '\$', 10)
				self.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', self.eNBUserName, 5)
				self.command('cd ' + self.eNBSourceCodePath, '\$', 5)
492 493 494 495
			full_config_file = full_config_file[:extIdx + 5]
			config_path, config_file = os.path.split(full_config_file)
		else:
			sys.exit('Insufficient Parameter')
496
		ci_full_config_file = config_path + '/ci-' + config_file
497 498 499 500
		rruCheck = False
		result = re.search('rru', str(config_file))
		if result is not None:
			rruCheck = True
501 502 503 504 505 506 507
		# do not reset board twice in IF4.5 case
		result = re.search('rru|enb', str(config_file))
		if result is not None:
			self.command('echo ' + self.eNBPassword + ' | sudo -S uhd_find_devices', '\$', 5)
			result = re.search('type: b200', str(self.ssh.before))
			if result is not None:
				logging.debug('Found a B2xx device --> resetting it')
Boris Djalal's avatar
Test.  
Boris Djalal committed
508
				##self.command('echo ' + self.eNBPassword + ' | sudo -S sudo b2xx_fx3_utils --reset-device', '\$', 5)
509
				# Reloading FGPA bin firmware
Boris Djalal's avatar
Test.  
Boris Djalal committed
510
				##self.command('echo ' + self.eNBPassword + ' | sudo -S uhd_find_devices', '\$', 5)
511 512
		# Make a copy and adapt to EPC / eNB IP addresses
		self.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5)
513 514
		self.command('sed -i -e \'s/CI_MME_IP_ADDR/' + self.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2);
		self.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2);
515
		# Launch eNB with the modified config file
516 517
		self.command('source oaienv', '\$', 5)
		self.command('cd cmake_targets', '\$', 5)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
518
		self.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface + '-softmodem -O ' + self.eNBSourceCodePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh ', '\$', 5)
519
		self.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh ', '\$', 5)
Boris Djalal's avatar
Test.  
Boris Djalal committed
520
		##self.command('echo ' + self.eNBPassword + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5)				
Boris Djalal's avatar
Fix  
Boris Djalal committed
521
		#to use daemon on CentOS we need to source the function
Boris Djalal's avatar
Test  
Boris Djalal committed
522 523 524 525 526 527
		#linux_distro = platform.linux_distribution()[0]
		#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
		#self.command('source /etc/init.d/functions', '\$', 5)
		#use nohup instead of daemon
		#self.command('echo ' + self.eNBPassword + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + self.eNBSourceCodePath + '/cmake_targets -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
		self.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh' + ' > ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log' + ' 2>&1 &', self.eNBUserName, 5)		
528
		if not rruCheck:
529
			self.eNBLogFile = 'enb_' + self.testCase_id + '.log'
530 531
			if extra_options != '':
				self.eNBOptions = extra_options
532 533 534 535 536 537
		time.sleep(6)
		doLoop = True
		loopCounter = 10
		while (doLoop):
			loopCounter = loopCounter - 1
			if (loopCounter == 0):
538 539 540 541 542
				# In case of T tracer recording, we may need to kill it
				result = re.search('T_stdout', str(self.Initialize_eNB_args))
				if result is not None:
					self.command('killall --signal SIGKILL record', '\$', 5)
				self.close()
543
				doLoop = False
544
				logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m')
545
				self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK)
546 547 548 549 550 551 552 553 554 555 556 557 558
				self.CreateHtmlTabFooter(False)
				# In case of T tracer recording, we need to kill tshark on EPC side
				result = re.search('T_stdout', str(self.Initialize_eNB_args))
				if result is not None:
					self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
					logging.debug('\u001B[1m Stopping tshark \u001B[0m')
					self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5)
					self.close()
					time.sleep(1)
					pcap_log_file = 'enb_' + self.testCase_id + '_s1log.pcap'
					copyin_res = self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + pcap_log_file, '.')
					if (copyin_res == 0):
						self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, pcap_log_file, self.eNBSourceCodePath + '/cmake_targets/.')
559
				sys.exit(1)
560
			else:
561
				self.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4)
562 563 564 565
				if rruCheck:
					result = re.search('wait RUs', str(self.ssh.before))
				else:
					result = re.search('got sync', str(self.ssh.before))
Raphael Defosseux's avatar
Raphael Defosseux committed
566 567 568 569
				if result is None:
					time.sleep(6)
				else:
					doLoop = False
570 571
					if rruCheck and extra_options != '':
						self.rruOptions = extra_options
572
					self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK)
Raphael Defosseux's avatar
Raphael Defosseux committed
573
					logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m')
574

575 576
		self.close()

577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
	def InitializeUE_common(self, device_id):
		logging.debug('send adb commands')
		try:
			self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
			# The following commands are deprecated since we no longer work on Android 7+
			# self.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10)
			# self.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60)
			# a dedicated script has to be installed inside the UE
			# airplane mode on means call /data/local/tmp/off
			self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60)
			#airplane mode off means call /data/local/tmp/on
			logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m')
			self.close()
		except:
			os.kill(os.getppid(),signal.SIGUSR1)

	def InitializeUE(self):
		if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
			Usage()
			sys.exit('Insufficient Parameter')
		multi_jobs = []
		for device_id in self.UEDevices:
599
			p = Process(target = self.InitializeUE_common, args = (device_id,))
600 601 602 603 604
			p.daemon = True
			p.start()
			multi_jobs.append(p)
		for job in multi_jobs:
			job.join()
605
		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
606

607 608 609 610 611 612 613 614 615 616 617 618
	def InitializeOAIUE(self):
		if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '':
			Usage()
			sys.exit('Insufficient Parameter')
		#initialize_OAI_UE_flag = True
		#pStatus = self.CheckOAIUEProcessExist(initialize_OAI_UE_flag)
		#if (pStatus < 0):
		#	self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus)
		#	self.CreateHtmlTabFooter(False)
		#	sys.exit(1)
		self.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
		# b2xx_fx3_utils reset procedure
Boris Djalal's avatar
Test.  
Boris Djalal committed
619
		self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 10)
620 621
		result = re.search('type: b200', str(self.ssh.before))
		if result is not None:
Boris Djalal's avatar
Boris Djalal committed
622 623 624
			pass
			##logging.debug('Found a B2xx device --> resetting it')
			##self.command('echo ' + self.UEPassword + ' | sudo -S sudo b2xx_fx3_utils --reset-device', '\$', 5)
625
			# Reloading FGPA bin firmware
Boris Djalal's avatar
Boris Djalal committed
626
			##self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 5)
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
		else:
			logging.debug('Did not find any B2xx device')
		self.command('cd ' + self.UESourceCodePath, '\$', 5)
		# Initialize_OAI_UE_args usually start with -C and followed by the location in repository
		#full_config_file = self.Initialize_OAI_UE_args.replace('-O ','')
		#extIdx = full_config_file.find('.conf')
		#if (extIdx > 0):
		#	extra_options = full_config_file[extIdx + 5:]
		#	# if tracer options is on, compiling and running T Tracer
		#	result = re.search('T_stdout', str(extra_options))
		##	if result is not None:
		#		logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m')
		#		self.command('cd common/utils/T/tracer', '\$', 5)
		#		self.command('make', '\$', 10)
		#		self.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + self.UESourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', self.UEUserName, 5)
		#		self.command('cd ' + self.UESourceCodePath, '\$', 5)
		#	full_config_file = full_config_file[:extIdx + 5]
		#	config_path, config_file = os.path.split(full_config_file)
		#ci_full_config_file = config_path + '/ci-' + config_file
		#rruCheck = False
		#result = re.search('rru', str(config_file))
		#if result is not None:
		#	rruCheck = True
		## Make a copy and adapt to EPC / UE IP addresses
		#self.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5)
		#self.command('sed -i -e \'s/CI_UE_IP_ADDR/' + self.UEIPAddress + '/\' ' + ci_full_config_file, '\$', 2);
		# Launch UE with the modified config file
		self.command('source oaienv', '\$', 5)
Boris Djalal's avatar
Boris Djalal committed
655
		self.command('cd cmake_targets/ran_build/build', '\$', 5)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
656
		self.command('echo "ulimit -c unlimited && ./'+ self.air_interface +'-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5)
657 658
		self.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5)
		self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5)
Boris Djalal's avatar
Fix  
Boris Djalal committed
659
		#to use daemon on CentOS we need to source the function
Boris Djalal's avatar
Test  
Boris Djalal committed
660 661 662 663
		#linux_distro = platform.linux_distribution()[0]		
		#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
			#self.command('source /etc/init.d/functions', '\$', 5)
		#use nohup instead of daemon
Boris Djalal's avatar
Boris Djalal committed
664
		##self.command('echo $USER; nohup sudo ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh' + ' > ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ' + ' 2>&1 &', self.UEUserName, 5)
Boris Djalal's avatar
Test  
Boris Djalal committed
665
		#self.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/ran_build/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5)
666
		self.UELogFile = + 'ue_' + self.testCase_id + '.log'
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
		time.sleep(6)
		self.command('cd ../..', '\$', 5)
		doLoop = True
		loopCounter = 10
		while (doLoop):
			loopCounter = loopCounter - 1
			if (loopCounter == 0):
				# In case of T tracer recording, we may need to kill it
				#result = re.search('T_stdout', str(self.Initialize_OAI_UE_args))
				#if result is not None:
				#	self.command('killall --signal SIGKILL record', '\$', 5)
				self.close()
				doLoop = False
				logging.error('\u001B[1;37;41m UE logging system did not show got sync! \u001B[0m')
				self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE')
				self.CreateHtmlTabFooter(False)
				## In case of T tracer recording, we need to kill tshark on EPC side
				#result = re.search('T_stdout', str(self.Initialize_OAI_UE_args))
				#if result is not None:
				#	self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
				#	logging.debug('\u001B[1m Stopping tshark \u001B[0m')
				#	self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5)
				#	self.close()
				#	time.sleep(1)
				#	pcap_log_file = 'enb_' + self.testCase_id + '_s1log.pcap'
				#	copyin_res = self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + pcap_log_file, '.')
				#	if (copyin_res == 0):
				#		self.copyout(self.UEIPAddress, self.UEUserName, self.UEPassword, pcap_log_file, self.UESourceCodePath + '/cmake_targets/.')
				sys.exit(1)
			else:
697
				self.command('stdbuf -o0 cat ' + self.UELogFile + ' | egrep --text --color=never -i "wait|sync"', '\$', 4)
698 699 700 701 702 703 704 705 706
				result = re.search('got sync', str(self.ssh.before))
				if result is None:
					time.sleep(6)
				else:
					doLoop = False
					self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE')
					logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m')
		self.close()

Boris Djalal's avatar
WIP.  
Boris Djalal committed
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
	def InitializeOAIeNB(self):
		if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.eNBSourceCodePath == '':
			Usage()
			sys.exit('Insufficient Parameter')
		#initialize_OAI_eNB_flag = True
		#pStatus = self.CheckOAIeNBProcessExist(initialize_OAI_eNB_flag)
		#if (pStatus < 0):
		#	self.CreateHtmlTestRow(self.Initialize_OAI_eNB_args, 'KO', pStatus)
		#	self.CreateHtmlTabFooter(False)
		#	sys.exit(1)
		self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
		self.command('cd ' + self.eNBSourceCodePath, '\$', 5)
		# Initialize_OAI_eNB_args usually start with -C and followed by the location in repository
		#full_config_file = self.Initialize_OAI_eNB_args.replace('-O ','')
		#extIdx = full_config_file.find('.conf')
		#if (extIdx > 0):
		#	extra_options = full_config_file[extIdx + 5:]
		#	# if tracer options is on, compiling and running T Tracer
		#	result = re.search('T_stdout', str(extra_options))
		##	if result is not None:
		#		logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m')
		#		self.command('cd common/utils/T/tracer', '\$', 5)
		#		self.command('make', '\$', 10)
		#		self.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', self.eNBUserName, 5)
		#		self.command('cd ' + self.eNBSourceCodePath, '\$', 5)
		#	full_config_file = full_config_file[:extIdx + 5]
		#	config_path, config_file = os.path.split(full_config_file)
		#ci_full_config_file = config_path + '/ci-' + config_file
		#rruCheck = False
		#result = re.search('rru', str(config_file))
		#if result is not None:
		#	rruCheck = True
		## Make a copy and adapt to EPC / eNB IP addresses
		#self.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5)
		#self.command('sed -i -e \'s/CI_eNB_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2);
		# Launch eNB with the modified config file
		self.command('source oaienv', '\$', 5)
Boris Djalal's avatar
Boris Djalal committed
744
		self.command('cd cmake_targets/ran_build/build', '\$', 5)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
745
		#self.command('echo "ulimit -c unlimited && ./' + self.air_interface + '-softmodem ' + self.Initialize_OAI_eNB_args + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
746 747
		self.eNBLogFile = 'enb_' + self.testCase_id + '.log'
		self.command('echo "ulimit -c unlimited && ./' + self.air_interface + '-softmodem ' + self.Initialize_OAI_eNB_args + '|& tee ' + self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFile + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
748
		self.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
Boris Djalal's avatar
Boris Djalal committed
749
		##self.command('echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log', '\$', 5)
Boris Djalal's avatar
Fix  
Boris Djalal committed
750
		#to use daemon on CentOS we need to source the function
Boris Djalal's avatar
Test  
Boris Djalal committed
751 752 753 754
		#linux_distro = platform.linux_distribution()[0]		
		#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
			#self.command('source /etc/init.d/functions', '\$', 5)
		#use nohup instead of daemon
Boris Djalal's avatar
Boris Djalal committed
755
		##self.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh' + ' > ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log' + ' 2>&1 &', self.eNBUserName, 5)
Boris Djalal's avatar
Test  
Boris Djalal committed
756
		#self.command('echo ' + self.eNBPassword + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + self.eNBSourceCodePath + '/cmake_targets/ran_build/build -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
757 758 759 760
		time.sleep(6)
		self.command('cd ../..', '\$', 5)
		doLoop = True
		loopCounter = 10
761
		print('gNB log file: ' + self.eNBLogFile)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787
		while (doLoop):
			loopCounter = loopCounter - 1
			if (loopCounter == 0):
				# In case of T tracer recording, we may need to kill it
				#result = re.search('T_stdout', str(self.Initialize_OAI_eNB_args))
				#if result is not None:
				#	self.command('killall --signal SIGKILL record', '\$', 5)
				self.close()
				doLoop = False
				logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m')
				self.CreateHtmlTestRow(self.Initialize_OAI_eNB_args, 'KO', ALL_PROCESSES_OK, 'OAI eNB')
				self.CreateHtmlTabFooter(False)
				## In case of T tracer recording, we need to kill tshark on EPC side
				#result = re.search('T_stdout', str(self.Initialize_OAI_eNB_args))
				#if result is not None:
				#	self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
				#	logging.debug('\u001B[1m Stopping tshark \u001B[0m')
				#	self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5)
				#	self.close()
				#	time.sleep(1)
				#	pcap_log_file = 'enb_' + self.testCase_id + '_s1log.pcap'
				#	copyin_res = self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + pcap_log_file, '.')
				#	if (copyin_res == 0):
				#		self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, pcap_log_file, self.eNBSourceCodePath + '/cmake_targets/.')
				sys.exit(1)
			else:
788 789 790 791
				print('current directory: ' + os.getcwd())
				self.command('pwd', '\$', 4)
				print('self.command pwd: ' + str(self.ssh.before))
				self.command('stdbuf -o0 cat ' + self.eNBLogFile + ' | egrep --text --color=never -i "wait|sync"', '\$', 4)
Boris Djalal's avatar
Fix.  
Boris Djalal committed
792
				#print(self.ssh.before)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
793 794 795 796 797 798 799 800 801
				result = re.search('got sync', str(self.ssh.before))
				if result is None:
					time.sleep(6)
				else:
					doLoop = False
					self.CreateHtmlTestRow(self.Initialize_OAI_eNB_args, 'OK', ALL_PROCESSES_OK, 'OAI eNB')
					logging.debug('\u001B[1m Initialize OAI eNB Completed\u001B[0m')
		self.close()

802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
	def checkDevTTYisUnlocked(self):
		self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
		count = 0
		while count < 5:
			self.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10)
			result = re.search('picocom', str(self.ssh.before))
			if result is None:
				count = 10
			else:
				time.sleep(5)
				count = count + 1
		self.close()

	def InitializeCatM(self):
		if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
			Usage()
			sys.exit('Insufficient Parameter')
		self.picocom_closure = True
		self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
		# dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S`
		self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10)
		self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10)
		time.sleep(1)
		# Calling twice AT to clear all buffers
		self.command('AT', 'OK|ERROR', 5)
		self.command('AT', 'OK', 5)
		# Disabling the Radio
		self.command('AT+CFUN=0', 'OK', 5)
		logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m')
		# Checking if auto-attach is enabled
		self.command('AT^AUTOATT?', 'OK', 5)
		result = re.search('AUTOATT: (?P<state>[0-9\-]+)', str(self.ssh.before))
		if result is not None:
			if result.group('state') is not None:
				autoAttachState = int(result.group('state'))
				if autoAttachState is not None:
					if autoAttachState == 0:
						self.command('AT^AUTOATT=1', 'OK', 5)
					logging.debug('\u001B[1m Auto-Attach enabled\u001B[0m')
		else:
			logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m')
		# Force closure of picocom but device might still be locked
		self.close()
		self.picocom_closure = False
		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
		self.checkDevTTYisUnlocked()

	def TerminateCatM(self):
		if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
			Usage()
			sys.exit('Insufficient Parameter')
		self.picocom_closure = True
		self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
		# dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S`
		self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10)
		self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10)
		time.sleep(1)
		# Calling twice AT to clear all buffers
		self.command('AT', 'OK|ERROR', 5)
		self.command('AT', 'OK', 5)
		# Disabling the Radio
		self.command('AT+CFUN=0', 'OK', 5)
		logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m')
		self.close()
		self.picocom_closure = False
		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
		self.checkDevTTYisUnlocked()

	def AttachCatM(self):
		if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
			Usage()
			sys.exit('Insufficient Parameter')
		self.picocom_closure = True
		self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
		# dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S`
		self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10)
		self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10)
		time.sleep(1)
		# Calling twice AT to clear all buffers
		self.command('AT', 'OK|ERROR', 5)
		self.command('AT', 'OK', 5)
		# Enabling the Radio
		self.command('AT+CFUN=1', 'SIMSTORE,READY', 5)
		logging.debug('\u001B[1m Cellular Functionality enabled\u001B[0m')
		time.sleep(4)
		# We should check if we register
		count = 0
889 890 891
		attach_cnt = 0
		attach_status = False
		while count < 5:
892
			self.command('AT+CEREG?', 'OK', 5)
893
			result = re.search('CEREG: 2,(?P<state>[0-9\-]+),', str(self.ssh.before))
894 895 896
			if result is not None:
				mDataConnectionState = int(result.group('state'))
				if mDataConnectionState is not None:
897 898 899 900 901 902 903 904 905 906 907 908 909
					if mDataConnectionState == 1:
						count = 10
						attach_status = True
						result = re.search('CEREG: 2,1,"(?P<networky>[0-9A-Z]+)","(?P<networkz>[0-9A-Z]+)"', str(self.ssh.before))
						if result is not None:
							networky = result.group('networky')
							networkz = result.group('networkz')
							logging.debug('\u001B[1m CAT-M module attached to eNB (' + str(networky) + '/' + str(networkz) + ')\u001B[0m')
						else:
							logging.debug('\u001B[1m CAT-M module attached to eNB\u001B[0m')
					else:
						logging.debug('+CEREG: 2,' + str(mDataConnectionState))
						attach_cnt = attach_cnt + 1
910 911
			else:
				logging.debug(str(self.ssh.before))
912
				attach_cnt = attach_cnt + 1
913 914
			count = count + 1
			time.sleep(1)
915 916 917 918 919 920 921 922 923
		if attach_status:
			self.command('AT+CESQ', 'OK', 5)
			result = re.search('CESQ: 99,99,255,255,(?P<rsrq>[0-9]+),(?P<rsrp>[0-9]+)', str(self.ssh.before))
			if result is not None:
				nRSRQ = int(result.group('rsrq'))
				nRSRP = int(result.group('rsrp'))
				if (nRSRQ is not None) and (nRSRP is not None):
					logging.debug('    RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB')
					logging.debug('    RSRP = ' + str(-140+nRSRP) + ' dBm')
924 925
		self.close()
		self.picocom_closure = False
926
		html_queue = SimpleQueue()
927
		self.checkDevTTYisUnlocked()
928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
		if attach_status:
			html_cell = '<pre style="background-color:white">CAT-M module\nAttachment Completed in ' + str(attach_cnt+4) + ' seconds'
			if (nRSRQ is not None) and (nRSRP is not None):
				html_cell += '\n   RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB'
				html_cell += '\n   RSRP = ' + str(-140+nRSRP) + ' dBm</pre>'
			else:
				html_cell += '</pre>'
			html_queue.put(html_cell)
			self.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue)
		else:
			html_cell = '<pre style="background-color:white">CAT-M module\nAttachment Failed</pre>'
			html_queue.put(html_cell)
			self.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue)

	def PingCatM(self):
		if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '':
			Usage()
			sys.exit('Insufficient Parameter')
		initialize_eNB_flag = False
		pStatus = self.CheckProcessExist(initialize_eNB_flag)
		if (pStatus < 0):
			self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
			self.CreateHtmlTabFooter(False)
			sys.exit(1)
		try:
			statusQueue = SimpleQueue()
			lock = Lock()
			self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
			self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
			self.command('cd scripts', '\$', 5)
			if re.match('OAI', self.EPCType, re.IGNORECASE):
				logging.debug('Using the OAI EPC HSS: not implemented yet')
				self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
				self.CreateHtmlTabFooter(False)
				sys.exit(1)
			else:
				self.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5)
				result = re.search('Allocated ipv4 addr: (?P<ipaddr>[0-9\.]+) from Pool', str(self.ssh.before))
				if result is not None:
					moduleIPAddr = result.group('ipaddr')
				else:
					return
			ping_time = re.findall("-c (\d+)",str(self.ping_args))
			device_id = 'catm'
			ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee -a ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5)
			# TIMEOUT CASE
			if ping_status < 0:
				message = 'Ping with UE (' + str(moduleIPAddr) + ') crashed due to TIMEOUT!'
				logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
				self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message)
				return
			result = re.search(', (?P<packetloss>[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before))
			if result is None:
				message = 'Packet Loss Not Found!'
				logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
				self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message)
				return
			packetloss = result.group('packetloss')
			if float(packetloss) == 100:
				message = 'Packet Loss is 100%'
				logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
				self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message)
				return
			result = re.search('rtt min\/avg\/max\/mdev = (?P<rtt_min>[0-9\.]+)\/(?P<rtt_avg>[0-9\.]+)\/(?P<rtt_max>[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before))
			if result is None:
				message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!'
				logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
				self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message)
				return
			rtt_min = result.group('rtt_min')
			rtt_avg = result.group('rtt_avg')
			rtt_max = result.group('rtt_max')
			pal_msg = 'Packet Loss : ' + packetloss + '%'
			min_msg = 'RTT(Min)    : ' + rtt_min + ' ms'
			avg_msg = 'RTT(Avg)    : ' + rtt_avg + ' ms'
			max_msg = 'RTT(Max)    : ' + rtt_max + ' ms'
			lock.acquire()
			logging.debug('\u001B[1;37;44m ping result (' + moduleIPAddr + ') \u001B[0m')
			logging.debug('\u001B[1;34m    ' + pal_msg + '\u001B[0m')
			logging.debug('\u001B[1;34m    ' + min_msg + '\u001B[0m')
			logging.debug('\u001B[1;34m    ' + avg_msg + '\u001B[0m')
			logging.debug('\u001B[1;34m    ' + max_msg + '\u001B[0m')
			qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg
			packetLossOK = True
			if packetloss is not None:
				if float(packetloss) > float(self.ping_packetloss_threshold):
					qMsg += '\nPacket Loss too high'
					logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m')
					packetLossOK = False
				elif float(packetloss) > 0:
					qMsg += '\nPacket Loss is not 0%'
					logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m')
			lock.release()
			self.close()
			html_cell = '<pre style="background-color:white">CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '</pre>'
			statusQueue.put(html_cell)
			if (packetLossOK):
				self.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue)
			else:
				self.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue)
				self.AutoTerminateUEandeNB()
				self.CreateHtmlTabFooter(False)
				sys.exit(1)
		except:
			os.kill(os.getppid(),signal.SIGUSR1)
1033

Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1034
	def AttachUE_common(self, device_id, statusQueue, lock):
1035 1036 1037 1038
		try:
			self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
			self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60)
			time.sleep(2)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1039 1040
			max_count = 45
			count = max_count
1041 1042 1043 1044 1045
			while count > 0:
				self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15)
				result = re.search('mDataConnectionState.*=(?P<state>[0-9\-]+)', str(self.ssh.before))
				if result is None:
					logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1046 1047 1048 1049 1050 1051
					lock.acquire()
					statusQueue.put(-1)
					statusQueue.put(device_id)
					statusQueue.put('mDataConnectionState Not Found!')
					lock.release()
					break
1052 1053 1054
				mDataConnectionState = int(result.group('state'))
				if mDataConnectionState == 2:
					logging.debug('\u001B[1mUE (' + device_id + ') Attach Completed\u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1055 1056 1057 1058 1059
					lock.acquire()
					statusQueue.put(max_count - count)
					statusQueue.put(device_id)
					statusQueue.put('Attach Completed')
					lock.release()
1060 1061 1062
					break
				count = count - 1
				if count == 15 or count == 30:
Raphael Defosseux's avatar
Raphael Defosseux committed
1063
					logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m')
1064 1065 1066 1067
					self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60)
					time.sleep(0.5)
					self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60)
					time.sleep(0.5)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1068
				logging.debug('\u001B[1mWait UE (' + device_id + ') a second until mDataConnectionState=2 (' + str(max_count-count) + ' times)\u001B[0m')
1069 1070 1071
				time.sleep(1)
			if count == 0:
				logging.debug('\u001B[1;37;41m UE (' + device_id + ') Attach Failed \u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1072 1073 1074 1075 1076
				lock.acquire()
				statusQueue.put(-1)
				statusQueue.put(device_id)
				statusQueue.put('Attach Failed')
				lock.release()
1077 1078 1079 1080 1081 1082 1083 1084 1085
			self.close()
		except:
			os.kill(os.getppid(),signal.SIGUSR1)

	def AttachUE(self):
		if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
			Usage()
			sys.exit('Insufficient Parameter')
		initialize_eNB_flag = False
Raphael Defosseux's avatar
Raphael Defosseux committed
1086 1087 1088
		pStatus = self.CheckProcessExist(initialize_eNB_flag)
		if (pStatus < 0):
			self.CreateHtmlTestRow('N/A', 'KO', pStatus)
1089
			self.AutoTerminateUEandeNB()
1090
			self.CreateHtmlTabFooter(False)
Raphael Defosseux's avatar
Raphael Defosseux committed
1091
			sys.exit(1)
1092
		multi_jobs = []
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1093 1094
		status_queue = SimpleQueue()
		lock = Lock()
1095
		nb_ue_to_connect = 0
1096
		for device_id in self.UEDevices:
1097 1098 1099 1100 1101 1102
			if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach):
				p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,))
				p.daemon = True
				p.start()
				multi_jobs.append(p)
			nb_ue_to_connect = nb_ue_to_connect + 1
1103 1104
		for job in multi_jobs:
			job.join()
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1105 1106

		if (status_queue.empty()):
1107
			self.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK)
1108
			self.CreateHtmlTabFooter(False)
1109
			self.AutoTerminateUEandeNB()
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
			sys.exit(1)
		else:
			attach_status = True
			html_queue = SimpleQueue()
			while (not status_queue.empty()):
				count = status_queue.get()
				if (count < 0):
					attach_status = False
				device_id = status_queue.get()
				message = status_queue.get()
				if (count < 0):
1121
					html_cell = '<pre style="background-color:white">UE (' + device_id + ')\n' + message + '</pre>'
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1122
				else:
1123
					html_cell = '<pre style="background-color:white">UE (' + device_id + ')\n' + message + ' in ' + str(count + 2) + ' seconds</pre>'
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1124 1125 1126
				html_queue.put(html_cell)
			if (attach_status):
				self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue)
1127 1128 1129 1130
				result = re.search('T_stdout', str(self.Initialize_eNB_args))
				if result is not None:
					logging.debug('Waiting 5 seconds to fill up record file')
					time.sleep(5)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1131 1132
			else:
				self.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue)
1133
				self.AutoTerminateUEandeNB()
1134
				self.CreateHtmlTabFooter(False)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1135
				sys.exit(1)
1136 1137 1138 1139

	def DetachUE_common(self, device_id):
		try:
			self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
1140
			self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60)
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
			logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m')
			self.close()
		except:
			os.kill(os.getppid(),signal.SIGUSR1)

	def DetachUE(self):
		if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
			Usage()
			sys.exit('Insufficient Parameter')
		initialize_eNB_flag = False
Raphael Defosseux's avatar
Raphael Defosseux committed
1151 1152 1153
		pStatus = self.CheckProcessExist(initialize_eNB_flag)
		if (pStatus < 0):
			self.CreateHtmlTestRow('N/A', 'KO', pStatus)
1154
			self.AutoTerminateUEandeNB()
1155
			self.CreateHtmlTabFooter(False)
Raphael Defosseux's avatar
Raphael Defosseux committed
1156
			sys.exit(1)
1157 1158
		multi_jobs = []
		for device_id in self.UEDevices:
1159
			p = Process(target = self.DetachUE_common, args = (device_id,))
1160 1161 1162 1163 1164
			p.daemon = True
			p.start()
			multi_jobs.append(p)
		for job in multi_jobs:
			job.join()
1165
		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
1166 1167 1168 1169
		result = re.search('T_stdout', str(self.Initialize_eNB_args))
		if result is not None:
			logging.debug('Waiting 5 seconds to fill up record file')
			time.sleep(5)
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214

	def RebootUE_common(self, device_id):
		try:
			self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
			previousmDataConnectionStates = []
			# Save mDataConnectionState
			self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15)
			self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15)
			result = re.search('mDataConnectionState.*=(?P<state>[0-9\-]+)', str(self.ssh.before))
			if result is None:
				logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m')
				sys.exit(1)
			previousmDataConnectionStates.append(int(result.group('state')))
			# Reboot UE
			self.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10)
			time.sleep(60)
			previousmDataConnectionState = previousmDataConnectionStates.pop(0)
			count = 180
			while count > 0:
				count = count - 1
				self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15)
				result = re.search('mDataConnectionState.*=(?P<state>[0-9\-]+)', str(self.ssh.before))
				if result is None:
					mDataConnectionState = None
				else:
					mDataConnectionState = int(result.group('state'))
					logging.debug('mDataConnectionState = ' + result.group('state'))
				if mDataConnectionState is None or (previousmDataConnectionState == 2 and mDataConnectionState != 2):
					logging.debug('\u001B[1mWait UE (' + device_id + ') a second until reboot completion (' + str(180-count) + ' times)\u001B[0m')
					time.sleep(1)
				else:
					logging.debug('\u001B[1mUE (' + device_id + ') Reboot Completed\u001B[0m')
					break
			if count == 0:
				logging.debug('\u001B[1;37;41m UE (' + device_id + ') Reboot Failed \u001B[0m')
				sys.exit(1)
			self.close()
		except:
			os.kill(os.getppid(),signal.SIGUSR1)

	def RebootUE(self):
		if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
			Usage()
			sys.exit('Insufficient Parameter')
		initialize_eNB_flag = False
Raphael Defosseux's avatar
Raphael Defosseux committed
1215 1216 1217
		pStatus = self.CheckProcessExist(initialize_eNB_flag)
		if (pStatus < 0):
			self.CreateHtmlTestRow('N/A', 'KO', pStatus)
1218
			self.CreateHtmlTabFooter(False)
Raphael Defosseux's avatar
Raphael Defosseux committed
1219
			sys.exit(1)
1220 1221
		multi_jobs = []
		for device_id in self.UEDevices:
1222
			p = Process(target = self.RebootUE_common, args = (device_id,))
1223 1224 1225 1226 1227
			p.daemon = True
			p.start()
			multi_jobs.append(p)
		for job in multi_jobs:
			job.join()
1228
		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240

	def GetAllUEDevices(self, terminate_ue_flag):
		if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
			Usage()
			sys.exit('Insufficient Parameter')
		self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
		self.command('adb devices', '\$', 15)
		self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",str(self.ssh.before))
		if terminate_ue_flag == False:
			if len(self.UEDevices) == 0:
				logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m')
				sys.exit(1)
1241 1242
		self.close()

1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255
	def GetAllCatMDevices(self, terminate_ue_flag):
		if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
			Usage()
			sys.exit('Insufficient Parameter')
		self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
		self.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15)
		self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",str(self.ssh.before))
		if terminate_ue_flag == False:
			if len(self.CatMDevices) == 0:
				logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m')
				sys.exit(1)
		self.close()

1256 1257 1258 1259
	def GetAllUEIPAddresses(self):
		if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
			Usage()
			sys.exit('Insufficient Parameter')
1260
		ue_ip_status = 0
1261 1262 1263
		self.UEIPAddresses = []
		self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
		for device_id in self.UEDevices:
1264 1265 1266 1267 1268 1269
			count = 0
			while count < 4:
				self.command('stdbuf -o0 adb -s ' + device_id + ' shell ip addr show | grep rmnet', '\$', 15)
				result = re.search('inet (?P<ueipaddress>[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', str(self.ssh.before))
				if result is None:
					logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m')
1270
					time.sleep(1)
1271 1272 1273 1274 1275 1276
					count += 1
				else:
					count = 10
			if count < 9:
				ue_ip_status -= 1
				continue
1277 1278 1279 1280 1281
			UE_IPAddress = result.group('ueipaddress')
			logging.debug('\u001B[1mUE (' + device_id + ') IP Address is ' + UE_IPAddress + '\u001B[0m')
			for ueipaddress in self.UEIPAddresses:
				if ueipaddress == UE_IPAddress:
					logging.debug('\u001B[1mUE (' + device_id + ') IP Address ' + UE_IPAddress + 'has been existed!' + '\u001B[0m')
1282 1283
					ue_ip_status -= 1
					continue
1284
			self.UEIPAddresses.append(UE_IPAddress)
1285
		self.close()
1286
		return ue_ip_status
1287

Raphael Defosseux's avatar
Raphael Defosseux committed
1288 1289 1290 1291 1292 1293 1294 1295 1296
	def ping_iperf_wrong_exit(self, lock, UE_IPAddress, device_id, statusQueue, message):
		lock.acquire()
		statusQueue.put(-1)
		statusQueue.put(device_id)
		statusQueue.put(UE_IPAddress)
		statusQueue.put(message)
		lock.release()

	def Ping_common(self, lock, UE_IPAddress, device_id, statusQueue):
1297 1298 1299 1300 1301
		try:
			self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
			self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
			self.command('cd scripts', '\$', 5)
			ping_time = re.findall("-c (\d+)",str(self.ping_args))
1302
			ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee -a ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5)
Raphael Defosseux's avatar
Raphael Defosseux committed
1303 1304 1305 1306 1307 1308
			# TIMEOUT CASE
			if ping_status < 0:
				message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!'
				logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
				self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message)
				return
1309 1310
			result = re.search(', (?P<packetloss>[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before))
			if result is None:
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1311 1312
				message = 'Packet Loss Not Found!'
				logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
Raphael Defosseux's avatar
Raphael Defosseux committed
1313
				self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1314
				return
1315 1316
			packetloss = result.group('packetloss')
			if float(packetloss) == 100:
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1317 1318
				message = 'Packet Loss is 100%'
				logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
Raphael Defosseux's avatar
Raphael Defosseux committed
1319
				self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1320
				return
1321 1322
			result = re.search('rtt min\/avg\/max\/mdev = (?P<rtt_min>[0-9\.]+)\/(?P<rtt_avg>[0-9\.]+)\/(?P<rtt_max>[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before))
			if result is None:
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1323 1324
				message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!'
				logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
Raphael Defosseux's avatar
Raphael Defosseux committed
1325
				self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1326
				return
1327 1328 1329
			rtt_min = result.group('rtt_min')
			rtt_avg = result.group('rtt_avg')
			rtt_max = result.group('rtt_max')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1330 1331 1332 1333
			pal_msg = 'Packet Loss : ' + packetloss + '%'
			min_msg = 'RTT(Min)    : ' + rtt_min + ' ms'
			avg_msg = 'RTT(Avg)    : ' + rtt_avg + ' ms'
			max_msg = 'RTT(Max)    : ' + rtt_max + ' ms'
1334 1335
			lock.acquire()
			logging.debug('\u001B[1;37;44m ping result (' + UE_IPAddress + ') \u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1336 1337 1338 1339 1340 1341
			logging.debug('\u001B[1;34m    ' + pal_msg + '\u001B[0m')
			logging.debug('\u001B[1;34m    ' + min_msg + '\u001B[0m')
			logging.debug('\u001B[1;34m    ' + avg_msg + '\u001B[0m')
			logging.debug('\u001B[1;34m    ' + max_msg + '\u001B[0m')
			qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg
			packetLossOK = True
1342 1343
			if packetloss is not None:
				if float(packetloss) > float(self.ping_packetloss_threshold):
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1344
					qMsg += '\nPacket Loss too high'
1345
					logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1346
					packetLossOK = False
1347
				elif float(packetloss) > 0:
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1348
					qMsg += '\nPacket Loss is not 0%'
Raphael Defosseux's avatar
Raphael Defosseux committed
1349
					logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1350 1351 1352 1353 1354 1355 1356 1357
			if (packetLossOK):
				statusQueue.put(0)
			else:
				statusQueue.put(-1)
			statusQueue.put(device_id)
			statusQueue.put(UE_IPAddress)
			statusQueue.put(qMsg)
			lock.release()
1358 1359 1360 1361 1362 1363 1364 1365 1366
			self.close()
		except:
			os.kill(os.getppid(),signal.SIGUSR1)

	def Ping(self):
		if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '':
			Usage()
			sys.exit('Insufficient Parameter')
		initialize_eNB_flag = False
Raphael Defosseux's avatar
Raphael Defosseux committed
1367 1368 1369
		pStatus = self.CheckProcessExist(initialize_eNB_flag)
		if (pStatus < 0):
			self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
1370
			self.CreateHtmlTabFooter(False)
Raphael Defosseux's avatar
Raphael Defosseux committed
1371
			sys.exit(1)
1372 1373 1374
		ueIpStatus = self.GetAllUEIPAddresses()
		if (ueIpStatus < 0):
			self.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE)
1375
			self.CreateHtmlTabFooter(False)
1376
			sys.exit(1)
1377 1378 1379
		multi_jobs = []
		i = 0
		lock = Lock()
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1380
		status_queue = SimpleQueue()
1381 1382
		for UE_IPAddress in self.UEIPAddresses:
			device_id = self.UEDevices[i]
1383
			p = Process(target = self.Ping_common, args = (lock,UE_IPAddress,device_id,status_queue,))
1384 1385 1386 1387 1388 1389
			p.daemon = True
			p.start()
			multi_jobs.append(p)
			i = i + 1
		for job in multi_jobs:
			job.join()
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1390 1391

		if (status_queue.empty()):
1392
			self.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK)
1393
			self.AutoTerminateUEandeNB()
1394
			self.CreateHtmlTabFooter(False)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
			sys.exit(1)
		else:
			ping_status = True
			html_queue = SimpleQueue()
			while (not status_queue.empty()):
				count = status_queue.get()
				if (count < 0):
					ping_status = False
				device_id = status_queue.get()
				ip_addr = status_queue.get()
				message = status_queue.get()
1406
				html_cell = '<pre style="background-color:white">UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '</pre>'
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1407 1408 1409 1410 1411
				html_queue.put(html_cell)
			if (ping_status):
				self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue)
			else:
				self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue)
1412
				self.AutoTerminateUEandeNB()
1413
				self.CreateHtmlTabFooter(False)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1414
				sys.exit(1)
1415

1416 1417 1418 1419 1420 1421 1422
	def Iperf_ComputeTime(self):
		result = re.search('-t (?P<iperf_time>\d+)', str(self.iperf_args))
		if result is None:
			logging.debug('\u001B[1;37;41m Iperf time Not Found! \u001B[0m')
			sys.exit(1)
		return result.group('iperf_time')

1423
	def Iperf_ComputeModifiedBW(self, idx, ue_num):
1424 1425 1426 1427 1428
		result = re.search('-b (?P<iperf_bandwidth>[0-9\.]+)[KMG]', str(self.iperf_args))
		if result is None:
			logging.debug('\u001B[1;37;41m Iperf bandwidth Not Found! \u001B[0m')
			sys.exit(1)
		iperf_bandwidth = result.group('iperf_bandwidth')
1429
		if self.iperf_profile == 'balanced':
1430
			iperf_bandwidth_new = float(iperf_bandwidth)/ue_num
1431
		if self.iperf_profile == 'single-ue':
1432
			iperf_bandwidth_new = float(iperf_bandwidth)
1433
		if self.iperf_profile == 'unbalanced':
1434 1435 1436 1437 1438 1439
			# residual is 2% of max bw
			residualBW = float(iperf_bandwidth) / 50
			if idx == 0:
				iperf_bandwidth_new = float(iperf_bandwidth) - ((ue_num - 1) * residualBW)
			else:
				iperf_bandwidth_new = residualBW
1440
		iperf_bandwidth_str = '-b ' + iperf_bandwidth
1441
		iperf_bandwidth_str_new = '-b ' + ('%.2f' % iperf_bandwidth_new)
1442 1443 1444 1445 1446 1447
		result = re.sub(iperf_bandwidth_str, iperf_bandwidth_str_new, str(self.iperf_args))
		if result is None:
			logging.debug('\u001B[1;37;41m Calculate Iperf bandwidth Failed! \u001B[0m')
			sys.exit(1)
		return result

1448
	def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options):
1449
		self.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5)
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473
		result = re.search('Avg Bitrate : (?P<average>[0-9\.]+ Mbits\/sec) Max Bitrate : (?P<maximum>[0-9\.]+ Mbits\/sec) Min Bitrate : (?P<minimum>[0-9\.]+ Mbits\/sec)', str(self.ssh.before))
		if result is not None:
			avgbitrate = result.group('average')
			maxbitrate = result.group('maximum')
			minbitrate = result.group('minimum')
			lock.acquire()
			logging.debug('\u001B[1;37;44m TCP iperf result (' + UE_IPAddress + ') \u001B[0m')
			msg = 'TCP Stats   :\n'
			if avgbitrate is not None:
				logging.debug('\u001B[1;34m    Avg Bitrate : ' + avgbitrate + '\u001B[0m')
				msg += 'Avg Bitrate : ' + avgbitrate + '\n'
			if maxbitrate is not None:
				logging.debug('\u001B[1;34m    Max Bitrate : ' + maxbitrate + '\u001B[0m')
				msg += 'Max Bitrate : ' + maxbitrate + '\n'
			if minbitrate is not None:
				logging.debug('\u001B[1;34m    Min Bitrate : ' + minbitrate + '\u001B[0m')
				msg += 'Min Bitrate : ' + minbitrate + '\n'
			statusQueue.put(0)
			statusQueue.put(device_id)
			statusQueue.put(UE_IPAddress)
			statusQueue.put(msg)
			lock.release()
		return 0

1474
	def Iperf_analyzeV2Output(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options):
1475 1476 1477 1478
		result = re.search('-u', str(iperf_real_options))
		if result is None:
			return self.Iperf_analyzeV2TCPOutput(lock, UE_IPAddress, device_id, statusQueue, iperf_real_options)

1479 1480 1481 1482 1483 1484 1485
		result = re.search('Server Report:', str(self.ssh.before))
		if result is None:
			result = re.search('read failed: Connection refused', str(self.ssh.before))
			if result is not None:
				logging.debug('\u001B[1;37;41m Could not connect to iperf server! \u001B[0m')
			else:
				logging.debug('\u001B[1;37;41m Server Report and Connection refused Not Found! \u001B[0m')
Raphael Defosseux's avatar
Raphael Defosseux committed
1486
			return -1
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504
		# Computing the requested bandwidth in float
		result = re.search('-b (?P<iperf_bandwidth>[0-9\.]+)[KMG]', str(iperf_real_options))
		if result is not None:
			req_bandwidth = result.group('iperf_bandwidth')
			req_bw = float(req_bandwidth)
			result = re.search('-b [0-9\.]+K', str(iperf_real_options))
			if result is not None:
				req_bandwidth = '%.1f Kbits/sec' % req_bw
				req_bw = req_bw * 1000
			result = re.search('-b [0-9\.]+M', str(iperf_real_options))
			if result is not None:
				req_bandwidth = '%.1f Mbits/sec' % req_bw
				req_bw = req_bw * 1000000
			result = re.search('-b [0-9\.]+G', str(iperf_real_options))
			if result is not None:
				req_bandwidth = '%.1f Gbits/sec' % req_bw
				req_bw = req_bw * 1000000000

1505
		result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P<bitrate>[0-9\.]+ [KMG]bits\/sec) +(?P<jitter>[0-9\.]+ ms) +(\d+\/..\d+) (\((?P<packetloss>[0-9\.]+)%\))', str(self.ssh.before))
1506 1507 1508 1509 1510 1511
		if result is not None:
			bitrate = result.group('bitrate')
			packetloss = result.group('packetloss')
			jitter = result.group('jitter')
			lock.acquire()
			logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1512
			iperfStatus = True
1513 1514
			msg = 'Req Bitrate : ' + req_bandwidth + '\n'
			logging.debug('\u001B[1;34m    Req Bitrate : ' + req_bandwidth + '\u001B[0m')
1515
			if bitrate is not None:
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1516
				msg += 'Bitrate     : ' + bitrate + '\n'
1517
				logging.debug('\u001B[1;34m    Bitrate     : ' + bitrate + '\u001B[0m')
1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533
				result = re.search('(?P<real_bw>[0-9\.]+) [KMG]bits/sec', str(bitrate))
				if result is not None:
					actual_bw = float(str(result.group('real_bw')))
					result = re.search('[0-9\.]+ K', bitrate)
					if result is not None:
						actual_bw = actual_bw * 1000
					result = re.search('[0-9\.]+ M', bitrate)
					if result is not None:
						actual_bw = actual_bw * 1000000
					result = re.search('[0-9\.]+ G', bitrate)
					if result is not None:
						actual_bw = actual_bw * 1000000000
					br_loss = 100 * actual_bw / req_bw
					bitperf = '%.2f ' % br_loss
					msg += 'Bitrate Perf: ' + bitperf + '%\n'
					logging.debug('\u001B[1;34m    Bitrate Perf: ' + bitperf + '%\u001B[0m')
1534
			if packetloss is not None:
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1535
				msg += 'Packet Loss : ' + packetloss + '%\n'
1536 1537
				logging.debug('\u001B[1;34m    Packet Loss : ' + packetloss + '%\u001B[0m')
				if float(packetloss) > float(self.iperf_packetloss_threshold):
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1538
					msg += 'Packet Loss too high!\n'
1539
					logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1540
					iperfStatus = False
1541
			if jitter is not None:
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1542
				msg += 'Jitter      : ' + jitter + '\n'
1543
				logging.debug('\u001B[1;34m    Jitter      : ' + jitter + '\u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1544 1545 1546 1547 1548 1549 1550
			if (iperfStatus):
				statusQueue.put(0)
			else:
				statusQueue.put(-1)
			statusQueue.put(device_id)
			statusQueue.put(UE_IPAddress)
			statusQueue.put(msg)
1551
			lock.release()
Raphael Defosseux's avatar
Raphael Defosseux committed
1552 1553 1554
			return 0

	def Iperf_analyzeV2Server(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options):
1555
		if (not os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')):
Raphael Defosseux's avatar
Raphael Defosseux committed
1556
			self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log')
Raphael Defosseux's avatar
Raphael Defosseux committed
1557 1558 1559 1560 1561
			return
		# Computing the requested bandwidth in float
		result = re.search('-b (?P<iperf_bandwidth>[0-9\.]+)[KMG]', str(iperf_real_options))
		if result is None:
			logging.debug('Iperf bandwidth Not Found!')
Raphael Defosseux's avatar
Raphael Defosseux committed
1562
			self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not compute Iperf bandwidth!')
Raphael Defosseux's avatar
Raphael Defosseux committed
1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579
			return
		else:
			req_bandwidth = result.group('iperf_bandwidth')
			req_bw = float(req_bandwidth)
			result = re.search('-b [0-9\.]+K', str(iperf_real_options))
			if result is not None:
				req_bandwidth = '%.1f Kbits/sec' % req_bw
				req_bw = req_bw * 1000
			result = re.search('-b [0-9\.]+M', str(iperf_real_options))
			if result is not None:
				req_bandwidth = '%.1f Mbits/sec' % req_bw
				req_bw = req_bw * 1000000
			result = re.search('-b [0-9\.]+G', str(iperf_real_options))
			if result is not None:
				req_bandwidth = '%.1f Gbits/sec' % req_bw
				req_bw = req_bw * 1000000000

1580
		server_file = open('iperf_server_' + self.testCase_id + '_' + device_id + '.log', 'r')
Raphael Defosseux's avatar
Raphael Defosseux committed
1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647
		br_sum = 0.0
		ji_sum = 0.0
		pl_sum = 0
		ps_sum = 0
		row_idx = 0
		for line in server_file.readlines():
			result = re.search('(?P<bitrate>[0-9\.]+ [KMG]bits\/sec) +(?P<jitter>[0-9\.]+ ms) +(?P<lostPack>[0-9]+)/ +(?P<sentPack>[0-9]+)', str(line))
			if result is not None:
				bitrate = result.group('bitrate')
				jitter = result.group('jitter')
				packetlost = result.group('lostPack')
				packetsent = result.group('sentPack')
				br = bitrate.split(' ')
				ji = jitter.split(' ')
				row_idx = row_idx + 1
				curr_br = float(br[0])
				pl_sum = pl_sum + int(packetlost)
				ps_sum = ps_sum + int(packetsent)
				if (br[1] == 'Kbits/sec'):
					curr_br = curr_br * 1000
				if (br[1] == 'Mbits/sec'):
					curr_br = curr_br * 1000 * 1000
				br_sum = curr_br + br_sum
				ji_sum = float(ji[0]) + ji_sum
		if (row_idx > 0):
			br_sum = br_sum / row_idx
			ji_sum = ji_sum / row_idx
			br_loss = 100 * br_sum / req_bw
			if (br_sum > 1000):
				br_sum = br_sum / 1000
				if (br_sum > 1000):
					br_sum = br_sum / 1000
					bitrate = '%.2f Mbits/sec' % br_sum
				else:
					bitrate = '%.2f Kbits/sec' % br_sum
			else:
				bitrate = '%.2f bits/sec' % br_sum
			bitperf = '%.2f ' % br_loss
			bitperf += '%'
			jitter = '%.2f ms' % (ji_sum)
			if (ps_sum > 0):
				pl = float(100 * pl_sum / ps_sum)
				packetloss = '%2.1f ' % (pl)
				packetloss += '%'
			else:
				packetloss = 'unknown'
			lock.acquire()
			if (br_loss < 90):
				statusQueue.put(1)
			else:
				statusQueue.put(0)
			statusQueue.put(device_id)
			statusQueue.put(UE_IPAddress)
			req_msg = 'Req Bitrate : ' + req_bandwidth
			bir_msg = 'Bitrate     : ' + bitrate
			brl_msg = 'Bitrate Perf: ' + bitperf
			jit_msg = 'Jitter      : ' + jitter
			pal_msg = 'Packet Loss : ' + packetloss
			statusQueue.put(req_msg + '\n' + bir_msg + '\n' + brl_msg + '\n' + jit_msg + '\n' + pal_msg + '\n')
			logging.debug('\u001B[1;37;45m iperf result (' + UE_IPAddress + ') \u001B[0m')
			logging.debug('\u001B[1;35m    ' + req_msg + '\u001B[0m')
			logging.debug('\u001B[1;35m    ' + bir_msg + '\u001B[0m')
			logging.debug('\u001B[1;35m    ' + brl_msg + '\u001B[0m')
			logging.debug('\u001B[1;35m    ' + jit_msg + '\u001B[0m')
			logging.debug('\u001B[1;35m    ' + pal_msg + '\u001B[0m')
			lock.release()
		else:
Raphael Defosseux's avatar
Raphael Defosseux committed
1648
			self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log')
Raphael Defosseux's avatar
Raphael Defosseux committed
1649 1650 1651

		server_file.close()

1652

Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1653
	def Iperf_analyzeV3Output(self, lock, UE_IPAddress, device_id, statusQueue):
1654 1655 1656
		result = re.search('(?P<bitrate>[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P<packetloss>[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', str(self.ssh.before))
		if result is None:
			result = re.search('(?P<error>iperf: error - [a-zA-Z0-9 :]+)', str(self.ssh.before))
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1657 1658 1659 1660
			lock.acquire()
			statusQueue.put(-1)
			statusQueue.put(device_id)
			statusQueue.put(UE_IPAddress)
1661 1662
			if result is not None:
				logging.debug('\u001B[1;37;41m ' + result.group('error') + ' \u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1663
				statusQueue.put(result.group('error'))
1664 1665
			else:
				logging.debug('\u001B[1;37;41m Bitrate and/or Packet Loss Not Found! \u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1666 1667 1668
				statusQueue.put('Bitrate and/or Packet Loss Not Found!')
			lock.release()

1669 1670 1671 1672 1673
		bitrate = result.group('bitrate')
		packetloss = result.group('packetloss')
		lock.acquire()
		logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m')
		logging.debug('\u001B[1;34m    Bitrate     : ' + bitrate + '\u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1674 1675
		msg = 'Bitrate     : ' + bitrate + '\n'
		iperfStatus = True
1676 1677
		if packetloss is not None:
			logging.debug('\u001B[1;34m    Packet Loss : ' + packetloss + '%\u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1678
			msg += 'Packet Loss : ' + packetloss + '%\n'
1679 1680
			if float(packetloss) > float(self.iperf_packetloss_threshold):
				logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1681 1682 1683 1684 1685 1686 1687 1688
				msg += 'Packet Loss too high!\n'
				iperfStatus = False
		if (iperfStatus):
			statusQueue.put(0)
		else:
			statusQueue.put(-1)
		statusQueue.put(device_id)
		statusQueue.put(UE_IPAddress)
Raphael Defosseux's avatar
Raphael Defosseux committed
1689
		statusQueue.put(msg)
1690 1691
		lock.release()

Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1692
	def Iperf_UL_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue):
1693 1694 1695 1696
		udpIperf = True
		result = re.search('-u', str(self.iperf_args))
		if result is None:
			udpIperf = False
1697 1698 1699 1700 1701 1702 1703 1704
		ipnumbers = UE_IPAddress.split('.')
		if (len(ipnumbers) == 4):
			ipnumbers[3] = '1'
		EPC_Iperf_UE_IPAddress = ipnumbers[0] + '.' + ipnumbers[1] + '.' + ipnumbers[2] + '.' + ipnumbers[3]

		# Launch iperf server on EPC side
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
		self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5)
1705
		self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5)
1706
		port = 5001 + idx
1707
		if udpIperf:
1708
			self.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5)
1709
		else:
1710
			self.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5)
1711 1712 1713 1714 1715 1716 1717 1718 1719
		time.sleep(0.5)
		self.close()

		# Launch iperf client on UE
		self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
		self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5)
		iperf_time = self.Iperf_ComputeTime()
		time.sleep(0.5)

1720 1721 1722 1723
		if udpIperf:
			modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num)
		else:
			modified_options = str(self.iperf_args)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1724
		modified_options = modified_options.replace('-R','')
1725 1726
		time.sleep(0.5)

1727 1728
		self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5)
		iperf_status = self.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee -a iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0)
Raphael Defosseux's avatar
Raphael Defosseux committed
1729 1730 1731 1732 1733 1734 1735
		# TIMEOUT Case
		if iperf_status < 0:
			self.close()
			message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !'
			logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
			self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message)
			return
1736
		clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options)
Raphael Defosseux's avatar
Raphael Defosseux committed
1737
		self.close()
1738

Raphael Defosseux's avatar
Raphael Defosseux committed
1739
		# Kill iperf server on EPC side
1740 1741 1742
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
		self.command('killall --signal SIGKILL iperf', self.EPCUserName, 5)
		self.close()
Raphael Defosseux's avatar
Raphael Defosseux committed
1743
		# in case of failure, retrieve server log
Raphael Defosseux's avatar
Raphael Defosseux committed
1744 1745
		if (clientStatus == -1):
			time.sleep(1)
1746 1747 1748
			if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')):
				os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log')
			self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.')
Raphael Defosseux's avatar
Raphael Defosseux committed
1749
			self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options)
1750

Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1751
	def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue):
1752
		try:
1753
			# Single-UE profile -- iperf only on one UE
1754
			if self.iperf_profile == 'single-ue' and idx != 0:
1755
				return
1756
			useIperf3 = False
1757
			udpIperf = True
1758
			self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1759
			# if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it
Raphael Defosseux's avatar
Raphael Defosseux committed
1760 1761
			self.command('if [ ! -d ' + self.EPCSourceCodePath + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5)
			self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5)
1762 1763 1764 1765 1766 1767
			# Checking if iperf / iperf3 are installed
			self.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5)
			result = re.search('iperf3', str(self.ssh.before))
			if result is None:
				result = re.search('iperf', str(self.ssh.before))
				if result is None:
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1768 1769
					message = 'Neither iperf nor iperf3 installed on UE!'
					logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
Raphael Defosseux's avatar
Raphael Defosseux committed
1770
					self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1771
					return
1772 1773
			else:
				useIperf3 = True
1774 1775 1776 1777 1778
			# in case of iperf, UL has its own function
			if (not useIperf3):
				result = re.search('-R', str(self.iperf_args))
				if result is not None:
					self.close()
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1779
					self.Iperf_UL_common(lock, UE_IPAddress, device_id, idx, ue_num, statusQueue)
1780 1781
					return

1782 1783 1784
			if (useIperf3):
				self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5)
			else:
1785
				self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5)
1786 1787
				result = re.search('-u', str(self.iperf_args))
				if result is None:
1788
					self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5)
1789 1790
					udpIperf = False
				else:
1791
					self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5)
1792 1793 1794 1795
			time.sleep(0.5)
			self.close()

			self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
1796 1797
			self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5)
			iperf_time = self.Iperf_ComputeTime()
1798 1799
			time.sleep(0.5)

1800 1801 1802 1803
			if udpIperf:
				modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num)
			else:
				modified_options = str(self.iperf_args)
1804 1805
			time.sleep(0.5)

1806
			self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5)
1807
			if (useIperf3):
1808
				self.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee -a iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0)
1809

Raphael Defosseux's avatar
Raphael Defosseux committed
1810
				clientStatus = 0
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1811
				self.Iperf_analyzeV3Output(lock, UE_IPAddress, device_id, statusQueue)
1812
			else:
1813
				iperf_status = self.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee -a iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0)
Raphael Defosseux's avatar
Raphael Defosseux committed
1814 1815 1816 1817 1818 1819
				if iperf_status < 0:
					self.close()
					message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !'
					logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
					self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message)
					return
1820
				clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options)
1821 1822 1823
			self.close()

			self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
1824
			self.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5)
1825 1826 1827 1828 1829
			result = re.search('shell +(?P<pid>\d+)', str(self.ssh.before))
			if result is not None:
				pid_iperf = result.group('pid')
				self.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5)
			self.close()
Raphael Defosseux's avatar
Raphael Defosseux committed
1830 1831
			if (clientStatus == -1):
				time.sleep(1)
1832 1833 1834
				if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')):
					os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log')
				self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.')
Raphael Defosseux's avatar
Raphael Defosseux committed
1835
				self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options)
1836 1837 1838 1839 1840 1841 1842 1843
		except:
			os.kill(os.getppid(),signal.SIGUSR1)

	def Iperf(self):
		if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
			Usage()
			sys.exit('Insufficient Parameter')
		initialize_eNB_flag = False
Raphael Defosseux's avatar
Raphael Defosseux committed
1844 1845 1846
		pStatus = self.CheckProcessExist(initialize_eNB_flag)
		if (pStatus < 0):
			self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus)
1847
			self.AutoTerminateUEandeNB()
1848
			self.CreateHtmlTabFooter(False)
Raphael Defosseux's avatar
Raphael Defosseux committed
1849
			sys.exit(1)
1850 1851
		ueIpStatus = self.GetAllUEIPAddresses()
		if (ueIpStatus < 0):
Raphael Defosseux's avatar
Raphael Defosseux committed
1852
			self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE)
1853
			self.AutoTerminateUEandeNB()
1854
			self.CreateHtmlTabFooter(False)
1855
			sys.exit(1)
1856 1857 1858 1859
		multi_jobs = []
		i = 0
		ue_num = len(self.UEIPAddresses)
		lock = Lock()
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1860
		status_queue = SimpleQueue()
1861 1862
		for UE_IPAddress in self.UEIPAddresses:
			device_id = self.UEDevices[i]
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1863
			p = Process(target = SSH.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,))
1864 1865 1866 1867 1868 1869
			p.daemon = True
			p.start()
			multi_jobs.append(p)
			i = i + 1
		for job in multi_jobs:
			job.join()
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1870 1871

		if (status_queue.empty()):
1872
			self.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK)
1873
			self.AutoTerminateUEandeNB()
1874
			self.CreateHtmlTabFooter(False)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1875 1876 1877
			sys.exit(1)
		else:
			iperf_status = True
Raphael Defosseux's avatar
Raphael Defosseux committed
1878
			iperf_noperf = False
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1879 1880 1881 1882 1883
			html_queue = SimpleQueue()
			while (not status_queue.empty()):
				count = status_queue.get()
				if (count < 0):
					iperf_status = False
Raphael Defosseux's avatar
Raphael Defosseux committed
1884 1885
				if (count > 0):
					iperf_noperf = True
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1886 1887 1888
				device_id = status_queue.get()
				ip_addr = status_queue.get()
				message = status_queue.get()
1889
				html_cell = '<pre style="background-color:white">UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '</pre>'
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1890
				html_queue.put(html_cell)
Raphael Defosseux's avatar
Raphael Defosseux committed
1891 1892 1893
			if (iperf_noperf and iperf_status):
				self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue)
			elif (iperf_status):
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1894 1895 1896
				self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue)
			else:
				self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue)
1897
				self.AutoTerminateUEandeNB()
1898
				self.CreateHtmlTabFooter(False)
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
1899
				sys.exit(1)
1900 1901 1902

	def CheckProcessExist(self, initialize_eNB_flag):
		multi_jobs = []
Raphael Defosseux's avatar
Raphael Defosseux committed
1903 1904
		status_queue = SimpleQueue()
		p = Process(target = SSH.CheckHSSProcess, args = (status_queue,))
1905 1906 1907
		p.daemon = True
		p.start()
		multi_jobs.append(p)
Raphael Defosseux's avatar
Raphael Defosseux committed
1908
		p = Process(target = SSH.CheckMMEProcess, args = (status_queue,))
1909 1910 1911
		p.daemon = True
		p.start()
		multi_jobs.append(p)
Raphael Defosseux's avatar
Raphael Defosseux committed
1912
		p = Process(target = SSH.CheckSPGWProcess, args = (status_queue,))
1913 1914 1915 1916
		p.daemon = True
		p.start()
		multi_jobs.append(p)
		if initialize_eNB_flag == False:
Raphael Defosseux's avatar
Raphael Defosseux committed
1917
			p = Process(target = SSH.CheckeNBProcess, args = (status_queue,))
1918 1919 1920 1921 1922 1923
			p.daemon = True
			p.start()
			multi_jobs.append(p)
		for job in multi_jobs:
			job.join()

Raphael Defosseux's avatar
Raphael Defosseux committed
1924 1925 1926 1927 1928 1929 1930 1931
		if (status_queue.empty()):
			return -15
		else:
			result = 0
			while (not status_queue.empty()):
				status = status_queue.get()
				if (status < 0):
					result = status
1932 1933 1934 1935
			if result == ENB_PROCESS_FAILED:
				fileCheck = re.search('enb_', str(self.eNBLogFile))
				if fileCheck is not None:
					self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFile, '.')
1936
					logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFile)
1937 1938
					if logStatus < 0:
						result = logStatus
Raphael Defosseux's avatar
Raphael Defosseux committed
1939 1940
			return result

1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971
	def CheckOAIUEProcessExist(self, initialize_OAI_UE_flag):
		multi_jobs = []
		status_queue = SimpleQueue()
		if initialize_OAI_UE_flag == False:
			p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,))
			p.daemon = True
			p.start()
			multi_jobs.append(p)
		for job in multi_jobs:
			job.join()

		if (status_queue.empty()):
			return -15
		else:
			result = 0
			while (not status_queue.empty()):
				status = status_queue.get()
				if (status < 0):
					result = status
			if result == OAI_UE_PROCESS_FAILED:
				fileCheck = re.search('enb_', str(self.UELogFile))
				if fileCheck is not None:
					self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.')
					logStatus = self.AnalyzeLogFile_UE(self.UELogFile)
					if logStatus < 0:
						result = logStatus
			return result

	def CheckOAIUEProcess(self, status_queue):
		try:
			self.open(self.OAIUEIPAddress, self.OAIUEUserName, self.OAIUEPassword)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
1972 1973
			self.command('stdbuf -o0 ps -aux | grep -v grep | grep --color=never ' + self.air_interface + '-uesoftmodem', '\$', 5)
			result = re.search(air_interface + '-uesoftmodem', str(self.ssh.before))
1974 1975 1976 1977 1978 1979 1980 1981 1982
			if result is None:
				logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m')
				status_queue.put(OAI_UE_PROCESS_FAILED)
			else:
				status_queue.put(OAI_UE_PROCESS_OK)
			self.close()
		except:
			os.kill(os.getppid(),signal.SIGUSR1)

Raphael Defosseux's avatar
Raphael Defosseux committed
1983
	def CheckeNBProcess(self, status_queue):
1984 1985
		try:
			self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
1986 1987
			self.command('stdbuf -o0 ps -aux | grep -v grep | grep --color=never ' + self.air_interface + '-softmodem', '\$', 5)
			result = re.search(air_interface + '-softmodem', str(self.ssh.before))
1988 1989
			if result is None:
				logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m')
1990
				status_queue.put(ENB_PROCESS_FAILED)
Raphael Defosseux's avatar
Raphael Defosseux committed
1991
			else:
1992
				status_queue.put(ENB_PROCESS_OK)
1993 1994 1995 1996
			self.close()
		except:
			os.kill(os.getppid(),signal.SIGUSR1)

Raphael Defosseux's avatar
Raphael Defosseux committed
1997
	def CheckHSSProcess(self, status_queue):
1998 1999 2000 2001 2002 2003 2004 2005 2006
		try:
			self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
			self.command('stdbuf -o0 ps -aux | grep -v grep | grep --color=never hss', '\$', 5)
			if re.match('OAI', self.EPCType, re.IGNORECASE):
				result = re.search('\/bin\/bash .\/run_', str(self.ssh.before))
			else:
				result = re.search('hss_sim s6as diam_hss', str(self.ssh.before))
			if result is None:
				logging.debug('\u001B[1;37;41m HSS Process Not Found! \u001B[0m')
2007
				status_queue.put(HSS_PROCESS_FAILED)
Raphael Defosseux's avatar
Raphael Defosseux committed
2008
			else:
2009
				status_queue.put(HSS_PROCESS_OK)
2010 2011 2012 2013
			self.close()
		except:
			os.kill(os.getppid(),signal.SIGUSR1)

Raphael Defosseux's avatar
Raphael Defosseux committed
2014
	def CheckMMEProcess(self, status_queue):
2015 2016 2017 2018 2019 2020 2021 2022 2023
		try:
			self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
			self.command('stdbuf -o0 ps -aux | grep -v grep | grep --color=never mme', '\$', 5)
			if re.match('OAI', self.EPCType, re.IGNORECASE):
				result = re.search('\/bin\/bash .\/run_', str(self.ssh.before))
			else:
				result = re.search('mme', str(self.ssh.before))
			if result is None:
				logging.debug('\u001B[1;37;41m MME Process Not Found! \u001B[0m')
2024
				status_queue.put(MME_PROCESS_FAILED)
Raphael Defosseux's avatar
Raphael Defosseux committed
2025
			else:
2026
				status_queue.put(MME_PROCESS_OK)
2027 2028 2029
			self.close()
		except:
			os.kill(os.getppid(),signal.SIGUSR1)
2030

Raphael Defosseux's avatar
Raphael Defosseux committed
2031
	def CheckSPGWProcess(self, status_queue):
2032 2033 2034 2035 2036 2037 2038 2039 2040 2041
		try:
			self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
			if re.match('OAI', self.EPCType, re.IGNORECASE):
				self.command('stdbuf -o0 ps -aux | grep -v grep | grep --color=never spgw', '\$', 5)
				result = re.search('\/bin\/bash .\/run_', str(self.ssh.before))
			else:
				self.command('stdbuf -o0 ps -aux | grep -v grep | grep --color=never xGw', '\$', 5)
				result = re.search('xGw', str(self.ssh.before))
			if result is None:
				logging.debug('\u001B[1;37;41m SPGW Process Not Found! \u001B[0m')
2042
				status_queue.put(SPGW_PROCESS_FAILED)
Raphael Defosseux's avatar
Raphael Defosseux committed
2043
			else:
2044
				status_queue.put(SPGW_PROCESS_OK)
2045 2046 2047
			self.close()
		except:
			os.kill(os.getppid(),signal.SIGUSR1)
2048

2049 2050
	def AnalyzeLogFile_eNB(self, eNBlogFile):
		if (not os.path.isfile('./' + eNBlogFile)):
2051
			return -1
2052
		enb_log_file = open('./' + eNBlogFile, 'r')
2053 2054 2055 2056 2057
		foundAssertion = False
		msgAssertion = ''
		msgLine = 0
		foundSegFault = False
		foundRealTimeIssue = False
Raphael Defosseux's avatar
Raphael Defosseux committed
2058 2059 2060 2061 2062 2063 2064 2065
		rrcSetupRequest = 0
		rrcSetupComplete = 0
		rrcReleaseRequest = 0
		rrcReconfigRequest = 0
		rrcReconfigComplete = 0
		rrcReestablishRequest = 0
		rrcReestablishComplete = 0
		rrcReestablishReject = 0
2066 2067
		rlcDiscardBuffer = 0
		rachCanceledProcedure = 0
Raphael Defosseux's avatar
Raphael Defosseux committed
2068
		uciStatMsgCount = 0
2069 2070
		pdcpFailure = 0
		ulschFailure = 0
2071
		self.htmleNBFailureMsg = ''
2072
		for line in enb_log_file.readlines():
2073 2074 2075 2076 2077 2078 2079 2080 2081 2082
			if self.rruOptions != '':
				res1 = re.search('max_rxgain (?P<requested_option>[0-9]+)', self.rruOptions)
				res2 = re.search('max_rxgain (?P<applied_option>[0-9]+)',  str(line))
				if res1 is not None and res2 is not None:
					requested_option = int(res1.group('requested_option'))
					applied_option = int(res2.group('applied_option'))
					if requested_option == applied_option:
						self.htmleNBFailureMsg += '<span class="glyphicon glyphicon-ok-circle"></span> Command line option(s) correctly applied <span class="glyphicon glyphicon-arrow-right"></span> ' + self.rruOptions + '\n\n'
					else:
						self.htmleNBFailureMsg += '<span class="glyphicon glyphicon-ban-circle"></span> Command line option(s) NOT applied <span class="glyphicon glyphicon-arrow-right"></span> ' + self.rruOptions + '\n\n'
2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097
			result = re.search('[Ss]egmentation [Ff]ault', str(line))
			if result is not None:
				foundSegFault = True
			result = re.search('[Cc]ore [dD]ump', str(line))
			if result is not None:
				foundSegFault = True
			result = re.search('[Aa]ssertion', str(line))
			if result is not None:
				foundAssertion = True
			result = re.search('LLL', str(line))
			if result is not None:
				foundRealTimeIssue = True
			if foundAssertion and (msgLine < 3):
				msgLine += 1
				msgAssertion += str(line)
2098
			result = re.search('Generating LTE_RRCConnectionSetup|Generating RRCConnectionSetup', str(line))
Raphael Defosseux's avatar
Raphael Defosseux committed
2099 2100
			if result is not None:
				rrcSetupRequest += 1
2101
			result = re.search('LTE_RRCConnectionSetupComplete from UE|RRCConnectionSetupComplete from UE', str(line))
Raphael Defosseux's avatar
Raphael Defosseux committed
2102 2103
			if result is not None:
				rrcSetupComplete += 1
2104
			result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line))
Raphael Defosseux's avatar
Raphael Defosseux committed
2105 2106
			if result is not None:
				rrcReleaseRequest += 1
2107
			result = re.search('Generate LTE_RRCConnectionReconfiguration|Generate RRCConnectionReconfiguration', str(line))
Raphael Defosseux's avatar
Raphael Defosseux committed
2108 2109
			if result is not None:
				rrcReconfigRequest += 1
2110
			result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti|RRCConnectionReconfigurationComplete from UE rnti', str(line))
Raphael Defosseux's avatar
Raphael Defosseux committed
2111 2112
			if result is not None:
				rrcReconfigComplete += 1
2113
			result = re.search('LTE_RRCConnectionReestablishmentRequest|RRCConnectionReestablishmentRequest', str(line))
Raphael Defosseux's avatar
Raphael Defosseux committed
2114 2115
			if result is not None:
				rrcReestablishRequest += 1
2116
			result = re.search('LTE_RRCConnectionReestablishmentComplete|RRCConnectionReestablishmentComplete', str(line))
Raphael Defosseux's avatar
Raphael Defosseux committed
2117 2118
			if result is not None:
				rrcReestablishComplete += 1
2119
			result = re.search('LTE_RRCConnectionReestablishmentReject|RRCConnectionReestablishmentReject', str(line))
Raphael Defosseux's avatar
Raphael Defosseux committed
2120 2121 2122 2123 2124
			if result is not None:
				rrcReestablishReject += 1
			result = re.search('uci->stat', str(line))
			if result is not None:
				uciStatMsgCount += 1
2125 2126 2127 2128 2129 2130
			result = re.search('PDCP.*Out of Resources.*reason', str(line))
			if result is not None:
				pdcpFailure += 1
			result = re.search('ULSCH in error in round', str(line))
			if result is not None:
				ulschFailure += 1
2131 2132 2133 2134 2135 2136
			result = re.search('BAD all_segments_received', str(line))
			if result is not None:
				rlcDiscardBuffer += 1
			result = re.search('Canceled RA procedure for UE rnti', str(line))
			if result is not None:
				rachCanceledProcedure += 1
2137
		enb_log_file.close()
Raphael Defosseux's avatar
Raphael Defosseux committed
2138 2139
		self.htmleNBFailureMsg = ''
		if uciStatMsgCount > 0:
2140 2141 2142 2143 2144
			statMsg = 'eNB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)'
			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
			self.htmleNBFailureMsg += statMsg + '\n'
		if pdcpFailure > 0:
			statMsg = 'eNB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)'
Raphael Defosseux's avatar
Raphael Defosseux committed
2145 2146
			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
			self.htmleNBFailureMsg += statMsg + '\n'
2147 2148 2149
		if ulschFailure > 0:
			statMsg = 'eNB showed ' + str(ulschFailure) + ' "ULSCH in error in round" message(s)'
			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
2150
			self.htmleNBFailureMsg += statMsg + '\n'
Raphael Defosseux's avatar
Raphael Defosseux committed
2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178
		if rrcSetupRequest > 0 or rrcSetupComplete > 0:
			rrcMsg = 'eNB requested ' + str(rrcSetupRequest) + ' RRC Connection Setup(s)'
			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
			self.htmleNBFailureMsg += rrcMsg + '\n'
			rrcMsg = ' -- ' + str(rrcSetupComplete) + ' were completed'
			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
			self.htmleNBFailureMsg += rrcMsg + '\n'
		if rrcReleaseRequest > 0:
			rrcMsg = 'eNB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)'
			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
			self.htmleNBFailureMsg += rrcMsg + '\n'
		if rrcReconfigRequest > 0 or rrcReconfigComplete > 0:
			rrcMsg = 'eNB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)'
			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
			self.htmleNBFailureMsg += rrcMsg + '\n'
			rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed'
			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
			self.htmleNBFailureMsg += rrcMsg + '\n'
		if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0:
			rrcMsg = 'eNB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)'
			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
			self.htmleNBFailureMsg += rrcMsg + '\n'
			rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed'
			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
			self.htmleNBFailureMsg += rrcMsg + '\n'
			rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected'
			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
			self.htmleNBFailureMsg += rrcMsg + '\n'
2179 2180 2181 2182
		if rachCanceledProcedure > 0:
			rachMsg = 'eNB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)'
			logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m')
			self.htmleNBFailureMsg += rachMsg + '\n'
2183 2184 2185 2186 2187
		if foundSegFault:
			logging.debug('\u001B[1;37;41m eNB ended with a Segmentation Fault! \u001B[0m')
			return ENB_PROCESS_SEG_FAULT
		if foundAssertion:
			logging.debug('\u001B[1;37;41m eNB ended with an assertion! \u001B[0m')
Raphael Defosseux's avatar
Raphael Defosseux committed
2188
			self.htmleNBFailureMsg += msgAssertion
2189 2190 2191
			return ENB_PROCESS_ASSERTION
		if foundRealTimeIssue:
			logging.debug('\u001B[1;37;41m eNB faced real time issues! \u001B[0m')
2192 2193
			self.htmleNBFailureMsg += 'eNB faced real time issues!\n'
			#return ENB_PROCESS_REALTIME_ISSUE
2194 2195 2196 2197 2198
		if rlcDiscardBuffer > 0:
			rlcMsg = 'eNB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)'
			logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m')
			self.htmleNBFailureMsg += rlcMsg + '\n'
			return ENB_PROCESS_REALTIME_ISSUE
2199 2200
		return 0

2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350
	def AnalyzeLogFile_UE(self, UElogFile):
		if (not os.path.isfile('./' + UElogFile)):
			return -1
		ue_log_file = open('./' + UElogFile, 'r')
		foundAssertion = False
		msgAssertion = ''
		msgLine = 0
		foundSegFault = False
		foundRealTimeIssue = False
		rlcDiscardBuffer = 0
		rachCanceledProcedure = 0
		uciStatMsgCount = 0
		pdcpFailure = 0
		ulschFailure = 0
		no_cell_sync_found = False
		mib_found = False
		frequency_found = False
		self.htmlUEFailureMsg = ''
		for line in ue_log_file.readlines():
			result = re.search('[Ss]egmentation [Ff]ault', str(line))
			if result is not None:
				foundSegFault = True
			result = re.search('[Cc]ore [dD]ump', str(line))
			if result is not None:
				foundSegFault = True
			result = re.search('[Aa]ssertion', str(line))
			if result is not None:
				foundAssertion = True
			result = re.search('LLL', str(line))
			if result is not None:
				foundRealTimeIssue = True
			if foundAssertion and (msgLine < 3):
				msgLine += 1
				msgAssertion += str(line)
			result = re.search('uci->stat', str(line))
			if result is not None:
				uciStatMsgCount += 1
			# No cell synchronization found, abandoning
			result = re.search('No cell synchronization found, abandoning', str(line))
			if result is not None:
				no_cell_sync_found = True
			result = re.search("MIB Information => ([a-zA-Z]{1,10}), ([a-zA-Z]{1,10}), NidCell (?P<nidcell>\d{1,3}), N_RB_DL (?P<n_rb_dl>\d{1,3}), PHICH DURATION (?P<phich_duration>\d), PHICH RESOURCE (?P<phich_resource>.{1,4}), TX_ANT (?P<tx_ant>\d)", str(line))
			if result is not None and (not mib_found):
				try:
					mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2)
					self.htmlUEFailureMsg += mibMsg + '\n'
					logging.debug('\033[94m' + mibMsg + '\033[0m')
					mibMsg = "    nidcell = " + result.group('nidcell')
					self.htmlUEFailureMsg += mibMsg
					logging.debug('\033[94m' + mibMsg + '\033[0m')
					mibMsg = "    n_rb_dl = " + result.group('n_rb_dl')
					self.htmlUEFailureMsg += mibMsg + '\n'
					logging.debug('\033[94m' + mibMsg + '\033[0m')
					mibMsg = "    phich_duration = " + result.group('phich_duration')
					self.htmlUEFailureMsg += mibMsg
					logging.debug('\033[94m' + mibMsg + '\033[0m')
					mibMsg = "    phich_resource = " + result.group('phich_resource')
					self.htmlUEFailureMsg += mibMsg + '\n'
					logging.debug('\033[94m' + mibMsg + '\033[0m')
					mibMsg = "    tx_ant = " + result.group('tx_ant')
					self.htmlUEFailureMsg += mibMsg + '\n'
					logging.debug('\033[94m' + mibMsg + '\033[0m')
					mib_found = True
				except Exception as e:
					logging.error('\033[91m' + "MIB marker was not found" + '\033[0m')
			result = re.search("Measured Carrier Frequency (?P<measured_carrier_frequency>\d{1,15}) Hz", str(line))
			if result is not None and (not frequency_found):
				try:
					mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz'
					self.htmlUEFailureMsg += mibMsg + '\n'
					logging.debug('\033[94m' + mibMsg + '\033[0m')
					frequency_found = True
				except Exception as e:
					logging.error('\033[91m' + "Measured Carrier Frequency not found" + '\033[0m')
			result = re.search("Found (?P<operator>[\w,\s]{1,15}) \(name from internal table\)", str(line))
			if result is not None:
				try:
					mibMsg = "The operator is: " + result.group('operator')
					self.htmlUEFailureMsg += mibMsg + '\n'
					logging.debug('\033[94m' + mibMsg + '\033[0m')
				except Exception as e:
					logging.error('\033[91m' + "Operator name not found" + '\033[0m')
			result = re.search("SIB5 InterFreqCarrierFreq element (.{1,4})/(.{1,4})", str(line))
			if result is not None:
				try:
					mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2)
					self.htmlUEFailureMsg += mibMsg + ' -> '
					logging.debug('\033[94m' + mibMsg + '\033[0m')
				except Exception as e:
					logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m')
			result = re.search("DL Carrier Frequency/ARFCN : (?P<carrier_frequency>\d{1,15}/\d{1,4})", str(line))
			if result is not None:
				try:
					freq = result.group('carrier_frequency')
					new_freq = re.sub('/[0-9]+','',freq)
					float_freq = float(new_freq) / 1000000
					self.htmlUEFailureMsg += 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz'
					logging.debug('\033[94m' + "    DL Carrier Frequency is: " + freq + '\033[0m')
				except Exception as e:
					logging.error('\033[91m' + "    DL Carrier Frequency not found" + '\033[0m')
			result = re.search("AllowedMeasBandwidth : (?P<allowed_bandwidth>\d{1,7})", str(line))
			if result is not None:
				try:
					prb = result.group('allowed_bandwidth')
					self.htmlUEFailureMsg += ' -- PRB: ' + prb + '\n'
					logging.debug('\033[94m' + "    AllowedMeasBandwidth: " + prb + '\033[0m')
				except Exception as e:
					logging.error('\033[91m' + "    AllowedMeasBandwidth not found" + '\033[0m')
		ue_log_file.close()
		if uciStatMsgCount > 0:
			statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)'
			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
			self.htmlUEFailureMsg += statMsg + '\n'
		if pdcpFailure > 0:
			statMsg = 'UE showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)'
			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
			self.htmlUEFailureMsg += statMsg + '\n'
		if ulschFailure > 0:
			statMsg = 'UE showed ' + str(ulschFailure) + ' "ULSCH in error in round" message(s)'
			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
			self.htmlUEFailureMsg += statMsg + '\n'
		if rachCanceledProcedure > 0:
			rachMsg = 'UE cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)'
			logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m')
			self.htmlUEFailureMsg += rachMsg + '\n'
		if foundSegFault:
			logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m')
			return ENB_PROCESS_SEG_FAULT
		if foundAssertion:
			logging.debug('\u001B[1;37;43m UE ended with an assertion! \u001B[0m')
			# removed for esthetics
			#self.htmlUEFailureMsg += msgAssertion
			self.htmlUEFailureMsg += 'UE ended with an assertion!\n'
			if not mib_found or not frequency_found:
				return UE_PROCESS_ASSERTION
		if foundRealTimeIssue:
			logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m')
			self.htmlUEFailureMsg += 'UE faced real time issues!\n'
			#return ENB_PROCESS_REALTIME_ISSUE
		if no_cell_sync_found and not mib_found:
			logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m')
			self.htmlUEFailureMsg += 'UE could not synchronize!\n'
			return UE_PROCESS_COULD_NOT_SYNC
		if rlcDiscardBuffer > 0:
			rlcMsg = 'UE RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)'
			logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m')
			self.htmlUEFailureMsg += rlcMsg + '\n'
			return ENB_PROCESS_REALTIME_ISSUE
		return 0

2351 2352
	def TerminateeNB(self):
		self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
2353
		self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5)
Boris Djalal's avatar
Fix  
Boris Djalal committed
2354
		#to use daemon on CentOS we need to source the function
Boris Djalal's avatar
Test  
Boris Djalal committed
2355 2356 2357 2358
		#linux_distro = platform.linux_distribution()[0]		
		#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
			#self.command('source /etc/init.d/functions', '\$', 5)
		#use nohup instead of daemon
Boris Djalal's avatar
Boris Djalal committed
2359
		##self.command('echo ' + self.eNBPassword + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5)
Boris Djalal's avatar
Test  
Boris Djalal committed
2360
		#self.command('echo $USER; nohup sudo ./my-lte-softmodem-run ' + ' > ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log' + ' 2>&1 &', self.eNBUserName, 5)
Boris Djalal's avatar
Test.  
Boris Djalal committed
2361
		##self.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
2362
		self.command('echo ' + self.eNBPassword + ' | sudo -S killall --signal SIGINT ' + self.air_interface + '-softmodem || true', '\$', 5)
2363
		time.sleep(5)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
2364 2365
		self.command('stdbuf -o0  ps -aux | grep -v grep | grep ' + self.air_interface + '-softmodem', '\$', 5)
		result = re.search(air_interface + '-softmodem', str(self.ssh.before))
2366
		if result is not None:
Boris Djalal's avatar
WIP.  
Boris Djalal committed
2367
			self.command('echo ' + self.eNBPassword + ' | sudo -S killall --signal SIGKILL ' + self.air_interface + '-softmodem || true', '\$', 5)
2368
			time.sleep(5)
2369
		self.close()
2370 2371
		# If tracer options is on, stopping tshark on EPC side
		result = re.search('T_stdout', str(self.Initialize_eNB_args))
2372
		if result is not None:
2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396
			self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
			logging.debug('\u001B[1m Stopping tshark \u001B[0m')
			self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5)
			time.sleep(1)
			pcap_log_file = self.eNBLogFile.replace('.log', '_s1log.pcap')
			self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + pcap_log_file, '\$', 5)
			self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + pcap_log_file, '.')
			self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, pcap_log_file, self.eNBSourceCodePath + '/cmake_targets/.')
			self.close()
			logging.debug('\u001B[1m Replaying RAW record file\u001B[0m')
			self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
			self.command('cd ' + self.eNBSourceCodePath + '/common/utils/T/tracer/', '\$', 5)
			raw_record_file = self.eNBLogFile.replace('.log', '_record.raw')
			replay_log_file = self.eNBLogFile.replace('.log', '_replay.log')
			extracted_txt_file = self.eNBLogFile.replace('.log', '_extracted_messages.txt')
			extracted_log_file = self.eNBLogFile.replace('.log', '_extracted_messages.log')
			self.command('./extract_config -i ' + self.eNBSourceCodePath + '/cmake_targets/' + raw_record_file + ' > ' + self.eNBSourceCodePath + '/cmake_targets/' + extracted_txt_file, '\$', 5)
			self.command('echo $USER; nohup ./replay -i ' + self.eNBSourceCodePath + '/cmake_targets/' + raw_record_file + ' > ' + self.eNBSourceCodePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', self.eNBUserName, 5)
			self.command('./textlog -d ' +  self.eNBSourceCodePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + self.eNBSourceCodePath + '/cmake_targets/' + extracted_log_file, '\$', 5)
			self.close()
			self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + extracted_log_file, '.')
			logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m')
			logStatus = self.AnalyzeLogFile_eNB(extracted_log_file)
			self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
2397
			self.eNBLogFile = ''
2398
		else:
2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418
			result = re.search('enb_', str(self.eNBLogFile))
			if result is not None:
				copyin_res = self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFile, '.')
				if (copyin_res == -1):
					logging.debug('\u001B[1;37;41m Could not copy eNB logfile to analyze it! \u001B[0m')
					self.htmleNBFailureMsg = 'Could not copy eNB logfile to analyze it!'
					self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE)
					self.eNBLogFile = ''
					return
				logging.debug('\u001B[1m Analyzing eNB logfile \u001B[0m')
				logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFile)
				if (logStatus < 0):
					self.CreateHtmlTestRow('N/A', 'KO', logStatus)
					self.CreateHtmlTabFooter(False)
					sys.exit(1)
				else:
					self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
				self.eNBLogFile = ''
			else:
				self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
2419 2420 2421 2422 2423 2424

	def TerminateHSS(self):
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
		if re.match('OAI', self.EPCType, re.IGNORECASE):
			self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5)
			time.sleep(2)
2425
			self.command('stdbuf -o0  ps -aux | grep -v grep | grep hss', '\$', 5)
2426 2427 2428 2429
			result = re.search('\/bin\/bash .\/run_', str(self.ssh.before))
			if result is not None:
				self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5)
		else:
2430 2431 2432
			self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
			self.command('cd scripts', '\$', 5)
			self.command('rm -f ./kill_hss.sh', '\$', 5)
Boris Djalal's avatar
Fix  
Boris Djalal committed
2433
			#to use daemon on CentOS we need to source the function
Boris Djalal's avatar
Test  
Boris Djalal committed
2434 2435 2436
			#linux_distro = platform.linux_distribution()[0]         
			#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
				#self.command('source /etc/init.d/functions', '\$', 5)
2437
			self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5)
2438 2439
			time.sleep(1)
			self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5)
2440
		self.close()
2441
		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
2442 2443 2444 2445 2446 2447

	def TerminateMME(self):
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
		if re.match('OAI', self.EPCType, re.IGNORECASE):
			self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5)
			time.sleep(2)
2448
			self.command('stdbuf -o0 ps -aux | grep -v grep | grep mme', '\$', 5)
2449 2450 2451 2452
			result = re.search('\/bin\/bash .\/run_', str(self.ssh.before))
			if result is not None:
				self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_mme mme || true', '\$', 5)
		else:
2453
			self.command('cd /opt/ltebox/tools', '\$', 5)
2454 2455
			self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_mme', '\$', 5)
		self.close()
2456
		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
2457 2458 2459 2460 2461 2462

	def TerminateSPGW(self):
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
		if re.match('OAI', self.EPCType, re.IGNORECASE):
			self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5)
			time.sleep(2)
2463
			self.command('stdbuf -o0 ps -aux | grep -v grep | grep spgw', '\$', 5)
2464 2465 2466 2467
			result = re.search('\/bin\/bash .\/run_', str(self.ssh.before))
			if result is not None:
				self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_spgw spgw || true', '\$', 5)
		else:
2468
			self.command('cd /opt/ltebox/tools', '\$', 5)
2469 2470
			self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_xGw', '\$', 5)
		self.close()
2471
		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
2472

2473 2474 2475 2476 2477 2478
	def TerminateUE_common(self, device_id):
		try:
			self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
			self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60)
			logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m')

2479 2480 2481 2482 2483
			self.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5)
			result = re.search('shell +(?P<pid>\d+)', str(self.ssh.before))
			if result is not None:
				pid_iperf = result.group('pid')
				self.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5)
2484 2485 2486 2487 2488 2489
			self.close()
		except:
			os.kill(os.getppid(),signal.SIGUSR1)

	def TerminateUE(self):
		terminate_ue_flag = True
2490
		self.GetAllUEDevices(terminate_ue_flag)
2491 2492 2493 2494 2495 2496 2497 2498
		multi_jobs = []
		for device_id in self.UEDevices:
			p = Process(target= SSH.TerminateUE_common, args = (device_id,))
			p.daemon = True
			p.start()
			multi_jobs.append(p)
		for job in multi_jobs:
			job.join()
2499
		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
2500

2501 2502 2503
	def TerminateOAIUE(self):
		self.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
		self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5)
Boris Djalal's avatar
Fix  
Boris Djalal committed
2504
		#to use daemon on CentOS we need to source the function
Boris Djalal's avatar
Test  
Boris Djalal committed
2505 2506 2507
		#linux_distro = platform.linux_distribution()[0]
		#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
			#self.command('source /etc/init.d/functions', '\$', 5)
Boris Djalal's avatar
Boris Djalal committed
2508
		##self.command('echo ' + self.UEPassword + ' | sudo -S daemon --name=ue' + str(self.UE_instance) + '_daemon --stop', '\$', 5)
Boris Djalal's avatar
Test.  
Boris Djalal committed
2509
		##self.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
2510
		self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT ' + self.air_interface + '-uesoftmodem || true', '\$', 5)
2511
		time.sleep(5)
Boris Djalal's avatar
WIP.  
Boris Djalal committed
2512 2513
		self.command('stdbuf -o0  ps -aux | grep -v grep | grep ' + self.air_interface + '-uesoftmodem', '\$', 5)
		result = re.search(air_interface + '-uesoftmodem', str(self.ssh.before))
2514
		if result is not None:
Boris Djalal's avatar
WIP.  
Boris Djalal committed
2515
			self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL ' + self.air_interface + '-uesoftmodem || true', '\$', 5)
2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573
			time.sleep(5)
		self.close()
		# If tracer options is on, stopping tshark on EPC side
		result = re.search('T_stdout', str(self.Initialize_OAI_UE_args))
		if result is not None:
			self.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
			logging.debug('\u001B[1m Stopping tshark \u001B[0m')
			self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5)
			time.sleep(1)
			pcap_log_file = self.UELogFile.replace('.log', '_s1log.pcap')
			self.command('echo ' + self.UEPassword + ' | sudo -S chmod 666 /tmp/' + pcap_log_file, '\$', 5)
			self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, '/tmp/' + pcap_log_file, '.')
			self.copyout(self.UEIPAddress, self.UEUserName, self.UEPassword, pcap_log_file, self.UESourceCodePath + '/cmake_targets/.')
			self.close()
			logging.debug('\u001B[1m Replaying RAW record file\u001B[0m')
			self.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
			self.command('cd ' + self.UESourceCodePath + '/common/utils/T/tracer/', '\$', 5)
			raw_record_file = self.UELogFile.replace('.log', '_record.raw')
			replay_log_file = self.UELogFile.replace('.log', '_replay.log')
			extracted_txt_file = self.UELogFile.replace('.log', '_extracted_messages.txt')
			extracted_log_file = self.UELogFile.replace('.log', '_extracted_messages.log')
			self.command('./extract_config -i ' + self.UESourceCodePath + '/cmake_targets/' + raw_record_file + ' > ' + self.UESourceCodePath + '/cmake_targets/' + extracted_txt_file, '\$', 5)
			self.command('echo $USER; nohup ./replay -i ' + self.UESourceCodePath + '/cmake_targets/' + raw_record_file + ' > ' + self.UESourceCodePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', self.UEUserName, 5)
			self.command('./textlog -d ' +  self.UESourceCodePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + self.UESourceCodePath + '/cmake_targets/' + extracted_log_file, '\$', 5)
			self.close()
			self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + extracted_log_file, '.')
			logging.debug('\u001B[1m Analyzing UE replay logfile \u001B[0m')
			logStatus = self.AnalyzeLogFile_UE(extracted_log_file)
			self.CreateHtmlTestRow(html_queue, 'OK', ALL_PROCESSES_OK)
			self.UELogFile = ''
		else:
			result = re.search('ue_', str(self.UELogFile))
			if result is not None:
				copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.')
				if (copyin_res == -1):
					logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m')
					optionsMsg = '<pre style="background-color:white">Could not copy UE logfile to analyze it!</pre>'
					self.CreateHtmlTestRow(optionsMsg, 'KO', UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE')
					self.UELogFile = ''
					return
				logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m')
				logStatus = self.AnalyzeLogFile_UE(self.UELogFile)
				if (logStatus < 0):
					optionsMsg = '<pre style="background-color:white"><b>Sniffing Unsuccessful</b>\n'
					optionsMsg += self.htmlUEFailureMsg
					optionsMsg += '</pre>'
					self.CreateHtmlTestRow(optionsMsg, 'KO', logStatus, 'UE')
					self.CreateHtmlTabFooter(False)
					sys.exit(1)
				else:
					optionsMsg = '<pre style="background-color:white"><b>Sniffing Successful</b>\n'
					optionsMsg += self.htmlUEFailureMsg
					optionsMsg += '</pre>'
					self.CreateHtmlTestRow(optionsMsg, 'OK', ALL_PROCESSES_OK)
				self.UELogFile = ''
			else:
				self.CreateHtmlTestRow('<pre style="background-color:white">No Log File to analyze</pre>', 'OK', ALL_PROCESSES_OK)

2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584
	def AutoTerminateUEandeNB(self):
		self.testCase_id = 'AUTO-KILL-UE'
		self.desc = 'Automatic Termination of UE'
		self.ShowTestID()
		self.TerminateUE()
		self.testCase_id = 'AUTO-KILL-eNB'
		self.desc = 'Automatic Termination of eNB'
		self.ShowTestID()
		self.eNB_instance = '0'
		self.TerminateeNB()

2585 2586 2587 2588
	def IdleSleep(self):
		time.sleep(self.idle_sleep_time)
		self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK)

2589
	def LogCollectBuild(self):
2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603
		if (self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != ''):
			IPAddress = self.eNBIPAddress
			UserName = self.eNBUserName
			Password = self.eNBPassword
			SourceCodePath = self.eNBSourceCodePath
		elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''):
			IPAddress = self.UEIPAddress
			UserName = self.UEUserName
			Password = self.UEPassword
			SourceCodePath = self.UESourceCodePath
		else:
			sys.exit('Insufficient Parameter')
		self.open(IPAddress, UserName, Password)
		self.command('cd ' + SourceCodePath, '\$', 5)
2604
		self.command('cd cmake_targets', '\$', 5)
Raphael Defosseux's avatar
Raphael Defosseux committed
2605
		self.command('rm -f build.log.zip', '\$', 5)
2606
		self.command('zip build.log.zip build_log_*/*', '\$', 60)
Raphael Defosseux's avatar
Raphael Defosseux committed
2607
		self.command('echo ' + self.eNBPassword + ' | sudo -S rm -rf build_log_*', '\$', 5)
2608
		self.close()
2609

2610 2611 2612 2613
	def LogCollecteNB(self):
		self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
		self.command('cd ' + self.eNBSourceCodePath, '\$', 5)
		self.command('cd cmake_targets', '\$', 5)
2614
		self.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5)
2615 2616
		self.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60)
		self.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5)
2617
		self.close()
2618

2619 2620 2621 2622
	def LogCollectPing(self):
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
		self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
		self.command('cd scripts', '\$', 5)
Raphael Defosseux's avatar
Raphael Defosseux committed
2623
		self.command('rm -f ping.log.zip', '\$', 5)
2624 2625 2626
		self.command('zip ping.log.zip ping*.log', '\$', 60)
		self.command('rm ping*.log', '\$', 5)
		self.close()
2627

2628 2629 2630 2631
	def LogCollectIperf(self):
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
		self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
		self.command('cd scripts', '\$', 5)
Raphael Defosseux's avatar
Raphael Defosseux committed
2632
		self.command('rm -f iperf.log.zip', '\$', 5)
2633 2634 2635
		self.command('zip iperf.log.zip iperf*.log', '\$', 60)
		self.command('rm iperf*.log', '\$', 5)
		self.close()
2636

2637 2638
	def LogCollectHSS(self):
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
2639 2640
		self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
		self.command('cd scripts', '\$', 5)
Raphael Defosseux's avatar
Raphael Defosseux committed
2641
		self.command('rm -f hss.log.zip', '\$', 5)
2642 2643 2644
		if re.match('OAI', self.EPCType, re.IGNORECASE):
			self.command('zip hss.log.zip hss*.log', '\$', 60)
			self.command('rm hss*.log', '\$', 5)
2645 2646 2647
		else:
			self.command('cp /opt/hss_sim0609/hss.log .', '\$', 60)
			self.command('zip hss.log.zip hss.log', '\$', 60)
2648
		self.close()
2649

2650 2651 2652
	def LogCollectMME(self):
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
		self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
2653
		self.command('cd scripts', '\$', 5)
Raphael Defosseux's avatar
Raphael Defosseux committed
2654
		self.command('rm -f mme.log.zip', '\$', 5)
2655 2656 2657 2658
		if re.match('OAI', self.EPCType, re.IGNORECASE):
			self.command('zip mme.log.zip mme*.log', '\$', 60)
			self.command('rm mme*.log', '\$', 5)
		else:
2659 2660
			self.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5)
			self.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0', '\$', 60)
2661
		self.close()
2662

2663 2664 2665
	def LogCollectSPGW(self):
		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
		self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
2666
		self.command('cd scripts', '\$', 5)
Raphael Defosseux's avatar
Raphael Defosseux committed
2667
		self.command('rm -f spgw.log.zip', '\$', 5)
2668 2669 2670 2671
		if re.match('OAI', self.EPCType, re.IGNORECASE):
			self.command('zip spgw.log.zip spgw*.log', '\$', 60)
			self.command('rm spgw*.log', '\$', 5)
		else:
2672 2673
			self.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5)
			self.command('zip spgw.log.zip xGwLog.0', '\$', 60)
2674
		self.close()
2675

2676 2677 2678 2679 2680 2681 2682 2683 2684
	def LogCollectOAIUE(self):
		self.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
		self.command('cd ' + self.UESourceCodePath, '\$', 5)
		self.command('cd cmake_targets', '\$', 5)
		self.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5)
		self.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60)
		self.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5)
		self.close()

2685 2686
	def RetrieveSystemVersion(self):
		if self.eNBIPAddress == 'none':
2687 2688 2689 2690 2691 2692 2693
			self.OsVersion = 'Ubuntu 16.04.5 LTS'
			self.KernelVersion = '4.15.0-45-generic'
			self.UhdVersion = '3.13.0.1-0'
			self.UsrpBoard = 'B210'
			self.CpuNb = '4'
			self.CpuModel = 'Intel(R) Core(TM) i5-6200U'
			self.CpuMHz = '2399.996 MHz'
2694
			return
2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706
		machine = None
		if self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != '':
			machine = 'eNB'
			IPAddress = self.eNBIPAddress
			UserName = self.eNBUserName
			Password = self.eNBPassword
		elif self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != '':
			machine = 'UE'
			IPAddress = self.UEIPAddress
			UserName = self.UEUserName
			Password = self.UEPassword
		if machine is None:
2707 2708
			Usage()
			sys.exit('Insufficient Parameter')
2709
		self.open(IPAddress, UserName, Password)
2710 2711 2712
		self.command('lsb_release -a', '\$', 5)
		result = re.search('Description:\\\\t(?P<os_type>[a-zA-Z0-9\-\_\.\ ]+)', str(self.ssh.before))
		if result is not None:
2713 2714
			self.OsVersion = result.group('os_type')
			logging.debug('OS is: ' + self.OsVersion)
2715 2716 2717
		self.command('uname -r', '\$', 5)
		result = re.search('uname -r\\\\r\\\\n(?P<kernel_version>[a-zA-Z0-9\-\_\.]+)', str(self.ssh.before))
		if result is not None:
2718 2719
			self.KernelVersion = result.group('kernel_version')
			logging.debug('Kernel Version is: ' + self.KernelVersion)
2720 2721 2722
		self.command('dpkg --list | egrep --color=never libuhd003', '\$', 5)
		result = re.search('libuhd003:amd64 *(?P<uhd_version>[0-9\.]+)', str(self.ssh.before))
		if result is not None:
2723 2724
			self.UhdVersion = result.group('uhd_version')
			logging.debug('UHD Version is: ' + self.UhdVersion)
2725
		self.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 12)
2726 2727 2728 2729
		result = re.search('product: (?P<usrp_board>[0-9A-Za-z]+)\\\\r\\\\n', str(self.ssh.before))
		if result is not None:
			self.UsrpBoard = result.group('usrp_board')
			logging.debug('USRP Board  is: ' + self.UsrpBoard)
2730 2731 2732
		self.command('lscpu', '\$', 5)
		result = re.search('CPU\(s\): *(?P<nb_cpus>[0-9]+).*Model name: *(?P<model>[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P<cpu_mhz>[0-9\.]+)', str(self.ssh.before))
		if result is not None:
2733 2734 2735 2736 2737 2738
			self.CpuNb = result.group('nb_cpus')
			logging.debug('nb_cpus: ' + self.CpuNb)
			self.CpuModel = result.group('model')
			logging.debug('model: ' + self.CpuModel)
			self.CpuMHz = result.group('cpu_mhz') + ' MHz'
			logging.debug('cpu_mhz: ' + self.CpuMHz)
2739 2740
		self.close()

2741
#-----------------------------------------------------------
Raphael Defosseux's avatar
Raphael Defosseux committed
2742 2743 2744 2745
# HTML Reporting....
#-----------------------------------------------------------
	def CreateHtmlHeader(self):
		if (not self.htmlHeaderCreated):
2746 2747 2748
			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
			logging.debug('\u001B[1m  Creating HTML header \u001B[0m')
			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
Raphael Defosseux's avatar
Raphael Defosseux committed
2749 2750 2751 2752
			self.htmlFile = open('test_results.html', 'w')
			self.htmlFile.write('<!DOCTYPE html>\n')
			self.htmlFile.write('<html class="no-js" lang="en-US">\n')
			self.htmlFile.write('<head>\n')
2753 2754 2755 2756
			self.htmlFile.write('  <meta name="viewport" content="width=device-width, initial-scale=1">\n')
			self.htmlFile.write('  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">\n')
			self.htmlFile.write('  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>\n')
			self.htmlFile.write('  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2757 2758
			self.htmlFile.write('  <title>Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID</title>\n')
			self.htmlFile.write('</head>\n')
2759 2760
			self.htmlFile.write('<body><div class="container">\n')
			self.htmlFile.write('  <br>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2761 2762 2763 2764
			self.htmlFile.write('  <table style="border-collapse: collapse; border: none;">\n')
			self.htmlFile.write('    <tr style="border-collapse: collapse; border: none;">\n')
			self.htmlFile.write('      <td style="border-collapse: collapse; border: none;">\n')
			self.htmlFile.write('        <a href="http://www.openairinterface.org/">\n')
2765
			self.htmlFile.write('           <img src="http://www.openairinterface.org/wp-content/uploads/2016/03/cropped-oai_final_logo2.png" alt="" border="none" height=50 width=150>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2766 2767 2768 2769 2770 2771 2772 2773 2774
			self.htmlFile.write('           </img>\n')
			self.htmlFile.write('        </a>\n')
			self.htmlFile.write('      </td>\n')
			self.htmlFile.write('      <td style="border-collapse: collapse; border: none; vertical-align: center;">\n')
			self.htmlFile.write('        <b><font size = "6">Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID</font></b>\n')
			self.htmlFile.write('      </td>\n')
			self.htmlFile.write('    </tr>\n')
			self.htmlFile.write('  </table>\n')
			self.htmlFile.write('  <br>\n')
2775
			self.htmlFile.write('  <div class="alert alert-info"><strong> <span class="glyphicon glyphicon-dashboard"></span> TEMPLATE_STAGE_NAME</strong></div>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2776 2777
			self.htmlFile.write('  <table border = "1">\n')
			self.htmlFile.write('     <tr>\n')
2778
			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-time"></span> Build Start Time (UTC) </td>\n')
2779 2780 2781
			self.htmlFile.write('       <td>TEMPLATE_BUILD_TIME</td>\n')
			self.htmlFile.write('     </tr>\n')
			self.htmlFile.write('     <tr>\n')
2782 2783
			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-cloud-upload"></span> GIT Repository </td>\n')
			self.htmlFile.write('       <td><a href="' + self.eNBRepository + '">' + self.eNBRepository + '</a></td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2784 2785
			self.htmlFile.write('     </tr>\n')
			self.htmlFile.write('     <tr>\n')
2786 2787
			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-wrench"></span> Job Trigger </td>\n')
			if (self.eNB_AllowMerge):
Raphael Defosseux's avatar
Raphael Defosseux committed
2788 2789 2790 2791 2792
				self.htmlFile.write('       <td>Merge-Request</td>\n')
			else:
				self.htmlFile.write('       <td>Push to Branch</td>\n')
			self.htmlFile.write('     </tr>\n')
			self.htmlFile.write('     <tr>\n')
2793 2794
			if (self.eNB_AllowMerge):
				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-out"></span> Source Branch </td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2795
			else:
2796 2797
				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tree-deciduous"></span> Branch</td>\n')
			self.htmlFile.write('       <td>' + self.eNBBranch + '</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2798 2799
			self.htmlFile.write('     </tr>\n')
			self.htmlFile.write('     <tr>\n')
2800 2801
			if (self.eNB_AllowMerge):
				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Source Commit ID </td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2802
			else:
2803 2804
				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Commit ID </td>\n')
			self.htmlFile.write('       <td>' + self.eNBCommitID + '</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2805
			self.htmlFile.write('     </tr>\n')
2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816
			if self.eNB_AllowMerge != '':
				commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.eNBCommitID, shell=True, universal_newlines=True)
				commit_message = commit_message.strip()
				self.htmlFile.write('     <tr>\n')
				if (self.eNB_AllowMerge):
					self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-comment"></span> Source Commit Message </td>\n')
				else:
					self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-comment"></span> Commit Message </td>\n')
				self.htmlFile.write('       <td>' + commit_message + '</td>\n')
				self.htmlFile.write('     </tr>\n')
			if (self.eNB_AllowMerge):
Raphael Defosseux's avatar
Raphael Defosseux committed
2817
				self.htmlFile.write('     <tr>\n')
2818 2819 2820 2821 2822
				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-in"></span> Target Branch </td>\n')
				if (self.eNBTargetBranch == ''):
					self.htmlFile.write('       <td>develop</td>\n')
				else:
					self.htmlFile.write('       <td>' + self.eNBTargetBranch + '</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2823 2824 2825
				self.htmlFile.write('     </tr>\n')
			self.htmlFile.write('  </table>\n')

2826
			if (self.ADBIPAddress != 'none'):
2827
				terminate_ue_flag = True
2828 2829
				self.GetAllUEDevices(terminate_ue_flag)
				self.GetAllCatMDevices(terminate_ue_flag)
2830 2831 2832
				self.htmlUEConnected = len(self.UEDevices)
				self.htmlFile.write('  <h2><span class="glyphicon glyphicon-phone"></span> <span class="glyphicon glyphicon-menu-right"></span> ' + str(len(self.UEDevices)) + ' UE(s) is(are) connected to ADB bench server</h2>\n')
				self.htmlFile.write('  <h2><span class="glyphicon glyphicon-phone"></span> <span class="glyphicon glyphicon-menu-right"></span> ' + str(len(self.CatMDevices)) + ' CAT-M UE(s) is(are) connected to bench server</h2>\n')
2833
			self.htmlFile.write('  <br>\n')
2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848
			self.htmlFile.write('  <ul class="nav nav-pills">\n')
			count = 0
			while (count < self.nbTestXMLfiles):
				pillMsg = '    <li><a data-toggle="pill" href="#'
				pillMsg += self.htmlTabRefs[count]
				pillMsg += '">'
				pillMsg += self.htmlTabNames[count]
				pillMsg += ' <span class="glyphicon glyphicon-'
				pillMsg += self.htmlTabIcons[count]
				pillMsg += '"></span></a></li>\n'
				self.htmlFile.write(pillMsg)
				count += 1
			self.htmlFile.write('  </ul>\n')
			self.htmlFile.write('  <div class="tab-content">\n')
			self.htmlFile.close()
2849

2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860
	def CreateHtmlTabHeader(self):
		if (not self.htmlHeaderCreated):
			if (not os.path.isfile('test_results.html')):
				self.CreateHtmlHeader()
			self.htmlFile = open('test_results.html', 'a')
			if (self.nbTestXMLfiles == 1):
				self.htmlFile.write('  <div id="' + self.htmlTabRefs[0] + '" class="tab-pane fade">\n')
				self.htmlFile.write('  <h3>Test Summary for <span class="glyphicon glyphicon-file"></span> ' + self.testXMLfiles[0] + '</h3>\n')
			else:
				self.htmlFile.write('  <div id="build-tab" class="tab-pane fade">\n')
			self.htmlFile.write('  <table class="table" border = "1">\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2861 2862 2863 2864 2865
			self.htmlFile.write('      <tr bgcolor = "#33CCFF" >\n')
			self.htmlFile.write('        <th>Test Id</th>\n')
			self.htmlFile.write('        <th>Test Desc</th>\n')
			self.htmlFile.write('        <th>Test Options</th>\n')
			self.htmlFile.write('        <th>Test Status</th>\n')
2866 2867 2868 2869 2870
			if (self.htmlUEConnected == -1):
				terminate_ue_flag = True
				if (self.ADBIPAddress != 'none'):
					self.GetAllUEDevices(terminate_ue_flag)
					self.GetAllCatMDevices(terminate_ue_flag)
2871 2872 2873 2874
				else:
					self.UEDevices.append('doughq9rehg')
					self.UEDevices.append('dnsgiuahgia')
					self.UEDevices.append('uehgieng9')
2875 2876
				self.htmlUEConnected = len(self.UEDevices)

Raphael Defosseux's avatar
Raphael Defosseux committed
2877 2878 2879 2880 2881 2882 2883
			i = 0
			while (i < self.htmlUEConnected):
				self.htmlFile.write('        <th>UE' + str(i) + ' Status</th>\n')
				i += 1
			self.htmlFile.write('      </tr>\n')
		self.htmlHeaderCreated = True

2884
	def CreateHtmlTabFooter(self, passStatus):
Raphael Defosseux's avatar
Raphael Defosseux committed
2885
		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <th bgcolor = "#33CCFF" colspan=2>Final Tab Status</th>\n')
			if passStatus:
				self.htmlFile.write('        <th bgcolor = "green" colspan=' + str(2 + self.htmlUEConnected) + '><font color="white">PASS <span class="glyphicon glyphicon-ok"></span> </font></th>\n')
			else:
				self.htmlFile.write('        <th bgcolor = "red" colspan=' + str(2 + self.htmlUEConnected) + '><font color="white">FAIL <span class="glyphicon glyphicon-remove"></span> </font></th>\n')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('  </table>\n')
			self.htmlFile.write('  </div>\n')
		self.htmlFooterCreated = False

	def CreateHtmlFooter(self, passStatus):
		if (os.path.isfile('test_results.html')):
2899 2900 2901
			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
			logging.debug('\u001B[1m  Creating HTML footer \u001B[0m')
			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
2902 2903 2904 2905 2906 2907 2908 2909 2910 2911
			self.RetrieveSystemVersion()
			self.htmlFile = open('test_results.html', 'a')
			self.htmlFile.write('</div>\n')
			self.htmlFile.write('  <p></p>\n')
			self.htmlFile.write('  <table class="table table-condensed">\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <th colspan=6>eNB Server Characteristics</th>\n')
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td>OS Version</td>\n')
2912
			self.htmlFile.write('        <td><span class="label label-default">' + self.OsVersion + '</span></td>\n')
2913
			self.htmlFile.write('        <td>Kernel Version</td>\n')
2914
			self.htmlFile.write('        <td><span class="label label-default">' + self.KernelVersion + '</span></td>\n')
2915
			self.htmlFile.write('        <td>UHD Version</td>\n')
2916 2917 2918
			self.htmlFile.write('        <td><span class="label label-default">' + self.UhdVersion + '</span></td>\n')
			self.htmlFile.write('        <td>USRP Board</td>\n')
			self.htmlFile.write('        <td><span class="label label-default">' + self.UsrpBoard + '</span></td>\n')
2919 2920 2921
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <td>Nb CPUs</td>\n')
2922
			self.htmlFile.write('        <td><span class="label label-default">' + self.CpuNb + '</span></td>\n')
2923
			self.htmlFile.write('        <td>CPU Model Name</td>\n')
2924
			self.htmlFile.write('        <td><span class="label label-default">' + self.CpuModel + '</span></td>\n')
2925
			self.htmlFile.write('        <td>CPU Frequency</td>\n')
2926 2927 2928
			self.htmlFile.write('        <td><span class="label label-default">' + self.CpuMHz + '</span></td>\n')
			self.htmlFile.write('        <td></td>\n')
			self.htmlFile.write('        <td></td>\n')
2929 2930 2931
			self.htmlFile.write('      </tr>\n')
			self.htmlFile.write('      <tr>\n')
			self.htmlFile.write('        <th colspan=4 bgcolor = "#33CCFF">Final Status</th>\n')
2932
			if passStatus:
2933
				self.htmlFile.write('        <th colspan=2 bgcolor="green"><font color="white">PASS <span class="glyphicon glyphicon-ok"></span></font></th>\n')
2934
			else:
2935
				self.htmlFile.write('        <th colspan=2 bgcolor="red"><font color="white">FAIL <span class="glyphicon glyphicon-remove"></span> </font></th>\n')
2936
			self.htmlFile.write('      </tr>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2937
			self.htmlFile.write('  </table>\n')
2938 2939 2940
			self.htmlFile.write('  <p></p>\n')
			self.htmlFile.write('  <div class="well well-lg">End of Test Report -- Copyright <span class="glyphicon glyphicon-copyright-mark"></span> 2018 <a href="http://www.openairinterface.org/">OpenAirInterface</a>. All Rights Reserved.</div>\n')
			self.htmlFile.write('</div></body>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2941 2942 2943
			self.htmlFile.write('</html>\n')
			self.htmlFile.close()

2944
	def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'):
Raphael Defosseux's avatar
Raphael Defosseux committed
2945 2946
		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
			self.htmlFile.write('      <tr>\n')
2947 2948
			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + self.testCase_id  + '</td>\n')
			self.htmlFile.write('        <td>' + self.desc  + '</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2949 2950 2951 2952
			self.htmlFile.write('        <td>' + str(options)  + '</td>\n')
			if (str(status) == 'OK'):
				self.htmlFile.write('        <td bgcolor = "lightgreen" >' + str(status)  + '</td>\n')
			elif (str(status) == 'KO'):
Raphael Defosseux's avatar
Raphael Defosseux committed
2953 2954
				if (processesStatus == 0):
					self.htmlFile.write('        <td bgcolor = "lightcoral" >' + str(status)  + '</td>\n')
2955
				elif (processesStatus == ENB_PROCESS_FAILED):
2956
					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process not found</td>\n')
2957
				elif (processesStatus == ENB_PROCESS_SEG_FAULT):
2958 2959 2960
					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process ended in Segmentation Fault</td>\n')
				elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == UE_PROCESS_ASSERTION):
					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process ended in Assertion</td>\n')
2961
				elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE):
2962 2963 2964 2965 2966
					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process faced Real Time issue(s)</td>\n')
				elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == UE_PROCESS_NOLOGFILE_TO_ANALYZE):
					self.htmlFile.write('        <td bgcolor = "orange" >OK?</td>\n')
				elif (processesStatus == UE_PROCESS_COULD_NOT_SYNC):
					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - UE could not sync</td>\n')
2967
				elif (processesStatus == HSS_PROCESS_FAILED):
Raphael Defosseux's avatar
Raphael Defosseux committed
2968
					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - HSS process not found</td>\n')
2969
				elif (processesStatus == MME_PROCESS_FAILED):
Raphael Defosseux's avatar
Raphael Defosseux committed
2970
					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - MME process not found</td>\n')
2971
				elif (processesStatus == SPGW_PROCESS_FAILED):
Raphael Defosseux's avatar
Raphael Defosseux committed
2972
					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - SPGW process not found</td>\n')
2973 2974
				elif (processesStatus == UE_IP_ADDRESS_ISSUE):
					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - Could not retrieve UE IP address</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2975 2976
				else:
					self.htmlFile.write('        <td bgcolor = "lightcoral" >' + str(status)  + '</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2977 2978
			else:
				self.htmlFile.write('        <td bgcolor = "orange" >' + str(status)  + '</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2979
			if (len(str(self.htmleNBFailureMsg)) > 2):
2980 2981 2982 2983 2984
				cellBgColor = 'white'
				result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg)
				if result is not None:
					cellBgColor = 'red'
				else:
2985
					result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg)
2986 2987
					if result is not None:
						cellBgColor = 'orange'
2988 2989
				self.htmlFile.write('        <td bgcolor = "' + cellBgColor + '" colspan=' + str(self.htmlUEConnected) + '><pre style="background-color:' +
 cellBgColor + '">' + self.htmleNBFailureMsg + '</pre></td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
2990
				self.htmleNBFailureMsg = ''
2991 2992 2993 2994 2995
			else:
				i = 0
				while (i < self.htmlUEConnected):
					self.htmlFile.write('        <td>-</td>\n')
					i += 1
Raphael Defosseux's avatar
Raphael Defosseux committed
2996 2997
			self.htmlFile.write('      </tr>\n')

Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
2998 2999
	def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue):
		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
Raphael Defosseux's avatar
Raphael Defosseux committed
3000
			addOrangeBK = False
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
3001
			self.htmlFile.write('      <tr>\n')
3002 3003
			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + self.testCase_id  + '</td>\n')
			self.htmlFile.write('        <td>' + self.desc  + '</td>\n')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
3004 3005 3006 3007 3008 3009
			self.htmlFile.write('        <td>' + str(options)  + '</td>\n')
			if (str(status) == 'OK'):
				self.htmlFile.write('        <td bgcolor = "lightgreen" >' + str(status)  + '</td>\n')
			elif (str(status) == 'KO'):
				self.htmlFile.write('        <td bgcolor = "lightcoral" >' + str(status)  + '</td>\n')
			else:
Raphael Defosseux's avatar
Raphael Defosseux committed
3010
				addOrangeBK = True
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
3011 3012 3013 3014 3015
				self.htmlFile.write('        <td bgcolor = "orange" >' + str(status)  + '</td>\n')
			i = 0
			while (i < self.htmlUEConnected):
				if (i < ue_status):
					if (not ue_queue.empty()):
Raphael Defosseux's avatar
Raphael Defosseux committed
3016
						if (addOrangeBK):
3017
							self.htmlFile.write('        <td bgcolor = "orange" >' + str(ue_queue.get()).replace('white', 'orange') + '</td>\n')
Raphael Defosseux's avatar
Raphael Defosseux committed
3018 3019
						else:
							self.htmlFile.write('        <td>' + str(ue_queue.get()) + '</td>\n')
Raphael Defosseux's avatar
CI:  
Raphael Defosseux committed
3020 3021 3022 3023 3024 3025 3026
					else:
						self.htmlFile.write('        <td>-</td>\n')
				else:
					self.htmlFile.write('        <td>-</td>\n')
				i += 1
			self.htmlFile.write('      </tr>\n')

3027 3028 3029 3030 3031 3032 3033 3034 3035
#-----------------------------------------------------------
# ShowTestID()
#-----------------------------------------------------------
	def ShowTestID(self):
		logging.debug('\u001B[1m----------------------------------------\u001B[0m')
		logging.debug('\u001B[1mTest ID:' + self.testCase_id + '\u001B[0m')
		logging.debug('\u001B[1m' + self.desc + '\u001B[0m')
		logging.debug('\u001B[1m----------------------------------------\u001B[0m')

Raphael Defosseux's avatar
Raphael Defosseux committed
3036
#-----------------------------------------------------------
3037 3038 3039 3040 3041 3042 3043 3044 3045 3046
# Usage()
#-----------------------------------------------------------
def Usage():
	print('------------------------------------------------------------')
	print('main.py Ver:' + Version)
	print('------------------------------------------------------------')
	print('Usage: python main.py [options]')
	print('  --help  Show this help.')
	print('  --mode=[Mode]')
	print('      TesteNB')
3047
	print('      InitiateHtml, FinalizeHtml')
3048 3049
	print('      TerminateeNB, TerminateUE, TerminateHSS, TerminateMME, TerminateSPGW')
	print('      LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf')
3050 3051 3052 3053
	print('  --eNBIPAddress=[eNB\'s IP Address]')
	print('  --eNBRepository=[eNB\'s Repository URL]')
	print('  --eNBBranch=[eNB\'s Branch Name]')
	print('  --eNBCommitID=[eNB\'s Commit Number]')
3054 3055
	print('  --eNB_AllowMerge=[eNB\'s Allow Merge Request (with target branch)]')
	print('  --eNBTargetBranch=[eNB\'s Target Branch in case of a Merge Request]')
3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066
	print('  --eNBUserName=[eNB\'s Login User Name]')
	print('  --eNBPassword=[eNB\'s Login Password]')
	print('  --eNBSourceCodePath=[eNB\'s Source Code Path]')
	print('  --EPCIPAddress=[EPC\'s IP Address]')
	print('  --EPCUserName=[EPC\'s Login User Name]')
	print('  --EPCPassword=[EPC\'s Login Password]')
	print('  --EPCSourceCodePath=[EPC\'s Source Code Path]')
	print('  --EPCType=[EPC\'s Type: OAI or ltebox]')
	print('  --ADBIPAddress=[ADB\'s IP Address]')
	print('  --ADBUserName=[ADB\'s Login User Name]')
	print('  --ADBPassword=[ADB\'s Login Password]')
3067
	print('  --XMLTestFile=[XML Test File to be run]')
3068 3069
	print('------------------------------------------------------------')

3070 3071
#def GetModeFromXML():
#	SSH.mode = test.findtext('mode')
3072

3073
def CheckClassValidity(action,id):
Boris Djalal's avatar
WIP.  
Boris Djalal committed
3074
	if action != 'Build_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'Initialize_OAI_eNB' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW'  and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep':
3075 3076 3077 3078 3079 3080 3081
		logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action)
		return False
	return True

def GetParametersFromXML(action):
	if action == 'Build_eNB':
		SSH.Build_eNB_args = test.findtext('Build_eNB_args')
3082

3083 3084
	if action == 'Initialize_eNB':
		SSH.Initialize_eNB_args = test.findtext('Initialize_eNB_args')
3085 3086 3087
		SSH.eNB_instance = test.findtext('eNB_instance')
		if (SSH.eNB_instance is None):
			SSH.eNB_instance = '0'
Boris Djalal's avatar
WIP.  
Boris Djalal committed
3088 3089 3090 3091 3092 3093
		SSH.air_interface = test.findtext('air_interface')
		if (SSH.air_interface is None):
			SSH.air_interface = 'lte'
		else:
			SSH.air_interface = SSH.air_interface.lower()
	
3094 3095 3096 3097
	if action == 'Terminate_eNB':
		SSH.eNB_instance = test.findtext('eNB_instance')
		if (SSH.eNB_instance is None):
			SSH.eNB_instance = '0'
3098

3099 3100 3101 3102 3103 3104 3105
	if action == 'Attach_UE':
		nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach')
		if (nbMaxUEtoAttach is None):
			SSH.nbMaxUEtoAttach = -1
		else:
			SSH.nbMaxUEtoAttach = int(nbMaxUEtoAttach)

3106 3107
	if action == 'Build_OAI_UE':
		SSH.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args')
Boris Djalal's avatar
WIP.  
Boris Djalal committed
3108 3109 3110 3111 3112
		SSH.clean_repository = test.findtext('clean_repository')
		if (SSH.clean_repository == 'false'):
			SSH.clean_repository = False
		else:
			SSH.clean_repository = True
3113 3114 3115 3116 3117 3118

	if action == 'Initialize_OAI_UE':
		SSH.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args')
		SSH.UE_instance = test.findtext('UE_instance')
		if (SSH.UE_instance is None):
			SSH.UE_instance = '0'
Boris Djalal's avatar
WIP.  
Boris Djalal committed
3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134
		SSH.air_interface = test.findtext('air_interface')
		if (SSH.air_interface is None):
			SSH.air_interface = 'lte'
		else:
			SSH.air_interface = SSH.air_interface.lower()
	
	if action == 'Initialize_OAI_eNB':
		SSH.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_eNB_args')
		SSH.UE_instance = test.findtext('eNB_instance')
		if (SSH.eNB_instance is None):
			SSH.eNB_instance = '0'
		SSH.air_interface = test.findtext('air_interface')
		if (SSH.air_interface is None):
			SSH.air_interface = 'lte'
		else:
			SSH.air_interface = SSH.air_interface.lower()
3135 3136 3137 3138 3139 3140 3141

	if action == 'Terminate_OAI_UE':
		SSH.eNB_instance = test.findtext('UE_instance')
		if (SSH.UE_instance is None):
			SSH.UE_instance = '0'

	if action == 'Ping' or action == 'Ping_CatM_module':
3142 3143 3144 3145 3146 3147
		SSH.ping_args = test.findtext('ping_args')
		SSH.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold')

	if action == 'Iperf':
		SSH.iperf_args = test.findtext('iperf_args')
		SSH.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold')
3148 3149 3150 3151 3152 3153 3154
		SSH.iperf_profile = test.findtext('iperf_profile')
		if (SSH.iperf_profile is None):
			SSH.iperf_profile = 'balanced'
		else:
			if SSH.iperf_profile != 'balanced' and SSH.iperf_profile != 'unbalanced' and SSH.iperf_profile != 'single-ue':
				logging.debug('ERROR: test-case has wrong profile ' + SSH.iperf_profile)
				SSH.iperf_profile = 'balanced'
3155

3156 3157 3158 3159 3160 3161 3162
	if action == 'IdleSleep':
		string_field = test.findtext('idle_sleep_time_in_sec')
		if (string_field is None):
			SSH.idle_sleep_time = 5
		else:
			SSH.idle_sleep_time = int(string_field)

3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182
#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)

#-----------------------------------------------------------
# Parameter Check
#-----------------------------------------------------------
mode = ''
SSH = SSHConnection()

argvs = sys.argv
argc = len(argvs)
3183
cwd = os.getcwd()
3184 3185 3186 3187 3188 3189 3190

while len(argvs) > 1:
	myArgv = argvs.pop(1)	# 0th is this file's name
	if re.match('^\-\-help$', myArgv, re.IGNORECASE):
		Usage()
		sys.exit(0)
	elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE):
3191
		#print('mode: ' + mode)
3192
		matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE)
3193 3194 3195
		#if matchReg and mode is not None:
			#print('Warning: the mode is defined in both xml file and command line')
			#print('ignoring the mode defined in the xml file')
3196
		print('mode: ' + mode)
3197 3198 3199 3200 3201 3202 3203
		mode = matchReg.group(1)
	elif re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE)
		SSH.eNBIPAddress = matchReg.group(1)
	elif re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE)
		SSH.eNBRepository = matchReg.group(1)
Raphael Defosseux's avatar
Raphael Defosseux committed
3204 3205 3206 3207 3208
	elif re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE)
		doMerge = matchReg.group(1)
		if ((doMerge == 'true') or (doMerge == 'True')):
			SSH.eNB_AllowMerge = True
3209 3210 3211 3212 3213 3214
	elif re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE)
		SSH.eNBBranch = matchReg.group(1)
	elif re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE)
		SSH.eNBCommitID = matchReg.group(1)
3215 3216 3217
	elif re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE)
		SSH.eNBTargetBranch = matchReg.group(1)
3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256
	elif re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE)
		SSH.eNBUserName = matchReg.group(1)
	elif re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE)
		SSH.eNBPassword = matchReg.group(1)
	elif re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE)
		SSH.eNBSourceCodePath = matchReg.group(1)
	elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE)
		SSH.EPCIPAddress = matchReg.group(1)
	elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE)
		SSH.EPCBranch = matchReg.group(1)
	elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE)
		SSH.EPCUserName = matchReg.group(1)
	elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE)
		SSH.EPCPassword = matchReg.group(1)
	elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE)
		SSH.EPCSourceCodePath = matchReg.group(1)
	elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE)
		if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE):
			SSH.EPCType = matchReg.group(1)
		else:
			sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox)')
	elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE)
		SSH.ADBIPAddress = matchReg.group(1)
	elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE)
		SSH.ADBUserName = matchReg.group(1)
	elif re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE)
		SSH.ADBPassword = matchReg.group(1)
3257 3258
	elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE)
3259 3260
		SSH.testXMLfiles.append(matchReg.group(1))
		SSH.nbTestXMLfiles += 1
3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272
	elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE)
		SSH.UEIPAddress = matchReg.group(1)
	elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE)
		SSH.UEUserName = matchReg.group(1)
	elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE)
		SSH.UEPassword = matchReg.group(1)
	elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE)
		SSH.UESourceCodePath = matchReg.group(1)
3273 3274 3275 3276 3277
	elif re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE):
		matchReg = re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE)
		finalStatus = matchReg.group(1)
		if ((finalStatus == 'true') or (finalStatus == 'True')):
			SSH.finalStatus = True
3278 3279 3280 3281 3282 3283 3284 3285 3286 3287
	else:
		Usage()
		sys.exit('Invalid Parameter: ' + myArgv)

if re.match('^TerminateeNB$', mode, re.IGNORECASE):
	if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '':
		Usage()
		sys.exit('Insufficient Parameter')
	SSH.TerminateeNB()
elif re.match('^TerminateUE$', mode, re.IGNORECASE):
3288 3289 3290 3291 3292 3293 3294
	if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''):
		Usage()
		sys.exit('Insufficient Parameter')
	signal.signal(signal.SIGUSR1, receive_signal)
	SSH.TerminateUE()
elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE):
	if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '':
3295 3296 3297 3298 3299
		Usage()
		sys.exit('Insufficient Parameter')
	signal.signal(signal.SIGUSR1, receive_signal)
	SSH.TerminateUE()
elif re.match('^TerminateHSS$', mode, re.IGNORECASE):
3300
	if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '':
3301 3302 3303 3304
		Usage()
		sys.exit('Insufficient Parameter')
	SSH.TerminateHSS()
elif re.match('^TerminateMME$', mode, re.IGNORECASE):
3305
	if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '':
3306 3307 3308 3309
		Usage()
		sys.exit('Insufficient Parameter')
	SSH.TerminateMME()
elif re.match('^TerminateSPGW$', mode, re.IGNORECASE):
3310
	if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '':
3311 3312 3313 3314
		Usage()
		sys.exit('Insufficient Parameter')
	SSH.TerminateSPGW()
elif re.match('^LogCollectBuild$', mode, re.IGNORECASE):
3315
	if (SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '') and (SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == ''):
3316 3317 3318 3319 3320 3321 3322 3323 3324
		Usage()
		sys.exit('Insufficient Parameter')
	SSH.LogCollectBuild()
elif re.match('^LogCollecteNB$', mode, re.IGNORECASE):
	if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '':
		Usage()
		sys.exit('Insufficient Parameter')
	SSH.LogCollecteNB()
elif re.match('^LogCollectHSS$', mode, re.IGNORECASE):
3325
	if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '':
3326 3327 3328 3329
		Usage()
		sys.exit('Insufficient Parameter')
	SSH.LogCollectHSS()
elif re.match('^LogCollectMME$', mode, re.IGNORECASE):
3330
	if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '':
3331 3332 3333 3334
		Usage()
		sys.exit('Insufficient Parameter')
	SSH.LogCollectMME()
elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE):
3335
	if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '':
3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348
		Usage()
		sys.exit('Insufficient Parameter')
	SSH.LogCollectSPGW()
elif re.match('^LogCollectPing$', mode, re.IGNORECASE):
	if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '':
		Usage()
		sys.exit('Insufficient Parameter')
	SSH.LogCollectPing()
elif re.match('^LogCollectIperf$', mode, re.IGNORECASE):
	if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '':
		Usage()
		sys.exit('Insufficient Parameter')
	SSH.LogCollectIperf()
3349
elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE):
Boris Djalal's avatar
WIP.  
Boris Djalal committed
3350 3351 3352 3353
	if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '':
		Usage()
		sys.exit('Insufficient Parameter')
	SSH.LogCollectOAIUE()
3354
elif re.match('^InitiateHtml$', mode, re.IGNORECASE):
3355
	if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''):
3356 3357 3358
		Usage()
		sys.exit('Insufficient Parameter')
	count = 0
3359
	foundCount = 0
3360
	while (count < SSH.nbTestXMLfiles):
3361
		xml_test_file = cwd + "/" + SSH.testXMLfiles[count]
3362 3363 3364 3365 3366 3367 3368
		if (os.path.isfile(xml_test_file)):
			xmlTree = ET.parse(xml_test_file)
			xmlRoot = xmlTree.getroot()
			SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count)))
			SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count)))
			SSH.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign'))
			foundCount += 1
3369
		count += 1
3370 3371
	if foundCount != SSH.nbTestXMLfiles:
		SSH.nbTestXMLfiles = foundCount
3372 3373 3374
	SSH.CreateHtmlHeader()
elif re.match('^FinalizeHtml$', mode, re.IGNORECASE):
	SSH.CreateHtmlFooter(SSH.finalStatus)
3375 3376
elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE):
	if re.match('^TesteNB$', mode, re.IGNORECASE):
3377 3378 3379 3380 3381 3382
		if SSH.eNBIPAddress == '' or SSH.eNBRepository == '' or SSH.eNBBranch == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '':
			Usage()
			sys.exit('Insufficient Parameter')
		elif SSH.ADBIPAddress == 'none' and SSH.EPCIPAddress == 'none':
			pass
		elif SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '' or SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '':
3383 3384 3385 3386 3387 3388 3389 3390 3391
			Usage()
			sys.exit('Insufficient Parameter')
		if (SSH.EPCIPAddress != ''):
			SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp")
			SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp")
	else:
		if SSH.UEIPAddress == '' or SSH.eNBRepository == '' or SSH.eNBBranch == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '':
			Usage()
			sys.exit('UE: Insufficient Parameter')
3392

3393
	#read test_case_list.xml file
3394
        # if no parameters for XML file, use default value
3395
	if (SSH.nbTestXMLfiles != 1):
3396
		xml_test_file = cwd + "/test_case_list.xml"
3397
	else:
3398
		xml_test_file = cwd + "/" + SSH.testXMLfiles[0]
3399 3400 3401 3402 3403 3404

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

	exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='')
	requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='')
3405 3406
	if (SSH.nbTestXMLfiles == 1):
		SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0'))
3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438
	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)

	#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:
3439
			#logging.debug('INFO: test will be run: ' + test)
3440
			todo_tests.append(test)
3441

3442
	signal.signal(signal.SIGUSR1, receive_signal)
3443

3444 3445
	SSH.CreateHtmlTabHeader()

3446 3447 3448 3449 3450 3451 3452 3453
	for test_case_id in todo_tests:
		for test in all_tests:
			id = test.get('id')
			if test_case_id != id:
				continue
			SSH.testCase_id = id
			SSH.desc = test.findtext('desc')
			action = test.findtext('class')
3454
			mode = test.findtext('mode')
3455 3456
			if (CheckClassValidity(action, id) == False):
				continue
3457
			SSH.ShowTestID()
3458 3459
			GetParametersFromXML(action)
			if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE':
3460 3461
				terminate_ue_flag = False
				SSH.GetAllUEDevices(terminate_ue_flag)
3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475
			if action == 'Build_eNB':
				SSH.BuildeNB()
			elif action == 'Initialize_eNB':
				SSH.InitializeeNB()
			elif action == 'Terminate_eNB':
				SSH.TerminateeNB()
			elif action == 'Initialize_UE':
				SSH.InitializeUE()
			elif action == 'Terminate_UE':
				SSH.TerminateUE()
			elif action == 'Attach_UE':
				SSH.AttachUE()
			elif action == 'Detach_UE':
				SSH.DetachUE()
3476 3477 3478 3479 3480 3481
			elif action == 'Build_OAI_UE':
				SSH.BuildOAIUE()
			elif action == 'Initialize_OAI_UE':
				SSH.InitializeOAIUE()
			elif action == 'Terminate_OAI_UE':
				SSH.TerminateOAIUE()
Boris Djalal's avatar
WIP.  
Boris Djalal committed
3482 3483
			elif action == 'Initialize_OAI_eNB':
				SSH.InitializeOAIeNB()
3484 3485 3486 3487 3488 3489 3490 3491
			elif action == 'Initialize_CatM_module':
				SSH.InitializeCatM()
			elif action == 'Terminate_CatM_module':
				SSH.TerminateCatM()
			elif action == 'Attach_CatM_module':
				SSH.AttachCatM()
			elif action == 'Detach_CatM_module':
				SSH.TerminateCatM()
3492 3493
			elif action == 'Ping_CatM_module':
				SSH.PingCatM()
3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511
			elif action == 'Ping':
				SSH.Ping()
			elif action == 'Iperf':
				SSH.Iperf()
			elif action == 'Reboot_UE':
				SSH.RebootUE()
			elif action == 'Initialize_HSS':
				SSH.InitializeHSS()
			elif action == 'Terminate_HSS':
				SSH.TerminateHSS()
			elif action == 'Initialize_MME':
				SSH.InitializeMME()
			elif action == 'Terminate_MME':
				SSH.TerminateMME()
			elif action == 'Initialize_SPGW':
				SSH.InitializeSPGW()
			elif action == 'Terminate_SPGW':
				SSH.TerminateSPGW()
3512 3513
			elif action == 'IdleSleep':
				SSH.IdleSleep()
3514 3515
			else:
				sys.exit('Invalid action')
Raphael Defosseux's avatar
Raphael Defosseux committed
3516

3517
	SSH.CreateHtmlTabFooter(True)
3518 3519 3520 3521
else:
	Usage()
	sys.exit('Invalid mode')
sys.exit(0)