From 9afdaf02444106dd8855554a1f9227a3aa84faf9 Mon Sep 17 00:00:00 2001
From: Gabriele Perrone <gabriele.perrone@openairinterface.org>
Date: Wed, 4 Mar 2020 15:13:07 +0100
Subject: [PATCH] pushing for debugging

---
 ci-scripts/constants.py                       |    2 +-
 ci-scripts/epc.py                             |   15 +-
 ci-scripts/html.py                            |  528 ++++++
 ci-scripts/main_enb.py                        | 1588 +++--------------
 ci-scripts/ran.py                             |  376 +++-
 ci-scripts/sshconnection.py                   |    5 +-
 .../enb_usrp210_band13_test_10mhz_tm1.xml     |    2 +-
 .../x2ho_enb_usrp210_band13_simple_test.xml   |  189 ++
 8 files changed, 1355 insertions(+), 1350 deletions(-)
 create mode 100644 ci-scripts/html.py
 create mode 100644 ci-scripts/xml_files/x2ho_enb_usrp210_band13_simple_test.xml

diff --git a/ci-scripts/constants.py b/ci-scripts/constants.py
index f07fd81b43b..65fca7193b0 100644
--- a/ci-scripts/constants.py
+++ b/ci-scripts/constants.py
@@ -56,6 +56,7 @@ OAI_UE_PROCESS_COULD_NOT_SYNC = -21
 OAI_UE_PROCESS_ASSERTION = -22
 OAI_UE_PROCESS_FAILED = -23
 OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24
+OAI_UE_PROCESS_SEG_FAULT = -25
 OAI_UE_PROCESS_OK = +6
 
 UE_STATUS_DETACHED = 0
@@ -68,4 +69,3 @@ X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1
 X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2
 X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3
 X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10
-
diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py
index 91d722a72fd..4f283f530e2 100644
--- a/ci-scripts/epc.py
+++ b/ci-scripts/epc.py
@@ -6,6 +6,8 @@ import re               # reg
 import logging
 import os
 import time
+import signal
+
 from multiprocessing import Process, Lock, SimpleQueue
 
 #-----------------------------------------------------------
@@ -49,23 +51,22 @@ class EPCManagement():
 	def GetType(self):
 		return self.EPCType
 	def Set_PcapFileName(self, pcapfn):
-		self.PcapFileName = pcapfn
+		self.EPC_PcapFileName = pcapfn
 	def Get_PcapFileName(self):
-		return self.PcapFileName
+		return self.EPC_PcapFileName
 
 	def InitializeHSS(self):
 		if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '':
 			HELP.GenericHelp(Version)
 			HELP.EPCSrvHelp(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath, self.EPCType)
 			sys.exit('Insufficient EPC Parameters')
-		#mySSH = SSH() 
 		mySSH = SSH.SSHConnection() 
 		mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
 		if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE):
 			logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS')
 			mySSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5)
 			logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m')
-			EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap'
+			self.EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap'
 			mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + self.EPC_PcapFileName, '\$', 5)
 			mySSH.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5)
 			mySSH.command('echo ' + self.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5)
@@ -85,7 +86,8 @@ class EPCManagement():
 			mySSH.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5)
 			mySSH.command('cd /opt/hss_sim0609', '\$', 5)
 			mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5)
-			mySSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real  ', '\$', 5)
+			#mySSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real  ', '\$', 5)
+			mySSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo su -c "screen -dm -S simulated_hss ./starthss"', '\$', 5)
 		else:
 			logging.error('This option should not occur!')
 		mySSH.close()
@@ -248,7 +250,8 @@ class EPCManagement():
 			mySSH.command('cd scripts', '\$', 5)
 			mySSH.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5)
 			time.sleep(1)
-			mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5)
+			#mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5)
+			mySSH.command('echo ' + self.EPCPassword + ' | sudo killall hss_sim', '\$', 5)
 		else:
 			logging.error('This should not happen!')
 		mySSH.close()
diff --git a/ci-scripts/html.py b/ci-scripts/html.py
new file mode 100644
index 00000000000..80ad46f51ef
--- /dev/null
+++ b/ci-scripts/html.py
@@ -0,0 +1,528 @@
+
+#-----------------------------------------------------------
+# Import
+#-----------------------------------------------------------
+import sys              # arg
+import re               # reg
+import logging
+import os
+import time
+import subprocess
+from multiprocessing import Process, Lock, SimpleQueue
+
+#-----------------------------------------------------------
+# OAI Testing modules
+#-----------------------------------------------------------
+#import main_enb
+#MAIN = main_enb.OaiCiTest()
+
+
+#-----------------------------------------------------------
+# Class Declaration
+#-----------------------------------------------------------
+class HTMLManagement():
+	def __init__(self):
+	#	self.FailReportCnt = 0
+	#	self.prematureExit = False
+		self.ranRepository = ''
+		self.ranBranch = ''
+		self.ranAllowMerge = False
+		self.ranCommitID = ''
+		self.ranTargetBranch = ''
+		#self.eNBIPAddress = ''
+		#self.eNBUserName = ''
+		#self.eNBPassword = ''
+		#self.eNBSourceCodePath = ''
+		#self.eNB1IPAddress = ''
+		#self.eNB1UserName = ''
+		#self.eNB1Password = ''
+		#self.eNB1SourceCodePath = ''
+		#self.eNB2IPAddress = ''
+		#self.eNB2UserName = ''
+		#self.eNB2Password = ''
+		#self.eNB2SourceCodePath = ''
+		#self.ADBIPAddress = ''
+		#self.ADBUserName = ''
+		#self.ADBPassword = ''
+		#self.ADBCentralized = True
+		#self.testCase_id = ''
+		self.testXMLfiles = []
+		self.nbTestXMLfiles = 0
+		#self.desc = ''
+		#self.Build_eNB_args = ''
+		#self.backgroundBuild = False
+		#self.backgroundBuildTestId = ['', '', '']
+		#self.Build_eNB_forced_workspace_cleanup = False
+		#self.Initialize_eNB_args = ''
+		#self.air_interface = 'lte'
+		#self.eNB_instance = ''
+		#self.eNB_serverId = ''
+		#self.eNBLogFiles = ['', '', '']
+		#self.eNBOptions = ['', '', '']
+		#self.eNBmbmsEnables = [False, False, False]
+		#self.eNBstatuses = [-1, -1, -1]
+		#self.ping_args = ''
+		#self.ping_packetloss_threshold = ''
+		#self.iperf_args = ''
+		#self.iperf_packetloss_threshold = ''
+		#self.iperf_profile = ''
+		#self.iperf_options = ''
+		#self.nbMaxUEtoAttach = -1
+		#self.UEDevices = []
+		#self.UEDevicesStatus = []
+		#self.UEDevicesRemoteServer = []
+		#self.UEDevicesRemoteUser = []
+		#self.UEDevicesOffCmd = []
+		#self.UEDevicesOnCmd = []
+		#self.UEDevicesRebootCmd = []
+		#self.CatMDevices = []
+		#self.UEIPAddresses = []
+		self.htmlFile = ''
+		self.htmlHeaderCreated = False
+		self.htmlFooterCreated = False
+		self.htmlUEConnected = -1
+		self.htmlNb_Smartphones = 0
+		self.htmlNb_CATM_Modules = 0
+		self.htmleNBFailureMsg = ''
+		self.htmlUEFailureMsg = ''
+		#self.picocom_closure = False
+		#self.idle_sleep_time = 0
+		#self.x2_ho_options = 'network'
+		#self.x2NbENBs = 0
+		#self.x2ENBBsIds = []
+		#self.x2ENBConnectedUEs = []
+		self.htmlTabRefs = []
+		self.htmlTabNames = []
+		self.htmlTabIcons = []
+		#self.repeatCounts = []
+		#self.finalStatus = False
+		#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.UELogFile = ''
+		#self.Build_OAI_UE_args = ''
+		#self.Initialize_OAI_UE_args = ''
+		#self.clean_repository = True
+		#self.flexranCtrlInstalled = False
+		#self.flexranCtrlStarted = False
+		#self.expectedNbOfConnectedUEs = 0
+		#self.startTime = 0
+
+
+#-----------------------------------------------------------
+# HTML Reporting....
+#-----------------------------------------------------------
+
+	def Setdesc(self, dsc):
+		self.desc = dsc
+
+	def SetstartTime(self, sttime):
+		self.startTime = sttime
+
+	def SettestCase_id(self, tcid):
+		self.testCase_id = tcid
+
+	
+	def SetranRepository(self, repository):
+		self.ranRepository = repository
+	def GetranRepository(self):
+		return self.ranRepository
+
+	def SetranAllowMerge(self, merge):
+		self.ranAllowMerge = merge
+	def GetranAllowMerge(self):
+		return self.ranAllowMerge
+
+
+	def SetranBranch(self, branch):
+		self.ranBranch = branch
+	def GetranBranch(self):
+		return self.ranBranch
+
+	def SetranCommitID(self, commitid):
+		self.ranCommitID = commitid
+	def GetranCommitID(self):
+		return self.ranCommitID
+
+	def SetranTargetBranch(self, tbranch):
+		self.ranTargetBranch = tbranch
+	def GetranTargetBranch(self):
+		return self.ranTargetBranch
+	
+#	def SetADBIPAddress(self, adbip):
+#		self.ADBIPAddress = adbip
+#	def GetADBIPAddress(self):
+#		return self.ADBIPAddress
+
+	def SethtmlUEConnected(self, nbUEs):
+		self.htmlUEConnected = nbUEs
+
+	def SethtmlNb_Smartphones(self, nbUEs):
+		self.htmlNb_Smartphones = nbUEs
+
+	def SethtmlNb_CATM_Modules(self, nbUEs):
+		self.htmlNb_CATM_Modules = nbUEs
+
+	def SetnbTestXMLfiles(self, nb):
+		self.nbTestXMLfiles = nb
+
+	def SettestXMLfiles(self, xmlFile):
+		self.testXMLfiles.append(xmlFile)
+
+	def SethtmlTabRefs(self, tabRef):
+		self.htmlTabRefs.append(tabRef)
+
+	def SethtmlTabNames(self, tabName):
+		self.htmlTabNames.append(tabName)
+
+	def SethtmlTabIcons(self, tabIcon):
+		self.htmlTabIcons.append(tabIcon)
+
+	def CreateHtmlHeader(self, ADBIPAddress):
+		if (not self.htmlHeaderCreated):
+			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
+			logging.debug('\u001B[1m  Creating HTML header \u001B[0m')
+			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
+			self.htmlFile = open('test_results.html', 'w')
+			self.htmlFile.write('<!DOCTYPE html>\n')
+			self.htmlFile.write('<html class="no-js" lang="en-US">\n')
+			self.htmlFile.write('<head>\n')
+			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')
+			self.htmlFile.write('  <title>Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID</title>\n')
+			self.htmlFile.write('</head>\n')
+			self.htmlFile.write('<body><div class="container">\n')
+			self.htmlFile.write('  <br>\n')
+			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')
+			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')
+			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')
+			self.htmlFile.write('  <div class="alert alert-info"><strong> <span class="glyphicon glyphicon-dashboard"></span> TEMPLATE_STAGE_NAME</strong></div>\n')
+			self.htmlFile.write('  <table border = "1">\n')
+			self.htmlFile.write('     <tr>\n')
+			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-time"></span> Build Start Time (UTC) </td>\n')
+			self.htmlFile.write('       <td>TEMPLATE_BUILD_TIME</td>\n')
+			self.htmlFile.write('     </tr>\n')
+			self.htmlFile.write('     <tr>\n')
+			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-cloud-upload"></span> GIT Repository </td>\n')
+			self.htmlFile.write('       <td><a href="' + self.ranRepository + '">' + self.ranRepository + '</a></td>\n')
+			self.htmlFile.write('     </tr>\n')
+			self.htmlFile.write('     <tr>\n')
+			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-wrench"></span> Job Trigger </td>\n')
+			if (self.ranAllowMerge):
+				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')
+			if (self.ranAllowMerge):
+				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-out"></span> Source Branch </td>\n')
+			else:
+				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tree-deciduous"></span> Branch</td>\n')
+			self.htmlFile.write('       <td>' + self.ranBranch + '</td>\n')
+			self.htmlFile.write('     </tr>\n')
+			self.htmlFile.write('     <tr>\n')
+			if (self.ranAllowMerge):
+				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Source Commit ID </td>\n')
+			else:
+				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Commit ID </td>\n')
+			self.htmlFile.write('       <td>' + self.ranCommitID + '</td>\n')
+			self.htmlFile.write('     </tr>\n')
+			if self.ranAllowMerge != '':
+				commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True)
+				commit_message = commit_message.strip()
+				self.htmlFile.write('     <tr>\n')
+				if (self.ranAllowMerge):
+					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.ranAllowMerge):
+				self.htmlFile.write('     <tr>\n')
+				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-in"></span> Target Branch </td>\n')
+				if (self.ranTargetBranch == ''):
+					self.htmlFile.write('       <td>develop</td>\n')
+				else:
+					self.htmlFile.write('       <td>' + self.ranTargetBranch + '</td>\n')
+				self.htmlFile.write('     </tr>\n')
+			self.htmlFile.write('  </table>\n')
+
+			if (ADBIPAddress != 'none'):
+				#terminate_ue_flag = True
+				#MAIN.GetAllUEDevices(terminate_ue_flag)
+				#self.GetAllCatMDevices(terminate_ue_flag)
+				#self.htmlUEConnected = len(self.UEDevices)
+				self.htmlFile.write('  <h2><span class="glyphicon glyphicon-phone"></span> <span class="glyphicon glyphicon-menu-right"></span> ' + str(self.htmlNb_Smartphones) + ' 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(self.htmlNb_CATM_Modules) + ' CAT-M UE(s) is(are) connected to bench server</h2>\n')
+			else:
+				#self.UEDevices.append('OAI-UE')
+				#self.htmlUEConnected = len(self.UEDevices)
+				self.htmlUEConnected = 1
+				self.htmlFile.write('  <h2><span class="glyphicon glyphicon-phone"></span> <span class="glyphicon glyphicon-menu-right"></span> 1 OAI UE(s) is(are) connected to CI bench</h2>\n')
+			self.htmlFile.write('  <br>\n')
+			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 += '__STATE_' + self.htmlTabNames[count] + '__'
+				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()
+
+	def CreateHtmlTabHeader(self):
+		if (not self.htmlHeaderCreated):
+			if (not os.path.isfile('test_results.html')):
+				self.CreateHtmlHeader('none')
+			self.htmlFile = open('test_results.html', 'a')
+			if (self.nbTestXMLfiles == 1):
+				self.htmlFile.write('  <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')
+			self.htmlFile.write('      <tr bgcolor = "#33CCFF" >\n')
+			self.htmlFile.write('        <th>Relative Time (ms)</th>\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')
+			#if (self.htmlUEConnected == -1):
+			#	terminate_ue_flag = True
+			#	if (self.ADBIPAddress != 'none'):
+			#		self.GetAllUEDevices(terminate_ue_flag)
+			#		self.GetAllCatMDevices(terminate_ue_flag)
+			#	else:
+			#		self.UEDevices.append('OAI-UE')
+			#	self.htmlUEConnected = len(self.UEDevices)
+
+			i = 0
+			while (i < self.htmlUEConnected):
+				self.htmlFile.write('        <th>UE' + str(i) + ' Status</th>\n')
+				i += 1
+			self.htmlFile.write('      </tr>\n')
+			self.htmlFile.close()
+		self.htmlHeaderCreated = True
+
+	def CreateHtmlTabFooter(self, passStatus):
+		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
+			self.htmlFile = open('test_results.html', 'a')
+			self.htmlFile.write('      <tr>\n')
+			self.htmlFile.write('        <th bgcolor = "#33CCFF" colspan=3>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.htmlFile.close()
+			time.sleep(1)
+			if passStatus:
+				cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html"
+				subprocess.run(cmd, shell=True)
+			else:
+				cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<span class=\"glyphicon glyphicon-remove\"><\/span>/' test_results.html"
+				subprocess.run(cmd, shell=True)
+		self.htmlFooterCreated = False
+
+	def CreateHtmlFooter(self, passStatus):
+		if (os.path.isfile('test_results.html')):
+			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
+			logging.debug('\u001B[1m  Creating HTML footer \u001B[0m')
+			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
+
+			self.htmlFile = open('test_results.html', 'a')
+			self.htmlFile.write('</div>\n')
+			self.htmlFile.write('  <p></p>\n')
+			self.htmlFile.write('  <table class="table table-condensed">\n')
+
+			machines = [ 'eNB', 'UE' ]
+			for machine in machines:
+				#This needs to move back to main and be called before CreateHtmlFooter
+				res = self.RetrieveSystemVersion(machine)
+				if res == -1:
+					continue
+				self.htmlFile.write('      <tr>\n')
+				self.htmlFile.write('        <th colspan=8>' + str(machine) + ' Server Characteristics</th>\n')
+				self.htmlFile.write('      </tr>\n')
+				self.htmlFile.write('      <tr>\n')
+				self.htmlFile.write('        <td>OS Version</td>\n')
+				self.htmlFile.write('        <td><span class="label label-default">' + self.OsVersion + '</span></td>\n')
+				self.htmlFile.write('        <td>Kernel Version</td>\n')
+				self.htmlFile.write('        <td><span class="label label-default">' + self.KernelVersion + '</span></td>\n')
+				self.htmlFile.write('        <td>UHD Version</td>\n')
+				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')
+				self.htmlFile.write('      </tr>\n')
+				self.htmlFile.write('      <tr>\n')
+				self.htmlFile.write('        <td>Nb CPUs</td>\n')
+				self.htmlFile.write('        <td><span class="label label-default">' + self.CpuNb + '</span></td>\n')
+				self.htmlFile.write('        <td>CPU Model Name</td>\n')
+				self.htmlFile.write('        <td><span class="label label-default">' + self.CpuModel + '</span></td>\n')
+				self.htmlFile.write('        <td>CPU Frequency</td>\n')
+				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')
+				self.htmlFile.write('      </tr>\n')
+
+			self.htmlFile.write('      <tr>\n')
+			self.htmlFile.write('        <th colspan=5 bgcolor = "#33CCFF">Final Status</th>\n')
+			if passStatus:
+				self.htmlFile.write('        <th colspan=3 bgcolor="green"><font color="white">PASS <span class="glyphicon glyphicon-ok"></span></font></th>\n')
+			else:
+				self.htmlFile.write('        <th colspan=3 bgcolor="red"><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('  <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')
+			self.htmlFile.write('</html>\n')
+			self.htmlFile.close()
+
+	#FailReportCnt should be passed as a parameter of CreateHtmlRetrySeparator method 
+	# no need for a setter and be a member of html class 
+	def CreateHtmlRetrySeparator(self, cntnumfails):
+		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
+			self.htmlFile = open('test_results.html', 'a')
+			self.htmlFile.write('      <tr bgcolor = "#33CCFF" >\n')
+			self.htmlFile.write('        <td colspan=' + str(5+self.htmlUEConnected) + '>Try Run #' + str(cntnumfails) + '</td>\n')
+			self.htmlFile.write('      </tr>\n')
+			self.htmlFile.close()
+
+	def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'):
+		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
+			self.htmlFile = open('test_results.html', 'a')
+			currentTime = int(round(time.time() * 1000)) - self.startTime
+			self.htmlFile.write('      <tr>\n')
+			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + format(currentTime / 1000, '.1f') + '</td>\n')
+			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + self.testCase_id  + '</td>\n')
+			self.htmlFile.write('        <td>' + self.desc  + '</td>\n')
+			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'):
+				if (processesStatus == 0):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >' + str(status)  + '</td>\n')
+				elif (processesStatus == ENB_PROCESS_FAILED):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - eNB process not found</td>\n')
+				elif (processesStatus == OAI_UE_PROCESS_FAILED):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - OAI UE process not found</td>\n')
+				elif (processesStatus == ENB_PROCESS_SEG_FAULT) or (processesStatus == OAI_UE_PROCESS_SEG_FAULT):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process ended in Segmentation Fault</td>\n')
+				elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process ended in Assertion</td>\n')
+				elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE):
+					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 == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE):
+					self.htmlFile.write('        <td bgcolor = "orange" >OK?</td>\n')
+				elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' Slave RRU could not synch</td>\n')
+				elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - UE could not sync</td>\n')
+				elif (processesStatus == HSS_PROCESS_FAILED):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - HSS process not found</td>\n')
+				elif (processesStatus == MME_PROCESS_FAILED):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - MME process not found</td>\n')
+				elif (processesStatus == SPGW_PROCESS_FAILED):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - SPGW process not found</td>\n')
+				elif (processesStatus == UE_IP_ADDRESS_ISSUE):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - Could not retrieve UE IP address</td>\n')
+				else:
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >' + str(status)  + '</td>\n')
+			else:
+				self.htmlFile.write('        <td bgcolor = "orange" >' + str(status)  + '</td>\n')
+			if (len(str(self.htmleNBFailureMsg)) > 2):
+				cellBgColor = 'white'
+				result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg)
+				if result is not None:
+					cellBgColor = 'red'
+				else:
+					result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg)
+					if result is not None:
+						cellBgColor = 'orange'
+				self.htmlFile.write('        <td bgcolor = "' + cellBgColor + '" colspan=' + str(self.htmlUEConnected) + '><pre style="background-color:' + cellBgColor + '">' + self.htmleNBFailureMsg + '</pre></td>\n')
+				self.htmleNBFailureMsg = ''
+			elif (len(str(self.htmlUEFailureMsg)) > 2):
+				cellBgColor = 'white'
+				result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg)
+				if result is not None:
+					cellBgColor = 'red'
+				else:
+					result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg)
+					if result is not None:
+						cellBgColor = 'orange'
+				self.htmlFile.write('        <td bgcolor = "' + cellBgColor + '" colspan=' + str(self.htmlUEConnected) + '><pre style="background-color:' + cellBgColor + '">' + self.htmlUEFailureMsg + '</pre></td>\n')
+				self.htmlUEFailureMsg = ''
+			else:
+				i = 0
+				while (i < self.htmlUEConnected):
+					self.htmlFile.write('        <td>-</td>\n')
+					i += 1
+			self.htmlFile.write('      </tr>\n')
+			self.htmlFile.close()
+
+	def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue):
+		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
+			self.htmlFile = open('test_results.html', 'a')
+			currentTime = int(round(time.time() * 1000)) - self.startTime
+			addOrangeBK = False
+			self.htmlFile.write('      <tr>\n')
+			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + format(currentTime / 1000, '.1f') + '</td>\n')
+			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + self.testCase_id  + '</td>\n')
+			self.htmlFile.write('        <td>' + self.desc  + '</td>\n')
+			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:
+				addOrangeBK = True
+				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()):
+						if (addOrangeBK):
+							self.htmlFile.write('        <td bgcolor = "orange" >' + str(ue_queue.get()).replace('white', 'orange') + '</td>\n')
+						else:
+							self.htmlFile.write('        <td>' + str(ue_queue.get()) + '</td>\n')
+					else:
+						self.htmlFile.write('        <td>-</td>\n')
+				else:
+					self.htmlFile.write('        <td>-</td>\n')
+				i += 1
+			self.htmlFile.write('      </tr>\n')
+			self.htmlFile.close()
+
+
diff --git a/ci-scripts/main_enb.py b/ci-scripts/main_enb.py
index e8c530a70bb..340aaed9b35 100644
--- a/ci-scripts/main_enb.py
+++ b/ci-scripts/main_enb.py
@@ -28,6 +28,8 @@
 #     pexpect
 #---------------------------------------------------------------------
 
+import constants as CONST
+
 #-----------------------------------------------------------
 # Version
 #-----------------------------------------------------------
@@ -36,39 +38,39 @@ Version = '0.1'
 #-----------------------------------------------------------
 # 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
-ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14
-ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = -15
-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
-OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20
-OAI_UE_PROCESS_COULD_NOT_SYNC = -21
-OAI_UE_PROCESS_ASSERTION = -22
-OAI_UE_PROCESS_FAILED = -23
-OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24
-OAI_UE_PROCESS_SEG_FAULT = -25
-OAI_UE_PROCESS_OK = +6
-
-UE_STATUS_DETACHED = 0
-UE_STATUS_DETACHING = 1
-UE_STATUS_ATTACHING = 2
-UE_STATUS_ATTACHED = 3
-
-X2_HO_REQ_STATE__IDLE = 0
-X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1
-X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2
-X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3
-X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10
+ALL_PROCESSES_OK = CONST.ALL_PROCESSES_OK
+ENB_PROCESS_FAILED = CONST.ENB_PROCESS_FAILED
+ENB_PROCESS_OK = CONST.ENB_PROCESS_OK
+ENB_PROCESS_SEG_FAULT = CONST.ENB_PROCESS_SEG_FAULT
+ENB_PROCESS_ASSERTION = CONST.ENB_PROCESS_ASSERTION
+ENB_PROCESS_REALTIME_ISSUE = CONST.ENB_PROCESS_REALTIME_ISSUE
+ENB_PROCESS_NOLOGFILE_TO_ANALYZE = CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE
+ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED
+HSS_PROCESS_FAILED = CONST.HSS_PROCESS_FAILED
+HSS_PROCESS_OK = CONST.HSS_PROCESS_OK
+MME_PROCESS_FAILED = CONST.MME_PROCESS_FAILED
+MME_PROCESS_OK = CONST.MME_PROCESS_OK
+SPGW_PROCESS_FAILED = CONST.SPGW_PROCESS_FAILED
+SPGW_PROCESS_OK = CONST.SPGW_PROCESS_OK
+UE_IP_ADDRESS_ISSUE = CONST.UE_IP_ADDRESS_ISSUE
+OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE
+OAI_UE_PROCESS_COULD_NOT_SYNC = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC
+OAI_UE_PROCESS_ASSERTION = CONST.OAI_UE_PROCESS_ASSERTION
+OAI_UE_PROCESS_FAILED = CONST.OAI_UE_PROCESS_FAILED
+OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE
+OAI_UE_PROCESS_SEG_FAULT = CONST.OAI_UE_PROCESS_SEG_FAULT
+OAI_UE_PROCESS_OK = CONST.OAI_UE_PROCESS_OK
+
+UE_STATUS_DETACHED = CONST.UE_STATUS_DETACHED
+UE_STATUS_DETACHING = CONST.UE_STATUS_DETACHING
+UE_STATUS_ATTACHING = CONST.UE_STATUS_ATTACHING
+UE_STATUS_ATTACHED = CONST.UE_STATUS_ATTACHED
+
+X2_HO_REQ_STATE__IDLE = CONST.X2_HO_REQ_STATE__IDLE
+X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = CONST.X2_HO_REQ_STATE__TARGET_RECEIVES_REQ
+X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = CONST.X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE
+X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = CONST.X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ
+X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = CONST.X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK
 
 #-----------------------------------------------------------
 # Import
@@ -167,9 +169,9 @@ class OaiCiTest():
 		self.x2NbENBs = 0
 		self.x2ENBBsIds = []
 		self.x2ENBConnectedUEs = []
-		self.htmlTabRefs = []
-		self.htmlTabNames = []
-		self.htmlTabIcons = []
+		#self.htmlTabRefs = []
+		#self.htmlTabNames = []
+		#self.htmlTabIcons = []
 		self.repeatCounts = []
 		self.finalStatus = False
 		self.OsVersion = ''
@@ -192,198 +194,8 @@ class OaiCiTest():
 		self.flexranCtrlStarted = False
 		self.expectedNbOfConnectedUEs = 0
 		self.startTime = 0
-'''
-	def BuildeNB(self):
-		if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
-			GenericHelp(Version)
-			sys.exit('Insufficient Parameter')
-		if self.eNB_serverId == '0':
-			lIpAddr = self.eNBIPAddress
-			lUserName = self.eNBUserName
-			lPassWord = self.eNBPassword
-			lSourcePath = RAN.GeteNBSourceCodePath()
-		elif self.eNB_serverId == '1':
-			lIpAddr = self.eNB1IPAddress
-			lUserName = self.eNB1UserName
-			lPassWord = self.eNB1Password
-			lSourcePath = self.eNB1SourceCodePath
-		elif self.eNB_serverId == '2':
-			lIpAddr = self.eNB2IPAddress
-			lUserName = self.eNB2UserName
-			lPassWord = self.eNB2Password
-			lSourcePath = self.eNB2SourceCodePath
-		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
-			GenericHelp(Version)
-			sys.exit('Insufficient Parameter')
-		SSH.open(lIpAddr, lUserName, lPassWord)
-		# Check if we build an 5G-NR gNB or an LTE eNB
-		result = re.search('--gNB', RAN.GetBuild_eNB_args())
-		if result is not None:
-			self.air_interface = 'nr'
-		else:
-			self.air_interface = 'lte'
-		# Worakround for some servers, we need to erase completely the workspace
-		if self.Build_eNB_forced_workspace_cleanup:
-			SSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15)
-		# on RedHat/CentOS .git extension is mandatory
-		result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository)
-		if result is not None:
-			full_ran_repo_name = self.ranRepository
-		else:
-			full_ran_repo_name = self.ranRepository + '.git'
-		SSH.command('mkdir -p ' + lSourcePath, '\$', 5)
-		SSH.command('cd ' + lSourcePath, '\$', 5)
-		SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600)
-		# Raphael: here add a check if git clone or git fetch went smoothly
-		SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5)
-		SSH.command('git config user.name "OAI Jenkins"', '\$', 5)
-		# Checking the BUILD INFO file
-		if not self.backgroundBuild:
-			SSH.command('ls *.txt', '\$', 5)
-			result = re.search('LAST_BUILD_INFO', SSH.getBefore())
-			if result is not None:
-				mismatch = False
-				SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2)
-				result = re.search(self.ranCommitID, SSH.getBefore())
-				if result is None:
-					mismatch = True
-				SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2)
-				if (RAN.GetranAllowMerge()):
-					result = re.search('YES', SSH.getBefore())
-					if result is None:
-						mismatch = True
-					SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2)
-					if RAN.GetranTargetBranch() == '':
-						result = re.search('develop', SSH.getBefore())
-					else:
-						result = re.search(RAN.GetranTargetBranch(), SSH.getBefore())
-					if result is None:
-						mismatch = True
-				else:
-					result = re.search('NO', SSH.getBefore())
-					if result is None:
-						mismatch = True
-				if not mismatch:
-					SSH.close()
-					self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK)
-					return
 
-		SSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30)
-		# if the commit ID is provided use it to point to it
-		if self.ranCommitID != '':
-			SSH.command('git checkout -f ' + self.ranCommitID, '\$', 5)
-		# if the branch is not develop, then it is a merge request and we need to do 
-		# the potential merge. Note that merge conflicts should already been checked earlier
-		if (RAN.GetranAllowMerge()):
-			if RAN.GetranTargetBranch() == '':
-				if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'):
-					SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5)
-			else:
-				logging.debug('Merging with the target branch: ' + RAN.GetranTargetBranch())
-				SSH.command('git merge --ff origin/' + RAN.GetranTargetBranch() + ' -m "Temporary merge for CI"', '\$', 5)
-		SSH.command('source oaienv', '\$', 5)
-		SSH.command('cd cmake_targets', '\$', 5)
-		SSH.command('mkdir -p log', '\$', 5)
-		SSH.command('chmod 777 log', '\$', 5)
-		# no need to remove in log (git clean did the trick)
-		if self.backgroundBuild:
-			SSH.command('echo "./build_oai ' + RAN.GetBuild_eNB_args() + '" > ./my-lte-softmodem-build.sh', '\$', 5)
-			SSH.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5)
-			SSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5)
-			SSH.close()
-			self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK)
-			self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id
-			return
-		SSH.command('stdbuf -o0 ./build_oai ' + RAN.GetBuild_eNB_args() + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500)
-		self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id)
-
-	def WaitBuildeNBisFinished(self):
-		if self.eNB_serverId == '0':
-			lIpAddr = self.eNBIPAddress
-			lUserName = self.eNBUserName
-			lPassWord = self.eNBPassword
-			lSourcePath = RAN.GeteNBSourceCodePath()
-		elif self.eNB_serverId == '1':
-			lIpAddr = self.eNB1IPAddress
-			lUserName = self.eNB1UserName
-			lPassWord = self.eNB1Password
-			lSourcePath = self.eNB1SourceCodePath
-		elif self.eNB_serverId == '2':
-			lIpAddr = self.eNB2IPAddress
-			lUserName = self.eNB2UserName
-			lPassWord = self.eNB2Password
-			lSourcePath = self.eNB2SourceCodePath
-		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
-			GenericHelp(Version)
-			sys.exit('Insufficient Parameter')
-		SSH.open(lIpAddr, lUserName, lPassWord)
-		count = 40
-		buildOAIprocess = True
-		while (count > 0) and buildOAIprocess:
-			SSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3)
-			result = re.search('build_oai', SSH.getBefore())
-			if result is None:
-				buildOAIprocess = False
-			else:
-				count -= 1
-				time.sleep(30)
-		self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)])
 
-	def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId):
-		SSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3)
-		SSH.command('ls ran_build/build', '\$', 3)
-		SSH.command('ls ran_build/build', '\$', 3)
-		if self.air_interface == 'nr':
-			nodeB_prefix = 'g'
-		else:
-			nodeB_prefix = 'e'
-		buildStatus = True
-		result = re.search(self.air_interface + '-softmodem', SSH.getBefore())
-		if result is None:
-			buildStatus = False
-		else:
-			# Generating a BUILD INFO file
-			SSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2)
-			SSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2)
-			if (RAN.GetranAllowMerge()):
-				SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2)
-				if RAN.GetranTargetBranch() == '':
-					SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2)
-				else:
-					SSH.command('echo "TGT_BRANCH: ' + RAN.GetranTargetBranch() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2)
-			else:
-				SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2)
-		SSH.command('mkdir -p build_log_' + testcaseId, '\$', 5)
-		SSH.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5)
-		SSH.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5)
-		if self.eNB_serverId != '0':
-			SSH.command('cd cmake_targets', '\$', 5)
-			SSH.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5)
-			SSH.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5)
-			SSH.close()
-			if (os.path.isfile('./tmp_build' + testcaseId + '.zip')):
-				os.remove('./tmp_build' + testcaseId + '.zip')
-			SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.')
-			if (os.path.isfile('./tmp_build' + testcaseId + '.zip')):
-				SSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', RAN.GeteNBSourceCodePath() + '/cmake_targets/.')
-				os.remove('./tmp_build' + testcaseId + '.zip')
-				SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
-				SSH.command('cd ' + RAN.GeteNBSourceCodePath() + '/cmake_targets', '\$', 5)
-				SSH.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5)
-				SSH.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5)
-				SSH.close()
-		else:
-			SSH.close()
-
-		if buildStatus:
-			logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m')
-			self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK)
-		else:
-			logging.error('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Failed\u001B[0m')
-			self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'KO', ALL_PROCESSES_OK)
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
-'''
 	def BuildOAIUE(self):
 		if self.UEIPAddress == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '':
 			GenericHelp(Version)
@@ -391,10 +203,10 @@ class OaiCiTest():
 		SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
 		result = re.search('--nrUE', self.Build_OAI_UE_args)
 		if result is not None:
-			RAN.Setair_interface() = 'nr'
+			RAN.Setair_interface('nr')
 			ue_prefix = 'NR '
 		else:
-			RAN.Setair_interface() = 'lte'
+			RAN.Setair_interface('lte')
 			ue_prefix = ''
 		result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', RAN.GetranRepository())
 		if result is not None:
@@ -434,7 +246,7 @@ class OaiCiTest():
 						mismatch = True
 				if not mismatch:
 					SSH.close()
-					self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK)
+					HTML.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK)
 					return
 
 			SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30)
@@ -470,7 +282,7 @@ class OaiCiTest():
 			# Generating a BUILD INFO file
 			SSH.command('echo "SRC_BRANCH: ' + RAN.GetranBranch() + '" > ../LAST_BUILD_INFO.txt', '\$', 2)
 			SSH.command('echo "SRC_COMMIT: ' + RAN.GetranCommitID() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2)
-			if (RAN.GetranAllowMerge):
+			if (RAN.GetranAllowMerge()):
 				SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2)
 				if RAN.GetranTargetBranch() == '':
 					SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2)
@@ -479,12 +291,12 @@ class OaiCiTest():
 			else:
 				SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2)
 			SSH.close()
-			self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE')
+			HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE')
 		else:
 			SSH.close()
 			logging.error('\u001B[1m Building OAI UE Failed\u001B[0m')
-			self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE')
-			self.CreateHtmlTabFooter(False)
+			HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE')
+			HTML.CreateHtmlTabFooter(False)
 			sys.exit(1)
 	
 	def CheckFlexranCtrlInstallation(self):
@@ -495,6 +307,7 @@ class OaiCiTest():
 		result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore())
 		if result is not None:
 			self.flexranCtrlInstalled = True
+			RAN.SetflexranCtrlInstalled(True)
 			logging.debug('Flexran Controller is installed')
 		SSH.close()
 
@@ -515,187 +328,10 @@ class OaiCiTest():
 		if result is not None:
 			logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m')
 			self.flexranCtrlStarted = True
+			RAN.SetflexranCtrlStarted(True)
 		SSH.close()
-		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
-'''
-	def InitializeeNB(self):
-		if self.eNB_serverId == '0':
-			lIpAddr = self.eNBIPAddress
-			lUserName = self.eNBUserName
-			lPassWord = self.eNBPassword
-			lSourcePath = RAN.GeteNBSourceCodePath()
-		elif self.eNB_serverId == '1':
-			lIpAddr = self.eNB1IPAddress
-			lUserName = self.eNB1UserName
-			lPassWord = self.eNB1Password
-			lSourcePath = self.eNB1SourceCodePath
-		elif self.eNB_serverId == '2':
-			lIpAddr = self.eNB2IPAddress
-			lUserName = self.eNB2UserName
-			lPassWord = self.eNB2Password
-			lSourcePath = self.eNB2SourceCodePath
-		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
-			GenericHelp(Version)
-			sys.exit('Insufficient Parameter')
-		check_eNB = False
-		check_OAI_UE = False
-		pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
-		if (pStatus < 0):
-			self.CreateHtmlTestRow(RAN.GetInitialize_eNB_args(), 'KO', pStatus)
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
-		# If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB
-		result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args()))
-		if result is not None:
-			SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword())
-			SSH.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', SSH.getBefore())
-			if result is not None:
-				eth_interface = result.group('eth_interface')
-				logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m')
-				EPC.EPC_PcapFileName  = 'enb_' + self.testCase_id + '_s1log.pcap'
-				SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f /tmp/' + EPC.EPC_PcapFileName , '\$', 5)
-				SSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.EPC_PcapFileName  + ' > /tmp/tshark.log 2>&1 &', EPC.GetUserName(), 5)
-			SSH.close()
-		SSH.open(lIpAddr, lUserName, lPassWord)
-		SSH.command('cd ' + lSourcePath, '\$', 5)
-		# Initialize_eNB_args usually start with -O and followed by the location in repository
-		full_config_file = RAN.GetInitialize_eNB_args().replace('-O ','')
-		extra_options = ''
-		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')
-				SSH.command('cd common/utils/T/tracer', '\$', 5)
-				SSH.command('make', '\$', 10)
-				SSH.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5)
-				SSH.command('cd ' + lSourcePath, '\$', 5)
-			full_config_file = full_config_file[:extIdx + 5]
-			config_path, config_file = os.path.split(full_config_file)
-		else:
-			sys.exit('Insufficient Parameter')
-		ci_full_config_file = config_path + '/ci-' + config_file
-		rruCheck = False
-		result = re.search('^rru|^rcc|^du.band', str(config_file))
-		if result is not None:
-			rruCheck = True
-		# do not reset board twice in IF4.5 case
-		result = re.search('^rru|^enb|^du.band', str(config_file))
-		if result is not None:
-			SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60)
-			result = re.search('type: b200', SSH.getBefore())
-			if result is not None:
-				logging.debug('Found a B2xx device --> resetting it')
-				SSH.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10)
-				# Reloading FGPA bin firmware
-				SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60)
-		# Make a copy and adapt to EPC / eNB IP addresses
-		SSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5)
-		SSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + EPC.GetIPAddress() + '/\' ' + ci_full_config_file, '\$', 2);
-		SSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2);
-		SSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2);
-		SSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2);
-		SSH.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2);
-		if self.flexranCtrlInstalled and self.flexranCtrlStarted:
-			SSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED        = "yes";/\' ' + ci_full_config_file, '\$', 2);
-		else:
-			SSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED        = "no";/\' ' + ci_full_config_file, '\$', 2);
-		self.eNBmbmsEnables[int(self.eNB_instance)] = False
-		SSH.command('grep enable_enb_m2 ' + ci_full_config_file, '\$', 2);
-		result = re.search('yes', SSH.getBefore())
-		if result is not None:
-			self.eNBmbmsEnables[int(self.eNB_instance)] = True
-			logging.debug('\u001B[1m MBMS is enabled on this eNB\u001B[0m')
-		result = re.search('noS1', str(RAN.GetInitialize_eNB_args()))
-		eNBinNoS1 = False
-		if result is not None:
-			eNBinNoS1 = True
-			logging.debug('\u001B[1m eNB is in noS1 configuration \u001B[0m')
-		# Launch eNB with the modified config file
-		SSH.command('source oaienv', '\$', 5)
-		SSH.command('cd cmake_targets', '\$', 5)
-		SSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface + '-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
-		SSH.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
-		SSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5)
-		SSH.command('hostnamectl','\$', 5)
-		result = re.search('CentOS Linux 7', SSH.getBefore())
-		if result is not None:
-			SSH.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10)
-		else:
-			SSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
-		self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log'
-		if extra_options != '':
-			self.eNBOptions[int(self.eNB_instance)] = extra_options
-		time.sleep(6)
-		doLoop = True
-		loopCounter = 20
-		enbDidSync = False
-		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(RAN.GetInitialize_eNB_args()))
-				if result is not None:
-					SSH.command('killall --signal SIGKILL record', '\$', 5)
-				SSH.close()
-				doLoop = False
-				logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m')
-				self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK)
-				# In case of T tracer recording, we need to kill tshark on EPC side
-				result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args()))
-				if result is not None:
-					SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword())
-					logging.debug('\u001B[1m Stopping tshark \u001B[0m')
-					SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5)
-					if EPC.EPC_PcapFileName  != '':
-						time.sleep(0.5)
-						SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5)
-					SSH.close()
-					time.sleep(1)
-					if EPC.EPC_PcapFileName  != '':
-						copyin_res = SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.EPC_PcapFileName , '.')
-						if (copyin_res == 0):
-							SSH.copyout(lIpAddr, lUserName, lPassWord, EPC.EPC_PcapFileName , lSourcePath + '/cmake_targets/.')
-				self.prematureExit = True
-				return
-			else:
-				SSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4)
-				if rruCheck:
-					result = re.search('wait RUs', SSH.getBefore())
-				else:
-					result = re.search('got sync|Starting F1AP at CU', SSH.getBefore())
-				if result is None:
-					time.sleep(6)
-				else:
-					doLoop = False
-					enbDidSync = True
-					time.sleep(10)
-
-		if enbDidSync and eNBinNoS1:
-			SSH.command('ifconfig oaitun_enb1', '\$', 4)
-			SSH.command('ifconfig oaitun_enb1', '\$', 4)
-			result = re.search('inet addr:1|inet 1', SSH.getBefore())
-			if result is not None:
-				logging.debug('\u001B[1m oaitun_enb1 interface is mounted and configured\u001B[0m')
-			else:
-				logging.error('\u001B[1m oaitun_enb1 interface is either NOT mounted or NOT configured\u001B[0m')
-			if self.eNBmbmsEnables[int(self.eNB_instance)]:
-				SSH.command('ifconfig oaitun_enm1', '\$', 4)
-				result = re.search('inet addr', SSH.getBefore())
-				if result is not None:
-					logging.debug('\u001B[1m oaitun_enm1 interface is mounted and configured\u001B[0m')
-				else:
-					logging.error('\u001B[1m oaitun_enm1 interface is either NOT mounted or NOT configured\u001B[0m')
-		if enbDidSync:
-			self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId)
-
-		SSH.close()
-		self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK)
-		logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m')
-'''
+		HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+	
 	def InitializeUE_common(self, device_id, idx):
 		try:
 			SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
@@ -757,7 +393,7 @@ class OaiCiTest():
 			i += 1
 		for job in multi_jobs:
 			job.join()
-		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+		HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 
 	def InitializeOAIUE(self):
 		if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '':
@@ -770,8 +406,8 @@ class OaiCiTest():
 				check_OAI_UE = False
 				pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
 				if (pStatus < 0):
-					self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus)
-					self.CreateHtmlTabFooter(False)
+					HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus)
+					HTML.CreateHtmlTabFooter(False)
 					sys.exit(1)
 			UE_prefix = ''
 		else:
@@ -915,7 +551,7 @@ class OaiCiTest():
 
 		SSH.close()
 		if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus:
-			self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE')
+			HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE')
 			logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m')
 			if (self.ADBIPAddress != 'none'):
 				self.UEDevices = []
@@ -928,10 +564,10 @@ class OaiCiTest():
 					self.htmlUEFailureMsg = 'oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured'
 				else:
 					self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured'
-				self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE')
+				HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE')
 			else:
 				self.htmlUEFailureMsg = 'nr-uesoftmodem did NOT synced'
-				self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE')
+				HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE')
 			logging.error('\033[91mInitialize OAI UE Failed! \033[0m')
 			self.AutoTerminateUEandeNB()
 
@@ -961,11 +597,11 @@ class OaiCiTest():
 		# Calling twice AT to clear all buffers
 		SSH.command('AT', 'OK|ERROR', 5)
 		SSH.command('AT', 'OK', 5)
-                # Doing a power cycle
-                self.command('AT^RESET', 'SIMSTORE,READY', 15)
-                self.command('AT', 'OK|ERROR', 5)
-                self.command('AT', 'OK', 5)
-                self.command('ATE1', 'OK', 5)
+		# Doing a power cycle
+		self.command('AT^RESET', 'SIMSTORE,READY', 15)
+		self.command('AT', 'OK|ERROR', 5)
+		self.command('AT', 'OK', 5)
+		self.command('ATE1', 'OK', 5)
 		# Disabling the Radio
 		SSH.command('AT+CFUN=0', 'OK', 5)
 		logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m')
@@ -984,7 +620,7 @@ class OaiCiTest():
 		# Force closure of picocom but device might still be locked
 		SSH.close()
 		self.picocom_closure = False
-		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+		HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 		self.checkDevTTYisUnlocked()
 
 	def TerminateCatM(self):
@@ -1005,7 +641,7 @@ class OaiCiTest():
 		logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m')
 		SSH.close()
 		self.picocom_closure = False
-		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+		HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 		self.checkDevTTYisUnlocked()
 
 	def AttachCatM(self):
@@ -1074,12 +710,12 @@ class OaiCiTest():
 			else:
 				html_cell += '</pre>'
 			html_queue.put(html_cell)
-			self.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue)
+			HTML.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue)
 		else:
 			logging.error('\u001B[1m CAT-M module Attachment Failed\u001B[0m')
 			html_cell = '<pre style="background-color:white">CAT-M module Attachment Failed</pre>'
 			html_queue.put(html_cell)
-			self.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue)
+			HTML.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue)
 			self.AutoTerminateUEandeNB()
 
 	def PingCatM(self):
@@ -1090,7 +726,7 @@ class OaiCiTest():
 		check_OAI_UE = False
 		pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
 		if (pStatus < 0):
-			self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
+			HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
 			return
 		try:
@@ -1101,8 +737,8 @@ class OaiCiTest():
 			SSH.command('cd scripts', '\$', 5)
 			if re.match('OAI', EPC.GetType(), re.IGNORECASE):
 				logging.debug('Using the OAI EPC HSS: not implemented yet')
-				self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
-				self.CreateHtmlTabFooter(False)
+				HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
+				HTML.CreateHtmlTabFooter(False)
 				sys.exit(1)
 			else:
 				SSH.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5)
@@ -1110,7 +746,7 @@ class OaiCiTest():
 				if result is not None:
 					moduleIPAddr = result.group('ipaddr')
 				else:
-					self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
+					HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
 					self.AutoTerminateUEandeNB()
 					return
 			ping_time = re.findall("-c (\d+)",str(self.ping_args))
@@ -1172,9 +808,9 @@ class OaiCiTest():
 			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)
+				HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue)
 			else:
-				self.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue)
+				HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue)
 				self.AutoTerminateUEandeNB()
 		except:
 			os.kill(os.getppid(),signal.SIGUSR1)
@@ -1198,6 +834,7 @@ class OaiCiTest():
 					SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15)
 				else:
 					SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60)
+				print('#GP: in SSH.getBefore() K=0 (it was K=2 in main.py)')
 				result = re.search('mDataConnectionState.*=(?P<state>[0-9\-]+)', SSH.getBefore())
 				if result is None:
 					logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m')
@@ -1256,7 +893,7 @@ class OaiCiTest():
 		check_OAI_UE = False
 		pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
 		if (pStatus < 0):
-			self.CreateHtmlTestRow('N/A', 'KO', pStatus)
+			HTML.CreateHtmlTestRow('N/A', 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
 			return
 		multi_jobs = []
@@ -1275,7 +912,7 @@ class OaiCiTest():
 			job.join()
 
 		if (status_queue.empty()):
-			self.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK)
+			HTML.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK)
 			self.AutoTerminateUEandeNB()
 			return
 		else:
@@ -1298,13 +935,13 @@ class OaiCiTest():
 					if self.UEDevicesStatus[cnt] == UE_STATUS_ATTACHING:
 						self.UEDevicesStatus[cnt] = UE_STATUS_ATTACHED
 					cnt += 1
-				self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue)
+				HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue)
 				result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args()))
 				if result is not None:
 					logging.debug('Waiting 5 seconds to fill up record file')
 					time.sleep(5)
 			else:
-				self.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue)
+				HTML.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue)
 				self.AutoTerminateUEandeNB()
 
 	def DetachUE_common(self, device_id, idx):
@@ -1330,7 +967,7 @@ class OaiCiTest():
 		check_OAI_UE = False
 		pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
 		if (pStatus < 0):
-			self.CreateHtmlTestRow('N/A', 'KO', pStatus)
+			HTML.CreateHtmlTestRow('N/A', 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
 			return
 		multi_jobs = []
@@ -1344,7 +981,7 @@ class OaiCiTest():
 			cnt += 1
 		for job in multi_jobs:
 			job.join()
-		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+		HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 		result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args()))
 		if result is not None:
 			logging.debug('Waiting 5 seconds to fill up record file')
@@ -1401,8 +1038,8 @@ class OaiCiTest():
 		check_OAI_UE = False
 		pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
 		if (pStatus < 0):
-			self.CreateHtmlTestRow('N/A', 'KO', pStatus)
-			self.CreateHtmlTabFooter(False)
+			HTML.CreateHtmlTestRow('N/A', 'KO', pStatus)
+			HTML.CreateHtmlTabFooter(False)
 			sys.exit(1)
 		multi_jobs = []
 		for device_id in self.UEDevices:
@@ -1412,7 +1049,7 @@ class OaiCiTest():
 			multi_jobs.append(p)
 		for job in multi_jobs:
 			job.join()
-		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+		HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 
 	def DataDisableUE_common(self, device_id, idx):
 		try:
@@ -1441,7 +1078,7 @@ class OaiCiTest():
 			i += 1
 		for job in multi_jobs:
 			job.join()
-		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+		HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 
 	def DataEnableUE_common(self, device_id, idx):
 		try:
@@ -1470,7 +1107,7 @@ class OaiCiTest():
 			i += 1
 		for job in multi_jobs:
 			job.join()
-		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+		HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 
 	def GetAllUEDevices(self, terminate_ue_flag):
 		if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
@@ -1506,11 +1143,13 @@ class OaiCiTest():
 						self.UEDevicesRebootCmd.append(comma_split[5])
 					phone_list_file.close()
 
-		if terminate_ue_flag == False:
+		if terminate_ue_flag == True:
+			print('terminate_ue_flag == True')
 			if len(self.UEDevices) == 0:
 				logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m')
 				sys.exit(1)
 		if len(self.UEDevicesStatus) == 0:
+			print('len(self.UEDevicesStatus) == 0')
 			cnt = 0
 			while cnt < len(self.UEDevices):
 				self.UEDevicesStatus.append(UE_STATUS_DETACHED)
@@ -1533,7 +1172,7 @@ class OaiCiTest():
 			SSH.close()
 			if result is not None:
 				logging.debug('Found a module list file on ADB server')
-		if terminate_ue_flag == False:
+		if terminate_ue_flag == True:
 			if len(self.CatMDevices) == 0:
 				logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m')
 				sys.exit(1)
@@ -1596,8 +1235,8 @@ class OaiCiTest():
 		check_OAI_UE = False
 		pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
 		if (pStatus < 0):
-			self.CreateHtmlTestRow('N/A', 'KO', pStatus)
-			self.CreateHtmlTabFooter(False)
+			HTML.CreateHtmlTestRow('N/A', 'KO', pStatus)
+			HTML.CreateHtmlTabFooter(False)
 			sys.exit(1)
 		multi_jobs = []
 		lock = Lock()
@@ -1633,7 +1272,7 @@ class OaiCiTest():
 			htmlOptions = 'N/A'
 
 		if (status_queue.empty()):
-			self.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK)
+			HTML.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK)
 			self.AutoTerminateUEandeNB()
 		else:
 			check_status = True
@@ -1647,9 +1286,9 @@ class OaiCiTest():
 				html_cell = '<pre style="background-color:white">UE (' + device_id + ')\n' + message + '</pre>'
 				html_queue.put(html_cell)
 			if check_status and passStatus:
-				self.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue)
+				HTML.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue)
 			else:
-				self.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue)
+				HTML.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue)
 				self.AutoTerminateUEandeNB()
 
 	def GetAllUEIPAddresses(self):
@@ -1680,6 +1319,7 @@ class OaiCiTest():
 		SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
 		idx = 0
 		for device_id in self.UEDevices:
+			print('UE status attched'+UE_STATUS_ATTACHED)
 			if self.UEDevicesStatus[idx] != UE_STATUS_ATTACHED:
 				idx += 1
 				continue
@@ -1809,14 +1449,14 @@ class OaiCiTest():
 		html_queue = SimpleQueue()
 		html_cell = '<pre style="background-color:white">OAI UE ping result\n' + qMsg + '</pre>'
 		html_queue.put(html_cell)
-		self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue)
+		HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue)
 
 	def PingNoS1(self):
 		check_eNB = True
 		check_OAI_UE = True
 		pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
 		if (pStatus < 0):
-			self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
+			HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
 			return
 		ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args))
@@ -1889,13 +1529,13 @@ class OaiCiTest():
 			html_cell = '<pre style="background-color:white">OAI UE ping result\n' + qMsg + '</pre>'
 			html_queue.put(html_cell)
 			if packetLossOK:
-				self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue)
+				HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue)
 			else:
-				self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue)
+				HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue)
 
 			# copying on the EPC server for logCollection
 			if ping_from_eNB is not None:
-				copyin_res = SSH.copyin(RAN.GeteNBIPAddress, RAN.GeteNBUserName, RAN.GeteNBPassword, RAN.GeteNBSourceCodePath() + '/cmake_targets/ping_' + self.testCase_id + '.log', '.')
+				copyin_res = SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/ping_' + self.testCase_id + '.log', '.')
 			else:
 				copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.')
 			if (copyin_res == 0):
@@ -1918,12 +1558,12 @@ class OaiCiTest():
 			check_OAI_UE = False
 		pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
 		if (pStatus < 0):
-			self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
+			HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
 			return
 		ueIpStatus = self.GetAllUEIPAddresses()
 		if (ueIpStatus < 0):
-			self.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE)
+			HTML.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE)
 			self.AutoTerminateUEandeNB()
 			return
 		multi_jobs = []
@@ -1941,7 +1581,7 @@ class OaiCiTest():
 			job.join()
 
 		if (status_queue.empty()):
-			self.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK)
+			HTML.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK)
 			self.AutoTerminateUEandeNB()
 		else:
 			ping_status = True
@@ -1956,9 +1596,9 @@ class OaiCiTest():
 				html_cell = '<pre style="background-color:white">UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '</pre>'
 				html_queue.put(html_cell)
 			if (ping_status):
-				self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue)
+				HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue)
 			else:
-				self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue)
+				HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue)
 				self.AutoTerminateUEandeNB()
 
 	def Iperf_ComputeTime(self):
@@ -2347,6 +1987,7 @@ class OaiCiTest():
 
 	def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue):
 		try:
+			logging.debug('entring Iperf_common')
 			# Single-UE profile -- iperf only on one UE
 			if self.iperf_profile == 'single-ue' and idx != 0:
 				return
@@ -2520,9 +2161,9 @@ class OaiCiTest():
 					SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.')
 				SSH.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5)
 				# fromdos has to be called on the python executor not on ADB server
-                                cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log'
-                                subprocess.run(cmd, shell=True)
-                                self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options)
+				cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log'
+				subprocess.run(cmd, shell=True)
+				self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options)
 
 			# in case of OAI UE: 
 			if (device_id == 'OAI-UE'):
@@ -2543,14 +2184,14 @@ class OaiCiTest():
 		check_OAI_UE = True
 		pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
 		if (pStatus < 0):
-			self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus)
+			HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
 			return
 		server_on_enb = re.search('-R', str(self.iperf_args))
 		if server_on_enb is not None:
-			iServerIPAddr = RAN.GeteNBIPAddress
-			iServerUser = RAN.GeteNBUserName
-			iServerPasswd = RAN.GeteNBPassword
+			iServerIPAddr = RAN.GeteNBIPAddress()
+			iServerUser = RAN.GeteNBUserName()
+			iServerPasswd = RAN.GeteNBPassword()
 			iClientIPAddr = self.UEIPAddress
 			iClientUser = self.UEUserName
 			iClientPasswd = self.UEPassword
@@ -2558,9 +2199,9 @@ class OaiCiTest():
 			iServerIPAddr = self.UEIPAddress
 			iServerUser = self.UEUserName
 			iServerPasswd = self.UEPassword
-			iClientIPAddr = RAN.GeteNBIPAddress
-			iClientUser = RAN.GeteNBUserName
-			iClientPasswd = RAN.GeteNBPassword
+			iClientIPAddr = RAN.GeteNBIPAddress()
+			iClientUser = RAN.GeteNBUserName()
+			iClientPasswd = RAN.GeteNBPassword()
 		if self.iperf_options != 'sink':
 			# Starting the iperf server
 			SSH.open(iServerIPAddr, iServerUser, iServerPasswd)
@@ -2637,11 +2278,11 @@ class OaiCiTest():
 			html_cell = '<pre style="background-color:white">UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '</pre>'
 			html_queue.put(html_cell)
 		if (iperf_noperf and iperf_status):
-			self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue)
+			HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue)
 		elif (iperf_status):
-			self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue)
+			HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue)
 		else:
-			self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue)
+			HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue)
 			self.AutoTerminateUEandeNB()
 
 	def Iperf(self):
@@ -2659,12 +2300,13 @@ class OaiCiTest():
 			check_OAI_UE = False
 		pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
 		if (pStatus < 0):
-			self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus)
+			HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
 			return
 		ueIpStatus = self.GetAllUEIPAddresses()
 		if (ueIpStatus < 0):
-			self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE)
+			logging.debug('going here')
+			HTML.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE)
 			self.AutoTerminateUEandeNB()
 			return
 
@@ -2684,9 +2326,10 @@ class OaiCiTest():
 		ue_num = len(self.UEIPAddresses)
 		lock = Lock()
 		status_queue = SimpleQueue()
+		logging.debug('ue_num = ' + str(ue_num))
 		for UE_IPAddress in self.UEIPAddresses:
 			device_id = self.UEDevices[i]
-			p = Process(target = CiTestObj.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,))
+			p = Process(target = self.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,))
 			p.daemon = True
 			p.start()
 			multi_jobs.append(p)
@@ -2695,7 +2338,7 @@ class OaiCiTest():
 			job.join()
 
 		if (status_queue.empty()):
-			self.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK)
+			HTML.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK)
 			self.AutoTerminateUEandeNB()
 		else:
 			iperf_status = True
@@ -2713,11 +2356,11 @@ class OaiCiTest():
 				html_cell = '<pre style="background-color:white">UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '</pre>'
 				html_queue.put(html_cell)
 			if (iperf_noperf and iperf_status):
-				self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue)
+				HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue)
 			elif (iperf_status):
-				self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue)
+				HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue)
 			else:
-				self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue)
+				HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue)
 				self.AutoTerminateUEandeNB()
 
 	def CheckProcessExist(self, check_eNB, check_OAI_UE):
@@ -2743,12 +2386,12 @@ class OaiCiTest():
 			if (check_eNB == False) and (check_OAI_UE == False):
 				return 0
 		if check_eNB:
-			p = Process(target = CiTestObj.CheckeNBProcess, args = (status_queue,))
+			p = Process(target = RAN.CheckeNBProcess, args = (status_queue,))
 			p.daemon = True
 			p.start()
 			multi_jobs.append(p)
 		if check_OAI_UE:
-			p = Process(target = CiTestObj.CheckOAIUEProcess, args = (status_queue,))
+			p = Process(target = self.CheckOAIUEProcess, args = (status_queue,))
 			p.daemon = True
 			p.start()
 			multi_jobs.append(p)
@@ -2766,7 +2409,7 @@ class OaiCiTest():
 			if result == ENB_PROCESS_FAILED:
 				fileCheck = re.search('enb_', str(RAN.GeteNBLogFiles[0]))
 				if fileCheck is not None:
-					SSH.copyin(RAN.GeteNBIPAddress, RAN.GeteNBUserName, RAN.GeteNBPassword, RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFiles[0], '.')
+					SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFiles[0], '.')
 					logStatus = self.AnalyzeLogFile_eNB(RAN.GeteNBLogFiles[0])
 					if logStatus < 0:
 						result = logStatus
@@ -2779,7 +2422,7 @@ class OaiCiTest():
 		multi_jobs = []
 		status_queue = SimpleQueue()
 		if initialize_OAI_UE_flag == False:
-			p = Process(target = CiTestObj.CheckOAIUEProcess, args = (status_queue,))
+			p = Process(target = self.CheckOAIUEProcess, args = (status_queue,))
 			p.daemon = True
 			p.start()
 			multi_jobs.append(p)
@@ -2816,293 +2459,10 @@ class OaiCiTest():
 			SSH.close()
 		except:
 			os.kill(os.getppid(),signal.SIGUSR1)
-'''
-	def CheckeNBProcess(self, status_queue):
-		try:
-			# At least the instance 0 SHALL be on!
-			if self.eNBstatuses[0] == 0:
-				lIpAddr = self.eNBIPAddress
-				lUserName = self.eNBUserName
-				lPassWord = self.eNBPassword
-			elif self.eNBstatuses[0] == 1:
-				lIpAddr = self.eNB1IPAddress
-				lUserName = self.eNB1UserName
-				lPassWord = self.eNB1Password
-			elif self.eNBstatuses[0] == 2:
-				lIpAddr = self.eNB2IPAddress
-				lUserName = self.eNB2UserName
-				lPassWord = self.eNB2Password
-			else:
-				lIpAddr = self.eNBIPAddress
-				lUserName = self.eNBUserName
-				lPassWord = self.eNBPassword
-			SSH.open(lIpAddr, lUserName, lPassWord)
-			SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + '-softmodem | grep -v grep', '\$', 5)
-			result = re.search(self.air_interface + '-softmodem', SSH.getBefore())
-			if result is None:
-				logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m')
-				status_queue.put(ENB_PROCESS_FAILED)
-			else:
-				status_queue.put(ENB_PROCESS_OK)
-			SSH.close()
-		except:
-			os.kill(os.getppid(),signal.SIGUSR1)
-'''	
-	def AnalyzeLogFile_eNB(self, eNBlogFile):
-		if (not os.path.isfile('./' + eNBlogFile)):
-			return -1
-		enb_log_file = open('./' + eNBlogFile, 'r')
-		exitSignalReceived = False
-		foundAssertion = False
-		msgAssertion = ''
-		msgLine = 0
-		foundSegFault = False
-		foundRealTimeIssue = False
-		rrcSetupComplete = 0
-		rrcReleaseRequest = 0
-		rrcReconfigRequest = 0
-		rrcReconfigComplete = 0
-		rrcReestablishRequest = 0
-		rrcReestablishComplete = 0
-		rrcReestablishReject = 0
-		rlcDiscardBuffer = 0
-		rachCanceledProcedure = 0
-		uciStatMsgCount = 0
-		pdcpFailure = 0
-		ulschFailure = 0
-		cdrxActivationMessageCount = 0
-		dropNotEnoughRBs = 0
-		mbmsRequestMsg = 0
-		self.htmleNBFailureMsg = ''
-		isRRU = False
-		isSlave = False
-		slaveReceivesFrameResyncCmd = False
-		X2HO_state = X2_HO_REQ_STATE__IDLE
-		X2HO_inNbProcedures = 0
-		X2HO_outNbProcedures = 0
-		for line in enb_log_file.readlines():
-			if X2HO_state == X2_HO_REQ_STATE__IDLE:
-				result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line))
-				if result is not None:
-					X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ
-				result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line))
-				if result is not None:
-					X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK
-			if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ:
-				result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line))
-				if result is not None:
-					X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE
-			if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE:
-				result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line))
-				if result is not None:
-					X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ
-			if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ:
-				result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line))
-				if result is not None:
-					X2HO_state = X2_HO_REQ_STATE__IDLE
-					X2HO_inNbProcedures += 1
-			if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK:
-				result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line))
-				if result is not None:
-					X2HO_state = X2_HO_REQ_STATE__IDLE
-					X2HO_outNbProcedures += 1
-
-			if RAN.SeteNBOptions[int(RAN.GeteNB_instance())] != '':
-				res1 = re.search('max_rxgain (?P<requested_option>[0-9]+)', RAN.GeteNBOptions[int(RAN.GeteNB_instance())])
-				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> ' + RAN.GeteNBOptions[int(RAN.GeteNB_instance())] + '\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> ' + RAN.GeteNBOptions[int(RAN.GeteNB_instance())] + '\n\n'
-			result = re.search('Exiting OAI softmodem', str(line))
-			if result is not None:
-				exitSignalReceived = True
-			result = re.search('[Ss]egmentation [Ff]ault', str(line))
-			if result is not None and not exitSignalReceived:
-				foundSegFault = True
-			result = re.search('[Cc]ore [dD]ump', str(line))
-			if result is not None and not exitSignalReceived:
-				foundSegFault = True
-			result = re.search('./ran_build/build/lte-softmodem', str(line))
-			if result is not None and not exitSignalReceived:
-				foundSegFault = True
-			result = re.search('[Aa]ssertion', str(line))
-			if result is not None and not exitSignalReceived:
-				foundAssertion = True
-			result = re.search('LLL', str(line))
-			if result is not None and not exitSignalReceived:
-				foundRealTimeIssue = True
-			if foundAssertion and (msgLine < 3):
-				msgLine += 1
-				msgAssertion += str(line)
-			result = re.search('Setting function for RU', str(line))
-			if result is not None:
-				isRRU = True
-			if isRRU:
-				result = re.search('RU 0 is_slave=yes', str(line))
-				if result is not None:
-					isSlave = True
-				if isSlave:
-					result = re.search('Received RRU_frame_resynch command', str(line))
-					if result is not None:
-						slaveReceivesFrameResyncCmd = True
-			result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line))
-			if result is not None:
-				rrcSetupComplete += 1
-			result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line))
-			if result is not None:
-				rrcReleaseRequest += 1
-			result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line))
-			if result is not None:
-				rrcReconfigRequest += 1
-			result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line))
-			if result is not None:
-				rrcReconfigComplete += 1
-			result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line))
-			if result is not None:
-				rrcReestablishRequest += 1
-			result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line))
-			if result is not None:
-				rrcReestablishComplete += 1
-			result = re.search('LTE_RRCConnectionReestablishmentReject', str(line))
-			if result is not None:
-				rrcReestablishReject += 1
-			result = re.search('CDRX configuration activated after RRC Connection', str(line))
-			if result is not None:
-				cdrxActivationMessageCount += 1
-			result = re.search('uci->stat', str(line))
-			if result is not None:
-				uciStatMsgCount += 1
-			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
-			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
-			result = re.search('dropping, not enough RBs', str(line))
-			if result is not None:
-				dropNotEnoughRBs += 1
-			if RAN.GeteNBmbmsEnables[int(RAN.GeteNB_instance())]:
-				result = re.search('MBMS USER-PLANE.*Requesting.*bytes from RLC', str(line))
-				if result is not None:
-					mbmsRequestMsg += 1
-		enb_log_file.close()
-		logging.debug('   File analysis completed')
-		self.htmleNBFailureMsg = ''
-		if RAN.Getair_interface() == 'lte':
-			nodeB_prefix = 'e'
-		else:
-			nodeB_prefix = 'g'
-		if uciStatMsgCount > 0:
-			statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)'
-			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
-			self.htmleNBFailureMsg += statMsg + '\n'
-		if pdcpFailure > 0:
-			statMsg = nodeB_prefix + 'NB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)'
-			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
-			self.htmleNBFailureMsg += statMsg + '\n'
-		if ulschFailure > 0:
-			statMsg = nodeB_prefix + 'NB showed ' + str(ulschFailure) + ' "ULSCH in error in round" message(s)'
-			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
-			self.htmleNBFailureMsg += statMsg + '\n'
-		if dropNotEnoughRBs > 0:
-			statMsg = 'eNB showed ' + str(dropNotEnoughRBs) + ' "dropping, not enough RBs" message(s)'
-			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
-			self.htmleNBFailureMsg += statMsg + '\n'
-		if rrcSetupComplete > 0:
-			rrcMsg = nodeB_prefix + 'NB completed ' + str(rrcSetupComplete) + ' 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 = nodeB_prefix + 'NB 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 = nodeB_prefix + 'NB 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 = nodeB_prefix + 'NB 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'
-		if RAN.GeteNBmbmsEnables[int(RAN.GeteNB_instance())]:
-			if mbmsRequestMsg > 0:
-				rrcMsg = 'eNB requested ' + str(mbmsRequestMsg) + ' times the RLC for MBMS USER-PLANE'
-				logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
-				self.htmleNBFailureMsg += rrcMsg + '\n'
-		if X2HO_inNbProcedures > 0:
-			rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)'
-			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
-			self.htmleNBFailureMsg += rrcMsg + '\n'
-		if X2HO_outNbProcedures > 0:
-			rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)'
-			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
-			self.htmleNBFailureMsg += rrcMsg + '\n'
-		if RAN.SeteNBOptions[int(RAN.GeteNB_instance())] != '':
-			res1 = re.search('drx_Config_present prSetup', RAN.GeteNBOptions[int(RAN.GeteNB_instance())])
-			if res1 is not None:
-				if cdrxActivationMessageCount > 0:
-					rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)'
-					logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
-					self.htmleNBFailureMsg += rrcMsg + '\n'
-				else:
-					rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration'
-					logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m')
-					self.htmleNBFailureMsg += rrcMsg + '\n'
-		if rachCanceledProcedure > 0:
-			rachMsg = nodeB_prefix + 'NB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)'
-			logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m')
-			self.htmleNBFailureMsg += rachMsg + '\n'
-		if isRRU:
-			if isSlave:
-				if slaveReceivesFrameResyncCmd:
-					rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU'
-					logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m')
-					self.htmleNBFailureMsg += rruMsg + '\n'
-				else:
-					rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU'
-					logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m')
-					self.htmleNBFailureMsg += rruMsg + '\n'
-					self.prematureExit = True
-					return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED
-		if foundSegFault:
-			logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with a Segmentation Fault! \u001B[0m')
-			return ENB_PROCESS_SEG_FAULT
-		if foundAssertion:
-			logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with an assertion! \u001B[0m')
-			self.htmleNBFailureMsg += msgAssertion
-			return ENB_PROCESS_ASSERTION
-		if foundRealTimeIssue:
-			logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m')
-			self.htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n'
-			#return ENB_PROCESS_REALTIME_ISSUE
-		if rlcDiscardBuffer > 0:
-			rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)'
-			logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m')
-			self.htmleNBFailureMsg += rlcMsg + '\n'
-			return ENB_PROCESS_REALTIME_ISSUE
-		return 0
+
+
+#	def AnalyzeLogFile_eNB(self, eNBlogFile):
+#	...
 
 	def AnalyzeLogFile_UE(self, UElogFile):
 		if (not os.path.isfile('./' + UElogFile)):
@@ -3354,104 +2714,8 @@ class OaiCiTest():
 				self.htmlUEFailureMsg += 'UE could not synchronize!\n'
 				return OAI_UE_PROCESS_COULD_NOT_SYNC
 		return 0
-'''
-	def TerminateeNB(self):
-		if self.eNB_serverId == '0':
-			lIpAddr = self.eNBIPAddress
-			lUserName = self.eNBUserName
-			lPassWord = self.eNBPassword
-			lSourcePath = RAN.GeteNBSourceCodePath()
-		elif self.eNB_serverId == '1':
-			lIpAddr = self.eNB1IPAddress
-			lUserName = self.eNB1UserName
-			lPassWord = self.eNB1Password
-			lSourcePath = self.eNB1SourceCodePath
-		elif self.eNB_serverId == '2':
-			lIpAddr = self.eNB2IPAddress
-			lUserName = self.eNB2UserName
-			lPassWord = self.eNB2Password
-			lSourcePath = self.eNB2SourceCodePath
-		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
-			GenericHelp(Version)
-			sys.exit('Insufficient Parameter')
-		SSH.open(lIpAddr, lUserName, lPassWord)
-		SSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5)
-		if self.air_interface == 'lte':
-			nodeB_prefix = 'e'
-		else:
-			nodeB_prefix = 'g'
-		SSH.command('stdbuf -o0  ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5)
-		result = re.search('-softmodem', SSH.getBefore())
-		if result is not None:
-			SSH.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5)
-			SSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT -r .*-softmodem || true', '\$', 5)
-			time.sleep(10)
-			SSH.command('stdbuf -o0  ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5)
-			result = re.search('-softmodem', SSH.getBefore())
-			if result is not None:
-				SSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem || true', '\$', 5)
-				time.sleep(5)
-		SSH.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
-		SSH.close()
-		# If tracer options is on, stopping tshark on EPC side
-		result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args()))
-		if result is not None:
-			SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword())
-			logging.debug('\u001B[1m Stopping tshark \u001B[0m')
-			SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5)
-			time.sleep(1)
-			if EPC.EPC_PcapFileName  != '':
-				SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5)
-				SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.EPC_PcapFileName , '.')
-				SSH.copyout(lIpAddr, lUserName, lPassWord, EPC.EPC_PcapFileName , lSourcePath + '/cmake_targets/.')
-			SSH.close()
-			logging.debug('\u001B[1m Replaying RAW record file\u001B[0m')
-			SSH.open(lIpAddr, lUserName, lPassWord)
-			SSH.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5)
-			enbLogFile = self.eNBLogFiles[int(self.eNB_instance)]
-			raw_record_file = enbLogFile.replace('.log', '_record.raw')
-			replay_log_file = enbLogFile.replace('.log', '_replay.log')
-			extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt')
-			extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log')
-			SSH.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5)
-			SSH.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5)
-			SSH.command('./textlog -d ' +  lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5)
-			SSH.close()
-			SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/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)
-			self.eNBLogFiles[int(self.eNB_instance)] = ''
-		else:
-			analyzeFile = False
-			if self.eNBLogFiles[int(self.eNB_instance)] != '':
-				analyzeFile = True
-				fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)]
-				self.eNBLogFiles[int(self.eNB_instance)] = ''
-			if analyzeFile:
-				copyin_res = SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.')
-				if (copyin_res == -1):
-					logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m')
-					self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!'
-					self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE)
-					self.eNBmbmsEnables[int(self.eNB_instance)] = False
-					return
-				if self.eNB_serverId != '0':
-					SSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, RAN.GeteNBSourceCodePath() + '/cmake_targets/')
-				logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + fileToAnalyze)
-				logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze)
-				if (logStatus < 0):
-					self.CreateHtmlTestRow('N/A', 'KO', logStatus)
-					self.preamtureExit = True
-					self.eNBmbmsEnables[int(self.eNB_instance)] = False
-					return
-				else:
-					self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
-			else:
-				self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
-		self.eNBmbmsEnables[int(self.eNB_instance)] = False
-		self.eNBstatuses[int(self.eNB_instance)] = -1
-'''	
+
+
 	def TerminateFlexranCtrl(self):
 		if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False:
 			return
@@ -3465,7 +2729,7 @@ class OaiCiTest():
 		time.sleep(1)
 		SSH.close()
 		self.flexranCtrlStarted = False
-		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+		HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 
 	def TerminateUE_common(self, device_id, idx):
 		try:
@@ -3496,19 +2760,19 @@ class OaiCiTest():
 			os.kill(os.getppid(),signal.SIGUSR1)
 
 	def TerminateUE(self):
-		terminate_ue_flag = True
+		terminate_ue_flag = False
 		self.GetAllUEDevices(terminate_ue_flag)
 		multi_jobs = []
 		i = 0
 		for device_id in self.UEDevices:
-			p = Process(target= CiTestObj.TerminateUE_common, args = (device_id,i,))
+			p = Process(target= self.TerminateUE_common, args = (device_id,i,))
 			p.daemon = True
 			p.start()
 			multi_jobs.append(p)
 			i += 1
 		for job in multi_jobs:
 			job.join()
-		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+		HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 
 	def TerminateOAIUE(self):
 		SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
@@ -3531,7 +2795,7 @@ class OaiCiTest():
 			if (copyin_res == -1):
 				logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m')
 				self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!'
-				self.CreateHtmlTestRow('N/A', 'KO', OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE')
+				HTML.CreateHtmlTestRow('N/A', 'KO', OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE')
 				self.UELogFile = ''
 				return
 			logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m')
@@ -3544,7 +2808,7 @@ class OaiCiTest():
 			if (logStatus < 0):
 				logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m')
 				self.htmlUEFailureMsg = '<b>' + ueAction + ' Failed</b>\n' + self.htmlUEFailureMsg
-				self.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE')
+				HTML.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE')
 				if RAN.Getair_interface() == 'lte':
 					# In case of sniffing on commercial eNBs we have random results
 					# Not an error then
@@ -3558,38 +2822,42 @@ class OaiCiTest():
 			else:
 				logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m')
 				self.htmlUEFailureMsg = '<b>' + ueAction + ' Completed</b>\n' + self.htmlUEFailureMsg
-				self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+				HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 			self.UELogFile = ''
 		else:
-			self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+			HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 
 	def AutoTerminateUEandeNB(self):
 		if (self.ADBIPAddress != 'none'):
 			self.testCase_id = 'AUTO-KILL-UE'
+			RAN.SettestCase_id(self.testCase_id)
 			self.desc = 'Automatic Termination of UE'
 			self.ShowTestID()
 			self.TerminateUE()
 		if (self.Initialize_OAI_UE_args != ''):
 			self.testCase_id = 'AUTO-KILL-UE'
+			RAN.SettestCase_id(self.testCase_id)
 			self.desc = 'Automatic Termination of UE'
 			self.ShowTestID()
 			self.TerminateOAIUE()
 		if (RAN.GetInitialize_eNB_args() != ''):
 			self.testCase_id = 'AUTO-KILL-eNB'
+			RAN.SettestCase_id(self.testCase_id)
 			self.desc = 'Automatic Termination of eNB'
 			self.ShowTestID()
-			RAN.SeteNB_instance() = '0'
-			self.TerminateeNB()
+			RAN.SeteNB_instance('0')
+			RAN.TerminateeNB()
 		if self.flexranCtrlInstalled and self.flexranCtrlStarted:
 			self.testCase_id = 'AUTO-KILL-flexran-ctl'
+			RAN.SettestCase_id(self.testCase_id)
 			self.desc = 'Automatic Termination of FlexRan CTL'
 			self.ShowTestID()
 			self.TerminateFlexranCtrl()
-		self.prematureExit = True
+		RAN.SetprematureExit(True)
 
 	def IdleSleep(self):
 		time.sleep(self.idle_sleep_time)
-		self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK)
+		HTML.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK)
 
 	def X2_Status(self, idx, fileName):
 		cmd = "curl --silent http://" + EPC.GetIPAddress() + ":9999/stats | jq '.' > " + fileName
@@ -3691,21 +2959,21 @@ class OaiCiTest():
 					logging.debug(msg)
 					fullMessage += msg + '</pre>'
 					html_queue.put(fullMessage)
-					self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue)
+					HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue)
 				else:
 					msg = "X2 Handover FAILED"
 					logging.error(msg)
 					fullMessage += msg + '</pre>'
 					html_queue.put(fullMessage)
-					self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue)
+					HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue)
 			else:
-				self.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK)
+				HTML.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK)
 
 	def LogCollectBuild(self):
 		if (RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != ''):
-			IPAddress = RAN.GeteNBIPAddress
-			UserName = RAN.GeteNBUserName
-			Password = RAN.GeteNBPassword
+			IPAddress = RAN.GeteNBIPAddress()
+			UserName = RAN.GeteNBUserName()
+			Password = RAN.GeteNBPassword()
 			SourceCodePath = RAN.GeteNBSourceCodePath()
 		elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''):
 			IPAddress = self.UEIPAddress
@@ -3720,16 +2988,6 @@ class OaiCiTest():
 		SSH.command('rm -f build.log.zip', '\$', 5)
 		SSH.command('zip build.log.zip build_log_*/*', '\$', 60)
 		SSH.close()
-'''
-	def LogCollecteNB(self):
-		SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
-		SSH.command('cd ' + RAN.GeteNBSourceCodePath(), '\$', 5)
-		SSH.command('cd cmake_targets', '\$', 5)
-		SSH.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5)
-		SSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60)
-		SSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5)
-		SSH.close()
-'''
 	def LogCollectPing(self):
 		SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword())
 		SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5)
@@ -3769,9 +3027,9 @@ class OaiCiTest():
 			return 0
 		if machine == 'eNB':
 			if RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != '':
-				IPAddress = RAN.GeteNBIPAddress
-				UserName = RAN.GeteNBUserName
-				Password = RAN.GeteNBPassword
+				IPAddress = RAN.GeteNBIPAddress()
+				UserName = RAN.GeteNBUserName()
+				Password = RAN.GeteNBPassword()
 			else:
 				return -1
 		if machine == 'UE':
@@ -3837,335 +3095,6 @@ class OaiCiTest():
 			logging.debug('cpu_mhz: ' + self.CpuMHz)
 		SSH.close()
 
-#-----------------------------------------------------------
-# HTML Reporting....
-#-----------------------------------------------------------
-	def CreateHtmlHeader(self):
-		if (not self.htmlHeaderCreated):
-			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
-			logging.debug('\u001B[1m  Creating HTML header \u001B[0m')
-			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
-			self.htmlFile = open('test_results.html', 'w')
-			self.htmlFile.write('<!DOCTYPE html>\n')
-			self.htmlFile.write('<html class="no-js" lang="en-US">\n')
-			self.htmlFile.write('<head>\n')
-			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')
-			self.htmlFile.write('  <title>Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID</title>\n')
-			self.htmlFile.write('</head>\n')
-			self.htmlFile.write('<body><div class="container">\n')
-			self.htmlFile.write('  <br>\n')
-			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')
-			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')
-			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')
-			self.htmlFile.write('  <div class="alert alert-info"><strong> <span class="glyphicon glyphicon-dashboard"></span> TEMPLATE_STAGE_NAME</strong></div>\n')
-			self.htmlFile.write('  <table border = "1">\n')
-			self.htmlFile.write('     <tr>\n')
-			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-time"></span> Build Start Time (UTC) </td>\n')
-			self.htmlFile.write('       <td>TEMPLATE_BUILD_TIME</td>\n')
-			self.htmlFile.write('     </tr>\n')
-			self.htmlFile.write('     <tr>\n')
-			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-cloud-upload"></span> GIT Repository </td>\n')
-			self.htmlFile.write('       <td><a href="' + RAN.GetranRepository() + '">' + RAN.GetranRepository() + '</a></td>\n')
-			self.htmlFile.write('     </tr>\n')
-			self.htmlFile.write('     <tr>\n')
-			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-wrench"></span> Job Trigger </td>\n')
-			if (RAN.GetranAllowMerge):
-				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')
-			if (RAN.GetranAllowMerge):
-				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-out"></span> Source Branch </td>\n')
-			else:
-				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tree-deciduous"></span> Branch</td>\n')
-			self.htmlFile.write('       <td>' + RAN.GetranBranch() + '</td>\n')
-			self.htmlFile.write('     </tr>\n')
-			self.htmlFile.write('     <tr>\n')
-			if (RAN.GetranAllowMerge):
-				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Source Commit ID </td>\n')
-			else:
-				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Commit ID </td>\n')
-			self.htmlFile.write('       <td>' + RAN.GetranCommitID() + '</td>\n')
-			self.htmlFile.write('     </tr>\n')
-			if RAN.GetranAllowMerge() != '':
-				commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + RAN.GetranCommitID, shell=True, universal_newlines=True)
-				commit_message = commit_message.strip()
-				self.htmlFile.write('     <tr>\n')
-				if (RAN.GetranAllowMerge):
-					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 (RAN.GetranAllowMerge):
-				self.htmlFile.write('     <tr>\n')
-				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-in"></span> Target Branch </td>\n')
-				if (RAN.GetranTargetBranch() == ''):
-					self.htmlFile.write('       <td>develop</td>\n')
-				else:
-					self.htmlFile.write('       <td>' + RAN.GetranTargetBranch() + '</td>\n')
-				self.htmlFile.write('     </tr>\n')
-			self.htmlFile.write('  </table>\n')
-
-			if (self.ADBIPAddress != 'none'):
-				terminate_ue_flag = True
-				self.GetAllUEDevices(terminate_ue_flag)
-				self.GetAllCatMDevices(terminate_ue_flag)
-				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')
-			else:
-				self.UEDevices.append('OAI-UE')
-				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)) + ' OAI UE(s) is(are) connected to CI bench</h2>\n')
-			self.htmlFile.write('  <br>\n')
-			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 += '__STATE_' + self.htmlTabNames[count] + '__'
-				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()
-
-	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')
-			self.htmlFile.write('      <tr bgcolor = "#33CCFF" >\n')
-			self.htmlFile.write('        <th>Relative Time (ms)</th>\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')
-			if (self.htmlUEConnected == -1):
-				terminate_ue_flag = True
-				if (self.ADBIPAddress != 'none'):
-					self.GetAllUEDevices(terminate_ue_flag)
-					self.GetAllCatMDevices(terminate_ue_flag)
-				else:
-					self.UEDevices.append('OAI-UE')
-				self.htmlUEConnected = len(self.UEDevices)
-
-			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
-
-	def CreateHtmlTabFooter(self, passStatus):
-		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
-			self.htmlFile.write('      <tr>\n')
-			self.htmlFile.write('        <th bgcolor = "#33CCFF" colspan=3>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.htmlFile.close()
-			time.sleep(1)
-			if passStatus:
-				cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html"
-				subprocess.run(cmd, shell=True)
-			else:
-				cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<span class=\"glyphicon glyphicon-remove\"><\/span>/' test_results.html"
-				subprocess.run(cmd, shell=True)
-		self.htmlFooterCreated = False
-
-	def CreateHtmlFooter(self, passStatus):
-		if (os.path.isfile('test_results.html')):
-			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
-			logging.debug('\u001B[1m  Creating HTML footer \u001B[0m')
-			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
-
-			self.htmlFile = open('test_results.html', 'a')
-			self.htmlFile.write('</div>\n')
-			self.htmlFile.write('  <p></p>\n')
-			self.htmlFile.write('  <table class="table table-condensed">\n')
-
-			machines = [ 'eNB', 'UE' ]
-			for machine in machines:
-				res = self.RetrieveSystemVersion(machine)
-				if res == -1:
-					continue
-				self.htmlFile.write('      <tr>\n')
-				self.htmlFile.write('        <th colspan=8>' + str(machine) + ' Server Characteristics</th>\n')
-				self.htmlFile.write('      </tr>\n')
-				self.htmlFile.write('      <tr>\n')
-				self.htmlFile.write('        <td>OS Version</td>\n')
-				self.htmlFile.write('        <td><span class="label label-default">' + self.OsVersion + '</span></td>\n')
-				self.htmlFile.write('        <td>Kernel Version</td>\n')
-				self.htmlFile.write('        <td><span class="label label-default">' + self.KernelVersion + '</span></td>\n')
-				self.htmlFile.write('        <td>UHD Version</td>\n')
-				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')
-				self.htmlFile.write('      </tr>\n')
-				self.htmlFile.write('      <tr>\n')
-				self.htmlFile.write('        <td>Nb CPUs</td>\n')
-				self.htmlFile.write('        <td><span class="label label-default">' + self.CpuNb + '</span></td>\n')
-				self.htmlFile.write('        <td>CPU Model Name</td>\n')
-				self.htmlFile.write('        <td><span class="label label-default">' + self.CpuModel + '</span></td>\n')
-				self.htmlFile.write('        <td>CPU Frequency</td>\n')
-				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')
-				self.htmlFile.write('      </tr>\n')
-
-			self.htmlFile.write('      <tr>\n')
-			self.htmlFile.write('        <th colspan=5 bgcolor = "#33CCFF">Final Status</th>\n')
-			if passStatus:
-				self.htmlFile.write('        <th colspan=3 bgcolor="green"><font color="white">PASS <span class="glyphicon glyphicon-ok"></span></font></th>\n')
-			else:
-				self.htmlFile.write('        <th colspan=3 bgcolor="red"><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('  <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')
-			self.htmlFile.write('</html>\n')
-			self.htmlFile.close()
-
-	def CreateHtmlRetrySeparator(self):
-		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
-			self.htmlFile.write('      <tr bgcolor = "#33CCFF" >\n')
-			self.htmlFile.write('        <td colspan=' + str(5+self.htmlUEConnected) + '>Try Run #' + str(self.FailReportCnt) + '</td>\n')
-			self.htmlFile.write('      </tr>\n')
-
-	def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'):
-		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
-			currentTime = int(round(time.time() * 1000)) - self.startTime
-			self.htmlFile.write('      <tr>\n')
-			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + format(currentTime / 1000, '.1f') + '</td>\n')
-			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + self.testCase_id  + '</td>\n')
-			self.htmlFile.write('        <td>' + self.desc  + '</td>\n')
-			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'):
-				if (processesStatus == 0):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >' + str(status)  + '</td>\n')
-				elif (processesStatus == ENB_PROCESS_FAILED):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - eNB process not found</td>\n')
-				elif (processesStatus == OAI_UE_PROCESS_FAILED):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - OAI UE process not found</td>\n')
-				elif (processesStatus == ENB_PROCESS_SEG_FAULT) or (processesStatus == OAI_UE_PROCESS_SEG_FAULT):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process ended in Segmentation Fault</td>\n')
-				elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process ended in Assertion</td>\n')
-				elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE):
-					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 == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE):
-					self.htmlFile.write('        <td bgcolor = "orange" >OK?</td>\n')
-				elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' Slave RRU could not synch</td>\n')
-				elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - UE could not sync</td>\n')
-				elif (processesStatus == HSS_PROCESS_FAILED):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - HSS process not found</td>\n')
-				elif (processesStatus == MME_PROCESS_FAILED):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - MME process not found</td>\n')
-				elif (processesStatus == SPGW_PROCESS_FAILED):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - SPGW process not found</td>\n')
-				elif (processesStatus == UE_IP_ADDRESS_ISSUE):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - Could not retrieve UE IP address</td>\n')
-				else:
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >' + str(status)  + '</td>\n')
-			else:
-				self.htmlFile.write('        <td bgcolor = "orange" >' + str(status)  + '</td>\n')
-			if (len(str(self.htmleNBFailureMsg)) > 2):
-				cellBgColor = 'white'
-				result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg)
-				if result is not None:
-					cellBgColor = 'red'
-				else:
-					result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg)
-					if result is not None:
-						cellBgColor = 'orange'
-				self.htmlFile.write('        <td bgcolor = "' + cellBgColor + '" colspan=' + str(self.htmlUEConnected) + '><pre style="background-color:' + cellBgColor + '">' + self.htmleNBFailureMsg + '</pre></td>\n')
-				self.htmleNBFailureMsg = ''
-			elif (len(str(self.htmlUEFailureMsg)) > 2):
-				cellBgColor = 'white'
-				result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg)
-				if result is not None:
-					cellBgColor = 'red'
-				else:
-					result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg)
-					if result is not None:
-						cellBgColor = 'orange'
-				self.htmlFile.write('        <td bgcolor = "' + cellBgColor + '" colspan=' + str(self.htmlUEConnected) + '><pre style="background-color:' + cellBgColor + '">' + self.htmlUEFailureMsg + '</pre></td>\n')
-				self.htmlUEFailureMsg = ''
-			else:
-				i = 0
-				while (i < self.htmlUEConnected):
-					self.htmlFile.write('        <td>-</td>\n')
-					i += 1
-			self.htmlFile.write('      </tr>\n')
-
-	def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue):
-		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
-			currentTime = int(round(time.time() * 1000)) - self.startTime
-			addOrangeBK = False
-			self.htmlFile.write('      <tr>\n')
-			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + format(currentTime / 1000, '.1f') + '</td>\n')
-			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + self.testCase_id  + '</td>\n')
-			self.htmlFile.write('        <td>' + self.desc  + '</td>\n')
-			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:
-				addOrangeBK = True
-				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()):
-						if (addOrangeBK):
-							self.htmlFile.write('        <td bgcolor = "orange" >' + str(ue_queue.get()).replace('white', 'orange') + '</td>\n')
-						else:
-							self.htmlFile.write('        <td>' + str(ue_queue.get()) + '</td>\n')
-					else:
-						self.htmlFile.write('        <td>-</td>\n')
-				else:
-					self.htmlFile.write('        <td>-</td>\n')
-				i += 1
-			self.htmlFile.write('      </tr>\n')
-
 #-----------------------------------------------------------
 # ShowTestID()
 #-----------------------------------------------------------
@@ -4183,47 +3112,47 @@ def CheckClassValidity(action,id):
 
 def GetParametersFromXML(action):
 	if action == 'Build_eNB':
-		RAN.SetBuild_eNB_args() = test.findtext('Build_eNB_args')
+		RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args'))
 		forced_workspace_cleanup = test.findtext('forced_workspace_cleanup')
 		if (forced_workspace_cleanup is None):
-			RAN.SetBuild_eNB_forced_workspace_cleanup() = False
+			RAN.SetBuild_eNB_forced_workspace_cleanup(False)
 		else:
 			if re.match('true', forced_workspace_cleanup, re.IGNORECASE):
-				RAN.SetBuild_eNB_forced_workspace_cleanup() = True
+				RAN.SetBuild_eNB_forced_workspace_cleanup(True)
 			else:
-				RAN.SetBuild_eNB_forced_workspace_cleanup() = False
-		RAN.SeteNB_instance() = test.findtext('eNB_instance')
+				RAN.SetBuild_eNB_forced_workspace_cleanup(False)
+		RAN.SeteNB_instance(test.findtext('eNB_instance'))
 		if (RAN.GeteNB_instance() is None):
-			RAN.SeteNB_instance() = '0'
-		CiTestObj.eNB_serverId = test.findtext('eNB_serverId')
-		if (CiTestObj.eNB_serverId is None):
-			CiTestObj.eNB_serverId = '0'
+			RAN.SeteNB_instance('0')
+		RAN.SeteNB_serverId(test.findtext('eNB_serverId'))
+		if (RAN.GeteNB_serverId() is None):
+			RAN.SeteNB_serverId('0')
 		xmlBgBuildField = test.findtext('backgroundBuild')
 		if (xmlBgBuildField is None):
-			RAN.SetbackgroundBuild() = False
+			RAN.SetbackgroundBuild(False)
 		else:
 			if re.match('true', xmlBgBuildField, re.IGNORECASE):
-				RAN.SetbackgroundBuild() = True
+				RAN.SetbackgroundBuild(True)
 			else:
-				RAN.SetbackgroundBuild() = False
+				RAN.SetbackgroundBuild(False)
 
 	if action == 'WaitEndBuild_eNB':
-		RAN.SetBuild_eNB_args() = test.findtext('Build_eNB_args')
-		RAN.SeteNB_instance() = test.findtext('eNB_instance')
+		RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args'))
+		RAN.SeteNB_instance(test.findtext('eNB_instance'))
 		if (RAN.GeteNB_instance() is None):
-			RAN.SeteNB_instance() = '0'
-		CiTestObj.eNB_serverId = test.findtext('eNB_serverId')
-		if (CiTestObj.eNB_serverId is None):
-			CiTestObj.eNB_serverId = '0'
+			RAN.SeteNB_instance('0')
+		RAN.SeteNB_serverId(test.findtext('eNB_serverId'))
+		if (RAN.GeteNB_serverId() is None):
+			RAN.SeteNB_serverId('0')
 
 	if action == 'Initialize_eNB':
-		RAN.SetInitialize_eNB_args() = test.findtext('Initialize_eNB_args')
-		RAN.SeteNB_instance() = test.findtext('eNB_instance')
+		RAN.SetInitialize_eNB_args(test.findtext('Initialize_eNB_args'))
+		RAN.SeteNB_instance(test.findtext('eNB_instance'))
 		if (RAN.GeteNB_instance() is None):
-			RAN.SeteNB_instance = '0'
-		CiTestObj.eNB_serverId = test.findtext('eNB_serverId')
-		if (CiTestObj.eNB_serverId is None):
-			CiTestObj.eNB_serverId = '0'
+			RAN.SeteNB_instance('0')
+		RAN.SeteNB_serverId(test.findtext('eNB_serverId'))
+		if (RAN.GeteNB_serverId() is None):
+			RAN.SeteNB_serverId('0')
 		CiTestObj.air_interface = test.findtext('air_interface')
 		if (CiTestObj.air_interface is None):
 			CiTestObj.air_interface = 'lte'
@@ -4231,12 +3160,12 @@ def GetParametersFromXML(action):
 			CiTestObj.air_interface = CiTestObj.air_interface.lower()
 
 	if action == 'Terminate_eNB':
-		RAN.SeteNB_instance() = test.findtext('eNB_instance')
+		RAN.SeteNB_instance(test.findtext('eNB_instance'))
 		if (RAN.GeteNB_instance() is None):
-			RAN.SeteNB_instance() = '0'
-		CiTestObj.eNB_serverId = test.findtext('eNB_serverId')
-		if (CiTestObj.eNB_serverId is None):
-			CiTestObj.eNB_serverId = '0'
+			RAN.SeteNB_instance('0')
+		RAN.SeteNB_serverId(test.findtext('eNB_serverId'))
+		if (RAN.GeteNB_serverId() is None):
+			RAN.SeteNB_serverId('0')
 		CiTestObj.air_interface = test.findtext('air_interface')
 		if (CiTestObj.air_interface is None):
 			CiTestObj.air_interface = 'lte'
@@ -4277,7 +3206,7 @@ def GetParametersFromXML(action):
 			CiTestObj.air_interface = SSH.air_interface.lower()
 
 	if action == 'Terminate_OAI_UE':
-		RAN.SeteNB_instance = test.findtext('UE_instance')
+		RAN.SeteNB_instance(test.findtext('UE_instance'))
 		if (CiTestObj.UE_instance is None):
 			CiTestObj.UE_instance = '0'
 
@@ -4340,15 +3269,18 @@ def receive_signal(signum, frame):
 mode = ''
 CiTestObj = OaiCiTest()
 
-from sshconnection import *
-from epc import *
-from helpreadme import *
-from enb import *
-SSH = SSHConnection()
-EPC = EPCManagement()
-RAN = RANManagement()
-#HELP = HelpReadme()
-#HELP.GenericHelp()
+import sshconnection 
+import epc
+import helpreadme
+import ran
+import html
+import constants
+ 
+SSH = sshconnection.SSHConnection()
+EPC = epc.EPCManagement()
+RAN = ran.RANManagement()
+HTML = html.HTMLManagement()
+
 
 argvs = sys.argv
 argc = len(argvs)
@@ -4356,6 +3288,7 @@ cwd = os.getcwd()
 
 while len(argvs) > 1:
 	myArgv = argvs.pop(1)	# 0th is this file's name
+
 	if re.match('^\-\-help$', myArgv, re.IGNORECASE):
 		GenericHelp(Version)
 		sys.exit(0)
@@ -4367,7 +3300,8 @@ while len(argvs) > 1:
 			matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE)
 		else:
 			matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE)
-		RAN.SetranRepository() = matchReg.group(1)
+		RAN.SetranRepository(matchReg.group(1))
+		HTML.SetranRepository(matchReg.group(1))
 	elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE):
 		if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE)
@@ -4375,68 +3309,72 @@ while len(argvs) > 1:
 			matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE)
 		doMerge = matchReg.group(1)
 		if ((doMerge == 'true') or (doMerge == 'True')):
-			RAN.SetranAllowMerge() = True
+			RAN.SetranAllowMerge(True)
+			HTML.SetranAllowMerge(True)
 	elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE):
 		if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE)
 		else:
 			matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE)
-		RAN.SetranBranch() = matchReg.group(1)
+		RAN.SetranBranch(matchReg.group(1))
+		HTML.SetranBranch(matchReg.group(1))
 	elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE):
 		if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE)
 		else:
 			matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE)
-		RAN.SetranCommitID() = matchReg.group(1)
+		RAN.SetranCommitID(matchReg.group(1))
+		HTML.SetranCommitID(matchReg.group(1))
 	elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE):
 		if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE)
 		else:
 			matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE)
-		RAN.SetranTargetBranch() = matchReg.group(1)
+		RAN.SetranTargetBranch(matchReg.group(1))
 	elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE):
 		if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE)
-			RAN.SeteNBIPAddress() = matchReg.group(1)
+			RAN.SeteNBIPAddress(matchReg.group(1))
 		elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE)
-			RAN.SeteNB1IPAddress() = matchReg.group(1)
+			RAN.SeteNB1IPAddress(matchReg.group(1))
 		elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE)
-			RAN.SeteNB2IPAddress() = matchReg.group(1)
+			RAN.SeteNB2IPAddress(matchReg.group(1))
 	elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE):
 		if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE)
-			RAN.SeteNBUserName() = matchReg.group(1)
+			RAN.SeteNBUserName(matchReg.group(1))
 		elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE)
-			RAN.SeteNB1UserName() = matchReg.group(1)
+			RAN.SeteNB1UserName(matchReg.group(1))
 		elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE)
-			RAN.SeteNB2UserName() = matchReg.group(1)
+			RAN.SeteNB2UserName(matchReg.group(1))
 	elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE):
 		if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE)
-			RAN.SeteNBPassword() = matchReg.group(1)
+			RAN.SeteNBPassword(matchReg.group(1))
 		elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE)
-			RAN.SeteNB1Password() = matchReg.group(1)
+			RAN.SeteNB1Password(matchReg.group(1))
 		elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE)
-			RAN.SeteNB2Password() = matchReg.group(1)
+			RAN.SeteNB2Password(matchReg.group(1))
 	elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
 		if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE)
-			RAN.SeteNBSourceCodePath() = matchReg.group(1)
+			RAN.SeteNBSourceCodePath(matchReg.group(1))
 		elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE)
-			RAN.SeteNB1SourceCodePath() = matchReg.group(1)
+			RAN.SeteNB1SourceCodePath(matchReg.group(1))
 		elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
 			matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE)
-			RAN.SeteNB2SourceCodePath() = matchReg.group(1)
+			RAN.SeteNB2SourceCodePath(matchReg.group(1))
 	elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE):
 		matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE)
 		EPC.SetIPAddress(matchReg.group(1))
+#GP250220: do we still need EPCBranch? it's not used anywhere
 	elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE):
 		matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE)
 		CiTestObj.EPCBranch = matchReg.group(1)
@@ -4476,6 +3414,7 @@ while len(argvs) > 1:
 	elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE):
 		matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE)
 		CiTestObj.testXMLfiles.append(matchReg.group(1))
+		HTML.SettestXMLfiles(matchReg.group(1))
 		CiTestObj.nbTestXMLfiles += 1
 	elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE):
 		matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE)
@@ -4502,9 +3441,9 @@ if re.match('^TerminateeNB$', mode, re.IGNORECASE):
 	if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '':
 		GenericHelp(Version)
 		sys.exit('Insufficient Parameter')
-	CiTestObj.eNB_serverId = '0'
-	RAN.SeteNB_instance = '0'
-	RAN.GeteNBSourceCodePath() = '/tmp/'
+	RAN.SeteNB_serverId('0')
+	RAN.SeteNB_instance('0')
+	RAN.SeteNBSourceCodePath('/tmp/')
 	CiTestObj.TerminateeNB()
 elif re.match('^TerminateUE$', mode, re.IGNORECASE):
 	if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''):
@@ -4588,23 +3527,38 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE):
 			except:
 				print("Error while parsing file: " + xml_test_file)
 			xmlRoot = xmlTree.getroot()
-			CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count)))
-			CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count)))
-			CiTestObj.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign'))
+			HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count)))
+			HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count)))
+			HTML.SethtmlTabIcons(xmlRoot.findtext('htmlTabIcon',default='info-sign'))
+			#CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count)))
+			#CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count)))
+			#CiTestObj.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign'))
 			foundCount += 1
 		count += 1
 	if foundCount != CiTestObj.nbTestXMLfiles:
 		CiTestObj.nbTestXMLfiles = foundCount
-	CiTestObj.CreateHtmlHeader()
+	HTML.SetnbTestXMLfiles(CiTestObj.nbTestXMLfiles)
+	
+	if (CiTestObj.ADBIPAddress != 'none'):
+		terminate_ue_flag = False
+		CiTestObj.GetAllUEDevices(terminate_ue_flag)
+		CiTestObj.GetAllCatMDevices(terminate_ue_flag)
+		HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices))
+		HTML.SethtmlNb_Smartphones(len(CiTestObj.UEDevices))
+		HTML.SethtmlNb_CATM_Modules(len(CiTestObj.CatMDevices))
+	HTML.CreateHtmlHeader(CiTestObj.ADBIPAddress)
 elif re.match('^FinalizeHtml$', mode, re.IGNORECASE):
-	CiTestObj.CreateHtmlFooter(CiTestObj.finalStatus)
+	HTML.CreateHtmlFooter(CiTestObj.finalStatus)
 elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE):
 	if re.match('^TesteNB$', mode, re.IGNORECASE):
 		if RAN.GeteNBIPAddress() == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '' or EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '':
 			GenericHelp(Version)
 			if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or EPC.GetType() == '':
 				EPCSrvHelp(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath(), EPC.GetType())
-		# Gabriele: other if conditions relevant to eNB etc. to be added	
+			if RAN.GetranRepository() == '':
+				GitSrvHelp(RAN.GetranRepository(),RAN.GetranBranch(),RAN.GetranCommitID(),RAN.GetranAllowMerge(),RAN.GetranTargetBranch())
+			if RAN.GeteNBIPAddress() == ''  or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '':
+				eNBSrvHelp(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath())
 			sys.exit('Insufficient Parameter')
 
 		if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'):
@@ -4628,8 +3582,10 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
 	exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='')
 	requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='')
 	if (CiTestObj.nbTestXMLfiles == 1):
-		CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0'))
-		CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0'))
+		HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-0'))
+		HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabName',default='Test-0'))
+		#CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0'))
+		#CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0'))
 		repeatCount = xmlRoot.findtext('repeatCount',default='1')
 		CiTestObj.repeatCounts.append(int(repeatCount))
 	all_tests=xmlRoot.findall('testCase')
@@ -4671,26 +3627,38 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
 
 	signal.signal(signal.SIGUSR1, receive_signal)
 
-	CiTestObj.CreateHtmlTabHeader()
+	if (CiTestObj.ADBIPAddress != 'none'):
+		terminate_ue_flag = False
+		CiTestObj.GetAllUEDevices(terminate_ue_flag)
+		CiTestObj.GetAllCatMDevices(terminate_ue_flag)
+	else:
+		CiTestObj.UEDevices.append('OAI-UE')
+	HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices))
+	HTML.CreateHtmlTabHeader()
 
 	CiTestObj.FailReportCnt = 0
-	CiTestObj.prematureExit = True
+	RAN.SetprematureExit(True)
 	CiTestObj.startTime = int(round(time.time() * 1000))
-	while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and CiTestObj.prematureExit:
-		CiTestObj.prematureExit = False
+	HTML.SetstartTime(CiTestObj.startTime)
+	while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.GetprematureExit():
+		RAN.SetprematureExit(False)
 		# At every iteratin of the retry loop, a separator will be added
-		CiTestObj.CreateHtmlRetrySeparator()
+		# pass CiTestObj.FailReportCnt as parameter of HTML.CreateHtmlRetrySeparator
+		HTML.CreateHtmlRetrySeparator(CiTestObj.FailReportCnt)
 		for test_case_id in todo_tests:
-			if CiTestObj.prematureExit:
+			if RAN.GetprematureExit():
 				break
 			for test in all_tests:
-				if CiTestObj.prematureExit:
+				if RAN.GetprematureExit():
 					break
 				id = test.get('id')
 				if test_case_id != id:
 					continue
 				CiTestObj.testCase_id = id
+				RAN.SettestCase_id(CiTestObj.testCase_id)
+				HTML.SettestCase_id(CiTestObj.testCase_id)
 				CiTestObj.desc = test.findtext('desc')
+				HTML.Setdesc(CiTestObj.desc)
 				action = test.findtext('class')
 				if (CheckClassValidity(action, id) == False):
 					continue
@@ -4705,6 +3673,10 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
 				elif action == 'WaitEndBuild_eNB':
 					RAN.WaitBuildeNBisFinished()
 				elif action == 'Initialize_eNB':
+					check_eNB = False
+					check_OAI_UE = False
+					RAN.SetpStatus(CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE))
+
 					RAN.InitializeeNB()
 				elif action == 'Terminate_eNB':
 					RAN.TerminateeNB()
@@ -4767,13 +3739,13 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
 				else:
 					sys.exit('Invalid action')
 		CiTestObj.FailReportCnt += 1
-	if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and CiTestObj.prematureExit:
+	if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.GetprematureExit():
 		logging.debug('Testsuite failed ' + str(CiTestObj.FailReportCnt) + ' time(s)')
-		CiTestObj.CreateHtmlTabFooter(False)
+		HTML.CreateHtmlTabFooter(False)
 		sys.exit('Failed Scenario')
 	else:
 		logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)')
-		CiTestObj.CreateHtmlTabFooter(True)
+		HTML.CreateHtmlTabFooter(True)
 else:
 	GenericHelp(Version)
 	sys.exit('Invalid mode')
diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py
index 21455573431..17461884e9f 100644
--- a/ci-scripts/ran.py
+++ b/ci-scripts/ran.py
@@ -11,11 +11,47 @@ from multiprocessing import Process, Lock, SimpleQueue
 #-----------------------------------------------------------
 # OAI Testing modules
 #-----------------------------------------------------------
-import sshconnection as mySSH
-#from sshconnection import mySSHConnection as mySSH
+import sshconnection as SSH
+import epc 
 import helpreadme as HELP
 import constants as CONST
+import html as HTML
 
+EPC = epc.EPCManagement()
+
+ALL_PROCESSES_OK = CONST.ALL_PROCESSES_OK
+ENB_PROCESS_FAILED = CONST.ENB_PROCESS_FAILED
+ENB_PROCESS_OK = CONST.ENB_PROCESS_OK
+ENB_PROCESS_SEG_FAULT = CONST.ENB_PROCESS_SEG_FAULT
+ENB_PROCESS_ASSERTION = CONST.ENB_PROCESS_ASSERTION
+ENB_PROCESS_REALTIME_ISSUE = CONST.ENB_PROCESS_REALTIME_ISSUE
+ENB_PROCESS_NOLOGFILE_TO_ANALYZE = CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE
+ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED
+HSS_PROCESS_FAILED = CONST.HSS_PROCESS_FAILED
+HSS_PROCESS_OK = CONST.HSS_PROCESS_OK
+MME_PROCESS_FAILED = CONST.MME_PROCESS_FAILED
+MME_PROCESS_OK = CONST.MME_PROCESS_OK
+SPGW_PROCESS_FAILED = CONST.SPGW_PROCESS_FAILED
+SPGW_PROCESS_OK = CONST.SPGW_PROCESS_OK
+UE_IP_ADDRESS_ISSUE = CONST.UE_IP_ADDRESS_ISSUE
+OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE
+OAI_UE_PROCESS_COULD_NOT_SYNC = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC
+OAI_UE_PROCESS_ASSERTION = CONST.OAI_UE_PROCESS_ASSERTION
+OAI_UE_PROCESS_FAILED = CONST.OAI_UE_PROCESS_FAILED
+OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE
+OAI_UE_PROCESS_SEG_FAULT = CONST.OAI_UE_PROCESS_SEG_FAULT
+OAI_UE_PROCESS_OK = CONST.OAI_UE_PROCESS_OK
+
+UE_STATUS_DETACHED = CONST.UE_STATUS_DETACHED
+UE_STATUS_DETACHING = CONST.UE_STATUS_DETACHING
+UE_STATUS_ATTACHING = CONST.UE_STATUS_ATTACHING
+UE_STATUS_ATTACHED = CONST.UE_STATUS_ATTACHED
+
+X2_HO_REQ_STATE__IDLE = CONST.X2_HO_REQ_STATE__IDLE
+X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = CONST.X2_HO_REQ_STATE__TARGET_RECEIVES_REQ
+X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = CONST.X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE
+X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = CONST.X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ
+X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = CONST.X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK
 
 #-----------------------------------------------------------
 # Class Declaration
@@ -45,7 +81,7 @@ class RANManagement():
 		#self.ADBUserName = ''
 		#self.ADBPassword = ''
 		#self.ADBCentralized = True
-		#self.testCase_id = ''
+		self.testCase_id = ''
 		#self.testXMLfiles = []
 		#self.nbTestXMLfiles = 0
 		#self.desc = ''
@@ -110,12 +146,19 @@ class RANManagement():
 		#self.Build_OAI_UE_args = ''
 		#self.Initialize_OAI_UE_args = ''
 		#self.clean_repository = True
-		#self.flexranCtrlInstalled = False
-		#self.flexranCtrlStarted = False
+		self.flexranCtrlInstalled = False
+		self.flexranCtrlStarted = False
 		#self.expectedNbOfConnectedUEs = 0
 		#self.startTime = 0
 
-
+	def SettestCase_id(self,tcid):
+		self.testCase_id = tcid
+	def SetflexranCtrlInstalled(self,fxrctin):
+		self.flexranCtrlInstalled = fxrctin
+	def SetflexranCtrlStarted(self,fxrctst):
+		self.flexranCtrlStarted = fxrctst
+	def SetpStatus(self, pSt):
+		self.pStatus = pSt
 	def SetranRepository(self, repository):
 		self.ranRepository = repository
 	def GetranRepository(self):
@@ -241,14 +284,22 @@ class RANManagement():
 	def GeteNB2SourceCodePath(self):
 		return self.eNB2SourceCodePath
 
+	def SetprematureExit(self, premex):
+		self.prematureExit = premex
+	def GetprematureExit(self):
+		return self.prematureExit
 
 
 	def BuildeNB(self):
+		myHTML = HTML.HTMLManagement()
 		if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
 			GenericHelp(Version)
 			sys.exit('Insufficient Parameter')
 		if self.eNB_serverId == '0':
+			#checkpoint enB_serverId
 			lIpAddr = self.eNBIPAddress
+			print(self.eNBIPAddress + 'self.eNBIPAddress')
+			print(lIpAddr + 'lIpAddr')
 			lUserName = self.eNBUserName
 			lPassWord = self.eNBPassword
 			lSourcePath = self.eNBSourceCodePath
@@ -262,11 +313,12 @@ class RANManagement():
 			lUserName = self.eNB2UserName
 			lPassWord = self.eNB2Password
 			lSourcePath = self.eNB2SourceCodePath
+		print(lIpAddr + 'just before the error')
 		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
 			GenericHelp(Version)
 			sys.exit('Insufficient Parameter')
 		mySSH = SSH.SSHConnection()
-                mySSH.open(lIpAddr, lUserName, lPassWord)
+		mySSH.open(lIpAddr, lUserName, lPassWord)
 		# Check if we build an 5G-NR gNB or an LTE eNB
 		result = re.search('--gNB', self.Build_eNB_args)
 		if result is not None:
@@ -316,7 +368,7 @@ class RANManagement():
 						mismatch = True
 				if not mismatch:
 					mySSH.close()
-					self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK)
+					myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK)
 					return
 
 		mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30)
@@ -342,7 +394,7 @@ class RANManagement():
 			mySSH.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5)
 			mySSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5)
 			mySSH.close()
-			self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK)
+			myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK)
 			self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id
 			return
 		mySSH.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500)
@@ -369,7 +421,7 @@ class RANManagement():
 		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
 			GenericHelp(Version)
 			sys.exit('Insufficient Parameter')
-                mySSH = SSH.SSHConnection()
+		mySSH = SSH.SSHConnection()
 		mySSH.open(lIpAddr, lUserName, lPassWord)
 		count = 40
 		buildOAIprocess = True
@@ -384,8 +436,9 @@ class RANManagement():
 		self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)])
 
 	def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId):
+		myHTML = HTML.HTMLManagement()
 		mySSH = SSH.SSHConnection()
-                mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3)
+		mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3)
 		mySSH.command('ls ran_build/build', '\$', 3)
 		mySSH.command('ls ran_build/build', '\$', 3)
 		if self.air_interface == 'nr':
@@ -432,15 +485,16 @@ class RANManagement():
 
 		if buildStatus:
 			logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m')
-			self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK)
+			myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK)
 		else:
 			logging.error('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Failed\u001B[0m')
-			self.CreateHtmlTestRow(self.Build_eNB_args, 'KO', ALL_PROCESSES_OK)
-			self.CreateHtmlTabFooter(False)
+			myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'KO', ALL_PROCESSES_OK)
+			myHTML.CreateHtmlTabFooter(False)
 			sys.exit(1)
 
 
 	def InitializeeNB(self):
+		myHTML = HTML.HTMLManagement()
 		if self.eNB_serverId == '0':
 			lIpAddr = self.eNBIPAddress
 			lUserName = self.eNBUserName
@@ -459,13 +513,13 @@ class RANManagement():
 		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
 			GenericHelp(Version)
 			sys.exit('Insufficient Parameter')
-                mySSH = SSH.SSHConnection()
-		check_eNB = False
-		check_OAI_UE = False
-		pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
-		if (pStatus < 0):
-			self.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', pStatus)
-			self.CreateHtmlTabFooter(False)
+		mySSH = SSH.SSHConnection()
+		#check_eNB = False
+		#check_OAI_UE = False
+		#pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
+		if (self.pStatus < 0):
+			myHTML.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', self.pStatus)
+			myHTML.CreateHtmlTabFooter(False)
 			sys.exit(1)
 		# 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))
@@ -476,7 +530,7 @@ class RANManagement():
 			if result is not None:
 				eth_interface = result.group('eth_interface')
 				logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m')
-				EPC.Get_PcapFileName()  = 'enb_' + self.testCase_id + '_s1log.pcap'
+				EPC.Set_PcapFileName('enb_' + self.testCase_id + '_s1log.pcap')
 				mySSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f /tmp/' + EPC.Get_PcapFileName() , '\$', 5)
 				mySSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.Get_PcapFileName()  + ' > /tmp/tshark.log 2>&1 &', EPC.GetUserName(), 5)
 			mySSH.close()
@@ -566,7 +620,7 @@ class RANManagement():
 				mySSH.close()
 				doLoop = False
 				logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m')
-				self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK)
+				myHTML.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK)
 				# 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:
@@ -616,7 +670,7 @@ class RANManagement():
 			self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId)
 
 		mySSH.close()
-		self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK)
+		myHTML.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK)
 		logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m')
 
 
@@ -640,7 +694,7 @@ class RANManagement():
 				lIpAddr = self.eNBIPAddress
 				lUserName = self.eNBUserName
 				lPassWord = self.eNBPassword
-                        mySSH = SSH.SSHConnection()
+			mySSH = SSH.SSHConnection()
 			mySSH.open(lIpAddr, lUserName, lPassWord)
 			mySSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + '-softmodem | grep -v grep', '\$', 5)
 			result = re.search(self.air_interface + '-softmodem', mySSH.getBefore())
@@ -656,6 +710,7 @@ class RANManagement():
 
 
 	def TerminateeNB(self):
+		myHTML = HTML.HTMLManagement()
 		if self.eNB_serverId == '0':
 			lIpAddr = self.eNBIPAddress
 			lUserName = self.eNBUserName
@@ -674,7 +729,7 @@ class RANManagement():
 		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
 			GenericHelp(Version)
 			sys.exit('Insufficient Parameter')
-                mySSH = SSH.SSHConnection()
+		mySSH = SSH.SSHConnection()
 		mySSH.open(lIpAddr, lUserName, lPassWord)
 		mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5)
 		if self.air_interface == 'lte':
@@ -721,7 +776,7 @@ class RANManagement():
 			mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/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)
+			myHTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 			self.eNBLogFiles[int(self.eNB_instance)] = ''
 		else:
 			analyzeFile = False
@@ -734,7 +789,7 @@ class RANManagement():
 				if (copyin_res == -1):
 					logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m')
 					self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!'
-					self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE)
+					myHTML.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE)
 					self.eNBmbmsEnables[int(self.eNB_instance)] = False
 					return
 				if self.eNB_serverId != '0':
@@ -742,20 +797,20 @@ class RANManagement():
 				logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + fileToAnalyze)
 				logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze)
 				if (logStatus < 0):
-					self.CreateHtmlTestRow('N/A', 'KO', logStatus)
+					myHTML.CreateHtmlTestRow('N/A', 'KO', logStatus)
 					self.preamtureExit = True
 					self.eNBmbmsEnables[int(self.eNB_instance)] = False
 					return
 				else:
-					self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+					myHTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 			else:
-				self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+				myHTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 		self.eNBmbmsEnables[int(self.eNB_instance)] = False
 		self.eNBstatuses[int(self.eNB_instance)] = -1
 
 
 	def LogCollecteNB(self):
-                mySSH = SSH.SSHConnection()
+		mySSH = SSH.SSHConnection()
 		mySSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
 		mySSH.command('cd ' + self.eNBSourceCodePath, '\$', 5)
 		mySSH.command('cd cmake_targets', '\$', 5)
@@ -763,3 +818,260 @@ class RANManagement():
 		mySSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60)
 		mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5)
 		mySSH.close()
+
+
+	def AnalyzeLogFile_eNB(self, eNBlogFile):
+		if (not os.path.isfile('./' + eNBlogFile)):
+			return -1
+		enb_log_file = open('./' + eNBlogFile, 'r')
+		exitSignalReceived = False
+		foundAssertion = False
+		msgAssertion = ''
+		msgLine = 0
+		foundSegFault = False
+		foundRealTimeIssue = False
+		rrcSetupComplete = 0
+		rrcReleaseRequest = 0
+		rrcReconfigRequest = 0
+		rrcReconfigComplete = 0
+		rrcReestablishRequest = 0
+		rrcReestablishComplete = 0
+		rrcReestablishReject = 0
+		rlcDiscardBuffer = 0
+		rachCanceledProcedure = 0
+		uciStatMsgCount = 0
+		pdcpFailure = 0
+		ulschFailure = 0
+		cdrxActivationMessageCount = 0
+		dropNotEnoughRBs = 0
+		mbmsRequestMsg = 0
+		self.htmleNBFailureMsg = ''
+		isRRU = False
+		isSlave = False
+		slaveReceivesFrameResyncCmd = False
+		X2HO_state = X2_HO_REQ_STATE__IDLE
+		X2HO_inNbProcedures = 0
+		X2HO_outNbProcedures = 0
+		for line in enb_log_file.readlines():
+			if X2HO_state == X2_HO_REQ_STATE__IDLE:
+				result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line))
+				if result is not None:
+					X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ
+				result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line))
+				if result is not None:
+					X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK
+			if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ:
+				result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line))
+				if result is not None:
+					X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE
+			if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE:
+				result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line))
+				if result is not None:
+					X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ
+			if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ:
+				result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line))
+				if result is not None:
+					X2HO_state = X2_HO_REQ_STATE__IDLE
+					X2HO_inNbProcedures += 1
+			if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK:
+				result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line))
+				if result is not None:
+					X2HO_state = X2_HO_REQ_STATE__IDLE
+					X2HO_outNbProcedures += 1
+
+			if self.eNBOptions[int(self.eNB_instance)] != '':
+				res1 = re.search('max_rxgain (?P<requested_option>[0-9]+)', self.eNBOptions[int(self.eNB_instance)])
+				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.eNBOptions[int(self.eNB_instance)] + '\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.eNBOptions[int(self.eNB_instance)] + '\n\n'
+			result = re.search('Exiting OAI softmodem', str(line))
+			if result is not None:
+				exitSignalReceived = True
+			result = re.search('[Ss]egmentation [Ff]ault', str(line))
+			if result is not None and not exitSignalReceived:
+				foundSegFault = True
+			result = re.search('[Cc]ore [dD]ump', str(line))
+			if result is not None and not exitSignalReceived:
+				foundSegFault = True
+			result = re.search('./ran_build/build/lte-softmodem', str(line))
+			if result is not None and not exitSignalReceived:
+				foundSegFault = True
+			result = re.search('[Aa]ssertion', str(line))
+			if result is not None and not exitSignalReceived:
+				foundAssertion = True
+			result = re.search('LLL', str(line))
+			if result is not None and not exitSignalReceived:
+				foundRealTimeIssue = True
+			if foundAssertion and (msgLine < 3):
+				msgLine += 1
+				msgAssertion += str(line)
+			result = re.search('Setting function for RU', str(line))
+			if result is not None:
+				isRRU = True
+			if isRRU:
+				result = re.search('RU 0 is_slave=yes', str(line))
+				if result is not None:
+					isSlave = True
+				if isSlave:
+					result = re.search('Received RRU_frame_resynch command', str(line))
+					if result is not None:
+						slaveReceivesFrameResyncCmd = True
+			result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line))
+			if result is not None:
+				rrcSetupComplete += 1
+			result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line))
+			if result is not None:
+				rrcReleaseRequest += 1
+			result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line))
+			if result is not None:
+				rrcReconfigRequest += 1
+			result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line))
+			if result is not None:
+				rrcReconfigComplete += 1
+			result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line))
+			if result is not None:
+				rrcReestablishRequest += 1
+			result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line))
+			if result is not None:
+				rrcReestablishComplete += 1
+			result = re.search('LTE_RRCConnectionReestablishmentReject', str(line))
+			if result is not None:
+				rrcReestablishReject += 1
+			result = re.search('CDRX configuration activated after RRC Connection', str(line))
+			if result is not None:
+				cdrxActivationMessageCount += 1
+			result = re.search('uci->stat', str(line))
+			if result is not None:
+				uciStatMsgCount += 1
+			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
+			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
+			result = re.search('dropping, not enough RBs', str(line))
+			if result is not None:
+				dropNotEnoughRBs += 1
+			if self.eNBmbmsEnables[int(self.eNB_instance)]:
+				result = re.search('MBMS USER-PLANE.*Requesting.*bytes from RLC', str(line))
+				if result is not None:
+					mbmsRequestMsg += 1
+		enb_log_file.close()
+		logging.debug('   File analysis completed')
+		self.htmleNBFailureMsg = ''
+		if self.air_interface() == 'lte':
+			nodeB_prefix = 'e'
+		else:
+			nodeB_prefix = 'g'
+		if uciStatMsgCount > 0:
+			statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)'
+			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
+			self.htmleNBFailureMsg += statMsg + '\n'
+		if pdcpFailure > 0:
+			statMsg = nodeB_prefix + 'NB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)'
+			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
+			self.htmleNBFailureMsg += statMsg + '\n'
+		if ulschFailure > 0:
+			statMsg = nodeB_prefix + 'NB showed ' + str(ulschFailure) + ' "ULSCH in error in round" message(s)'
+			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
+			self.htmleNBFailureMsg += statMsg + '\n'
+		if dropNotEnoughRBs > 0:
+			statMsg = 'eNB showed ' + str(dropNotEnoughRBs) + ' "dropping, not enough RBs" message(s)'
+			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
+			self.htmleNBFailureMsg += statMsg + '\n'
+		if rrcSetupComplete > 0:
+			rrcMsg = nodeB_prefix + 'NB completed ' + str(rrcSetupComplete) + ' 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 = nodeB_prefix + 'NB 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 = nodeB_prefix + 'NB 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 = nodeB_prefix + 'NB 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'
+		if self.eNBmbmsEnables[int(self.eNB_instance)]:
+			if mbmsRequestMsg > 0:
+				rrcMsg = 'eNB requested ' + str(mbmsRequestMsg) + ' times the RLC for MBMS USER-PLANE'
+				logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
+				self.htmleNBFailureMsg += rrcMsg + '\n'
+		if X2HO_inNbProcedures > 0:
+			rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)'
+			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
+			self.htmleNBFailureMsg += rrcMsg + '\n'
+		if X2HO_outNbProcedures > 0:
+			rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)'
+			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
+			self.htmleNBFailureMsg += rrcMsg + '\n'
+		if self.eNBOptions[int(self.eNB_instance)] != '':
+			res1 = re.search('drx_Config_present prSetup', self.eNBOptions[int(self.eNB_instance)])
+			if res1 is not None:
+				if cdrxActivationMessageCount > 0:
+					rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)'
+					logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
+					self.htmleNBFailureMsg += rrcMsg + '\n'
+				else:
+					rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration'
+					logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m')
+					self.htmleNBFailureMsg += rrcMsg + '\n'
+		if rachCanceledProcedure > 0:
+			rachMsg = nodeB_prefix + 'NB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)'
+			logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m')
+			self.htmleNBFailureMsg += rachMsg + '\n'
+		if isRRU:
+			if isSlave:
+				if slaveReceivesFrameResyncCmd:
+					rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU'
+					logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m')
+					self.htmleNBFailureMsg += rruMsg + '\n'
+				else:
+					rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU'
+					logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m')
+					self.htmleNBFailureMsg += rruMsg + '\n'
+					self.prematureExit(True)
+					return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED
+		if foundSegFault:
+			logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with a Segmentation Fault! \u001B[0m')
+			return ENB_PROCESS_SEG_FAULT
+		if foundAssertion:
+			logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with an assertion! \u001B[0m')
+			self.htmleNBFailureMsg += msgAssertion
+			return ENB_PROCESS_ASSERTION
+		if foundRealTimeIssue:
+			logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m')
+			self.htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n'
+			#return ENB_PROCESS_REALTIME_ISSUE
+		if rlcDiscardBuffer > 0:
+			rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)'
+			logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m')
+			self.htmleNBFailureMsg += rlcMsg + '\n'
+			return ENB_PROCESS_REALTIME_ISSUE
+		return 0
diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py
index 6103bf4f0fc..df1ada48348 100644
--- a/ci-scripts/sshconnection.py
+++ b/ci-scripts/sshconnection.py
@@ -3,7 +3,8 @@
 #-----------------------------------------------------------
 import pexpect          # pexpect
 import logging
-
+import time             # sleep
+import re
 #-----------------------------------------------------------
 # Class Declaration
 #-----------------------------------------------------------
@@ -69,7 +70,7 @@ class SSHConnection():
 			logging.debug('\u001B[1;37;41m Unexpected EOF \u001B[0m')
 			logging.debug('Expected Line : ' + expectedline)
 			logging.debug(str(self.ssh.before))
-                        sys.exit(self.sshresponse)
+			sys.exit(self.sshresponse)
 		elif self.sshresponse == 2:
 			logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m')
 			logging.debug('Expected Line : ' + expectedline)
diff --git a/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml b/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml
index 680f09c435e..611492b0bcd 100644
--- a/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml
+++ b/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml
@@ -24,7 +24,7 @@
 	<htmlTabRef>test-lte-m-10-tm1</htmlTabRef>
 	<htmlTabName>Test-LTE-M-10MHz-TM1</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>
-	<repeatCount>2</repeatCount>
+	<repeatCount>1</repeatCount>
 	<TestCaseRequestedList>
  030201
  040102
diff --git a/ci-scripts/xml_files/x2ho_enb_usrp210_band13_simple_test.xml b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_simple_test.xml
new file mode 100644
index 00000000000..8d813a8e2c0
--- /dev/null
+++ b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_simple_test.xml
@@ -0,0 +1,189 @@
+<!--
+
+ 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
+
+ 030101 000002 030102 040301 040501 040601 040641 050401 000002 040502 040602 040642 050402 000002 040503 040603 040643 040401 040201 030201 030202
+-->
+<testCaseList>
+	<htmlTabRef>test-x2-ho-05-tm1</htmlTabRef>
+	<htmlTabName>Test-X2-HO-FDD-05MHz-TM1</htmlTabName>
+	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>1</repeatCount>
+	<TestCaseRequestedList>
+ 030201 
+ 040101
+ 030101 040301 040501 040401 040201 030201 
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="000001">
+		<class>IdleSleep</class>
+		<desc>Waiting for 60 seconds</desc>
+		<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
+	</testCase>
+
+	<testCase id="000002">
+		<class>IdleSleep</class>
+		<desc>Waiting for 10 seconds</desc>
+		<idle_sleep_time_in_sec>10</idle_sleep_time_in_sec>
+	</testCase>
+
+	<testCase id="050102">
+		<class>Initialize_FlexranCtrl</class>
+		<desc>Starting Flexran Controller</desc>
+	</testCase>
+
+	<testCase id="050202">
+		<class>Terminate_FlexranCtrl</class>
+		<desc>Stopping Flexran Controller</desc>
+	</testCase>
+
+	<testCase id="030101">
+		<class>Initialize_eNB</class>
+		<desc>Initialize Master eNB (FDD/Band7/5MHz)</desc>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf --eNBs.[0].enable_x2 no</Initialize_eNB_args>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+	</testCase>
+
+	<testCase id="030102">
+		<class>Initialize_eNB</class>
+		<desc>Initialize Slave eNB (FDD/Band7/5MHz)</desc>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf</Initialize_eNB_args>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+	</testCase>
+
+	<testCase id="030201">
+		<class>Terminate_eNB</class>
+		<desc>Terminate Master eNB</desc>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+	</testCase>
+
+	<testCase id="030202">
+		<class>Terminate_eNB</class>
+		<desc>Terminate Slave eNB</desc>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+	</testCase>
+
+	<testCase id="040101">
+		<class>Initialize_UE</class>
+		<desc>Initialize UE</desc>
+	</testCase>
+
+	<testCase id="040201">
+		<class>Terminate_UE</class>
+		<desc>Terminate UE</desc>
+	</testCase>
+
+	<testCase id="040301">
+		<class>Attach_UE</class>
+		<desc>Attach UE</desc>
+	</testCase>
+
+	<testCase id="040401">
+		<class>Detach_UE</class>
+		<desc>Detach UE</desc>
+	</testCase>
+
+	<testCase id="040501">
+		<class>Ping</class>
+		<desc>ping (5MHz - 20 sec)</desc>
+		<ping_args>-c 20</ping_args>
+		<ping_packetloss_threshold>5</ping_packetloss_threshold>
+	</testCase>
+
+	<testCase id="040502">
+		<class>Ping</class>
+		<desc>ping (5MHz - 20 sec)</desc>
+		<ping_args>-c 20</ping_args>
+		<ping_packetloss_threshold>5</ping_packetloss_threshold>
+	</testCase>
+
+	<testCase id="040503">
+		<class>Ping</class>
+		<desc>ping (5MHz - 20 sec)</desc>
+		<ping_args>-c 20</ping_args>
+		<ping_packetloss_threshold>5</ping_packetloss_threshold>
+	</testCase>
+
+	<testCase id="040601">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - DL/8Mbps/UDP)(30 sec)</desc>
+		<iperf_args>-u -b 8M -t 30 -i 1</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="040602">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - DL/8Mbps/UDP)(30 sec)</desc>
+		<iperf_args>-u -b 8M -t 30 -i 1</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="040603">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - DL/8Mbps/UDP)(30 sec)</desc>
+		<iperf_args>-u -b 8M -t 30 -i 1</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="040641">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - UL/5Mbps/UDP)(30 sec)</desc>
+		<iperf_args>-u -b 5M -t 30 -i 1 -R</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="040642">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - UL/5Mbps/UDP)(30 sec)</desc>
+		<iperf_args>-u -b 5M -t 30 -i 1 -R</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="040643">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - UL/5Mbps/UDP)(30 sec)</desc>
+		<iperf_args>-u -b 5M -t 30 -i 1 -R</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="050401">
+		<class>Perform_X2_Handover</class>
+		<desc>Doing a Flexran-Controlled X2 Handover</desc>
+		<x2_ho_options>network</x2_ho_options>
+	</testCase>
+
+	<testCase id="050402">
+		<class>Perform_X2_Handover</class>
+		<desc>Doing a Flexran-Controlled X2 Handover</desc>
+		<x2_ho_options>network</x2_ho_options>
+	</testCase>
+
+</testCaseList>
-- 
GitLab