Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG UE
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Michael Black
OpenXG UE
Commits
43591877
Commit
43591877
authored
Jun 18, 2019
by
Raphael Defosseux
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
CI: a few cosmetics fixes on python
Signed-off-by:
Raphael Defosseux
<
raphael.defosseux@eurecom.fr
>
parent
b0b0b70a
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
43 additions
and
47 deletions
+43
-47
ci-scripts/main.py
ci-scripts/main.py
+43
-47
No files found.
ci-scripts/main.py
View file @
43591877
# dummy commit
#/*
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# * contributor license agreements. See the NOTICE file distributed with
...
...
@@ -599,6 +598,10 @@ class SSHConnection():
if
self
.
UEIPAddress
==
''
or
self
.
UEUserName
==
''
or
self
.
UEPassword
==
''
or
self
.
UESourceCodePath
==
''
:
Usage
()
sys
.
exit
(
'Insufficient Parameter'
)
if
self
.
air_interface
==
'lte'
:
UE_prefix
=
''
else
:
UE_prefix
=
'NR '
#initialize_OAI_UE_flag = True
#pStatus = self.CheckOAIUEProcessExist(initialize_OAI_UE_flag)
#if (pStatus < 0):
...
...
@@ -608,7 +611,7 @@ class SSHConnection():
self
.
open
(
self
.
UEIPAddress
,
self
.
UEUserName
,
self
.
UEPassword
)
# b2xx_fx3_utils reset procedure
self
.
command
(
'echo '
+
self
.
UEPassword
+
' | sudo -S uhd_find_devices'
,
'\$'
,
30
)
result
=
re
.
search
(
'type:
n3xx
'
,
str
(
self
.
ssh
.
before
))
result
=
re
.
search
(
'type:
b200
'
,
str
(
self
.
ssh
.
before
))
if
result
is
not
None
:
pass
logging
.
debug
(
'Found a B2xx device --> resetting it'
)
...
...
@@ -624,10 +627,6 @@ class SSHConnection():
self
.
command
(
'echo "ulimit -c unlimited && ./'
+
self
.
air_interface
+
'-uesoftmodem '
+
self
.
Initialize_OAI_UE_args
+
'" > ./my-lte-uesoftmodem-run'
+
str
(
self
.
UE_instance
)
+
'.sh'
,
'\$'
,
5
)
self
.
command
(
'chmod 775 ./my-lte-uesoftmodem-run'
+
str
(
self
.
UE_instance
)
+
'.sh'
,
'\$'
,
5
)
self
.
command
(
'echo '
+
self
.
UEPassword
+
' | sudo -S rm -Rf '
+
self
.
UESourceCodePath
+
'/cmake_targets/ue_'
+
self
.
testCase_id
+
'.log'
,
'\$'
,
5
)
#to use daemon on CentOS we need to source the function
#linux_distro = platform.linux_distribution()[0]
#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
#self.command('source /etc/init.d/functions', '\$', 5)
#use nohup instead of daemon
self
.
command
(
'echo $USER; nohup sudo ./my-lte-uesoftmodem-run'
+
str
(
self
.
UE_instance
)
+
'.sh'
+
' > '
+
self
.
UESourceCodePath
+
'/cmake_targets/ue_'
+
self
.
testCase_id
+
'.log '
+
' 2>&1 &'
,
self
.
UEUserName
,
5
)
#self.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/ran_build/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5)
...
...
@@ -641,7 +640,7 @@ class SSHConnection():
if
(
loopCounter
==
0
):
self
.
close
()
doLoop
=
False
logging
.
error
(
'
\u001B
[1;37;41m UE logging system did not show got sync!
\u001B
[0m'
)
logging
.
error
(
'
\u001B
[1;37;41m
'
+
UE_prefix
+
'
UE logging system did not show got sync!
\u001B
[0m'
)
self
.
CreateHtmlTestRow
(
self
.
Initialize_OAI_UE_args
,
'KO'
,
ALL_PROCESSES_OK
,
'OAI UE'
)
self
.
CreateHtmlTabFooter
(
False
)
sys
.
exit
(
1
)
...
...
@@ -656,7 +655,7 @@ class SSHConnection():
else
:
doLoop
=
False
self
.
CreateHtmlTestRow
(
self
.
Initialize_OAI_UE_args
,
'OK'
,
ALL_PROCESSES_OK
,
'OAI UE'
)
logging
.
debug
(
'
\u001B
[1m Initialize OAI UE Completed
\u001B
[0m'
)
logging
.
debug
(
'
\u001B
[1m Initialize OAI
'
+
UE_prefix
+
'
UE Completed
\u001B
[0m'
)
self
.
close
()
def
InitializeOAIeNB
(
self
):
...
...
@@ -671,6 +670,10 @@ class SSHConnection():
# sys.exit(1)
self
.
open
(
self
.
eNBIPAddress
,
self
.
eNBUserName
,
self
.
eNBPassword
)
self
.
command
(
'cd '
+
self
.
eNBSourceCodePath
,
'\$'
,
5
)
if
self
.
air_interface
==
'lte'
:
nodeB_prefix
=
'e'
else
:
nodeB_prefix
=
'g'
# Initialize_OAI_eNB_args usually start with -C and followed by the location in repository
#full_config_file = self.Initialize_OAI_eNB_args.replace('-O ','')
#extIdx = full_config_file.find('.conf')
...
...
@@ -702,10 +705,6 @@ class SSHConnection():
self
.
command
(
'echo "ulimit -c unlimited && ./'
+
self
.
air_interface
+
'-softmodem '
+
self
.
Initialize_OAI_eNB_args
+
'|& tee '
+
self
.
eNBSourceCodePath
+
'/cmake_targets/'
+
self
.
eNBLogFile
+
'" > ./my-lte-softmodem-run'
+
str
(
self
.
eNB_instance
)
+
'.sh'
,
'\$'
,
5
)
self
.
command
(
'chmod 775 ./my-lte-softmodem-run'
+
str
(
self
.
eNB_instance
)
+
'.sh'
,
'\$'
,
5
)
self
.
command
(
'echo '
+
self
.
eNBPassword
+
' | sudo -S rm -Rf '
+
self
.
eNBSourceCodePath
+
'/cmake_targets/enb_'
+
self
.
testCase_id
+
'.log'
,
'\$'
,
5
)
#to use daemon on CentOS we need to source the function
#linux_distro = platform.linux_distribution()[0]
#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
#self.command('source /etc/init.d/functions', '\$', 5)
#use nohup instead of daemon
self
.
command
(
'echo $USER; nohup sudo ./my-lte-softmodem-run'
+
str
(
self
.
eNB_instance
)
+
'.sh'
+
' > '
+
self
.
eNBSourceCodePath
+
'/cmake_targets/enb_'
+
self
.
testCase_id
+
'.log'
+
' 2>&1 &'
,
self
.
eNBUserName
,
5
)
#self.command('echo ' + self.eNBPassword + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + self.eNBSourceCodePath + '/cmake_targets/ran_build/build -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
...
...
@@ -713,7 +712,6 @@ class SSHConnection():
self
.
command
(
'cd ../..'
,
'\$'
,
5
)
doLoop
=
True
loopCounter
=
10
print
(
'gNB log file: '
+
self
.
eNBLogFile
)
while
(
doLoop
):
loopCounter
=
loopCounter
-
1
if
(
loopCounter
==
0
):
...
...
@@ -723,7 +721,7 @@ class SSHConnection():
# self.command('killall --signal SIGKILL record', '\$', 5)
self
.
close
()
doLoop
=
False
logging
.
error
(
'
\u001B
[1;37;41m
e
NB logging system did not show got sync!
\u001B
[0m'
)
logging
.
error
(
'
\u001B
[1;37;41m
'
+
nodeB_prefix
+
'
NB logging system did not show got sync!
\u001B
[0m'
)
self
.
CreateHtmlTestRow
(
self
.
Initialize_OAI_eNB_args
,
'KO'
,
ALL_PROCESSES_OK
,
'OAI eNB'
)
self
.
CreateHtmlTabFooter
(
False
)
## In case of T tracer recording, we need to kill tshark on EPC side
...
...
@@ -740,18 +738,14 @@ class SSHConnection():
# self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, pcap_log_file, self.eNBSourceCodePath + '/cmake_targets/.')
sys
.
exit
(
1
)
else
:
#print('current directory: ' + os.getcwd())
#self.command('pwd', '\$', 4)
#print('self.command pwd: ' + str(self.ssh.before))
self
.
command
(
'stdbuf -o0 cat '
+
self
.
eNBLogFile
+
' | egrep --text --color=never -i "wait|sync"'
,
'\$'
,
30
)
#print(self.ssh.before)
result
=
re
.
search
(
'got sync'
,
str
(
self
.
ssh
.
before
))
if
result
is
None
:
time
.
sleep
(
11
)
else
:
doLoop
=
False
self
.
CreateHtmlTestRow
(
self
.
Initialize_OAI_eNB_args
,
'OK'
,
ALL_PROCESSES_OK
,
'OAI eNB'
)
logging
.
debug
(
'
\u001B
[1m Initialize OAI
e
NB Completed
\u001B
[0m'
)
logging
.
debug
(
'
\u001B
[1m Initialize OAI
'
+
nodeB_prefix
+
'
NB Completed
\u001B
[0m'
)
self
.
close
()
def
checkDevTTYisUnlocked
(
self
):
...
...
@@ -2091,38 +2085,42 @@ class SSHConnection():
rachCanceledProcedure
+=
1
enb_log_file
.
close
()
self
.
htmleNBFailureMsg
=
''
if
self
.
air_interface
==
'lte'
:
nodeB_prefix
=
'e'
else
:
nodeB_prefix
=
'g'
if
uciStatMsgCount
>
0
:
statMsg
=
'e
NB showed '
+
str
(
uciStatMsgCount
)
+
' "uci->stat" message(s)'
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
=
'e
NB showed '
+
str
(
pdcpFailure
)
+
' "PDCP Out of Resources" message(s)'
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
=
'e
NB showed '
+
str
(
ulschFailure
)
+
' "ULSCH in error in round" message(s)'
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
rrcSetupRequest
>
0
or
rrcSetupComplete
>
0
:
rrcMsg
=
'e
NB requested '
+
str
(
rrcSetupRequest
)
+
' RRC Connection Setup(s)'
rrcMsg
=
nodeB_prefix
+
'
NB requested '
+
str
(
rrcSetupRequest
)
+
' RRC Connection Setup(s)'
logging
.
debug
(
'
\u001B
[1;30;43m '
+
rrcMsg
+
'
\u001B
[0m'
)
self
.
htmleNBFailureMsg
+=
rrcMsg
+
'
\n
'
rrcMsg
=
' -- '
+
str
(
rrcSetupComplete
)
+
' were completed'
logging
.
debug
(
'
\u001B
[1;30;43m '
+
rrcMsg
+
'
\u001B
[0m'
)
self
.
htmleNBFailureMsg
+=
rrcMsg
+
'
\n
'
if
rrcReleaseRequest
>
0
:
rrcMsg
=
'e
NB requested '
+
str
(
rrcReleaseRequest
)
+
' RRC Connection Release(s)'
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
=
'e
NB requested '
+
str
(
rrcReconfigRequest
)
+
' RRC Connection Reconfiguration(s)'
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
=
'e
NB requested '
+
str
(
rrcReestablishRequest
)
+
' RRC Connection Reestablishment(s)'
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'
...
...
@@ -2132,22 +2130,22 @@ class SSHConnection():
logging
.
debug
(
'
\u001B
[1;30;43m '
+
rrcMsg
+
'
\u001B
[0m'
)
self
.
htmleNBFailureMsg
+=
rrcMsg
+
'
\n
'
if
rachCanceledProcedure
>
0
:
rachMsg
=
'e
NB cancelled '
+
str
(
rachCanceledProcedure
)
+
' RA procedure(s)'
rachMsg
=
nodeB_prefix
+
'
NB cancelled '
+
str
(
rachCanceledProcedure
)
+
' RA procedure(s)'
logging
.
debug
(
'
\u001B
[1;30;43m '
+
rachMsg
+
'
\u001B
[0m'
)
self
.
htmleNBFailureMsg
+=
rachMsg
+
'
\n
'
if
foundSegFault
:
logging
.
debug
(
'
\u001B
[1;37;41m
e
NB ended with a Segmentation Fault!
\u001B
[0m'
)
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
e
NB ended with an assertion!
\u001B
[0m'
)
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
e
NB faced real time issues!
\u001B
[0m'
)
self
.
htmleNBFailureMsg
+=
'e
NB faced real time issues!
\n
'
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
=
'e
NB RLC discarded '
+
str
(
rlcDiscardBuffer
)
+
' buffer(s)'
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
...
...
@@ -2306,10 +2304,10 @@ class SSHConnection():
def
TerminateeNB
(
self
):
self
.
open
(
self
.
eNBIPAddress
,
self
.
eNBUserName
,
self
.
eNBPassword
)
self
.
command
(
'cd '
+
self
.
eNBSourceCodePath
+
'/cmake_targets'
,
'\$'
,
5
)
#to use daemon on CentOS we need to source the function
#linux_distro = platform.linux_distribution()[0]
#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE)
:
#self.command('source /etc/init.d/functions', '\$', 5)
if
self
.
air_interface
==
'lte'
:
nodeB_prefix
=
'e'
else
:
nodeB_prefix
=
'g'
#use nohup instead of daemon
self
.
command
(
'echo '
+
self
.
eNBPassword
+
' | sudo -S daemon --name=enb'
+
str
(
self
.
eNB_instance
)
+
'_daemon --stop'
,
'\$'
,
5
)
self
.
command
(
'rm -f my-lte-softmodem-run'
+
str
(
self
.
eNB_instance
)
+
'.sh'
,
'\$'
,
5
)
...
...
@@ -2354,12 +2352,12 @@ class SSHConnection():
if
result
is
not
None
:
copyin_res
=
self
.
copyin
(
self
.
eNBIPAddress
,
self
.
eNBUserName
,
self
.
eNBPassword
,
self
.
eNBSourceCodePath
+
'/cmake_targets/'
+
self
.
eNBLogFile
,
'.'
)
if
(
copyin_res
==
-
1
):
logging
.
debug
(
'
\u001B
[1;37;41m Could not copy
e
NB logfile to analyze it!
\u001B
[0m'
)
self
.
htmleNBFailureMsg
=
'Could not copy
e
NB logfile to analyze it!'
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
.
eNBLogFile
=
''
return
logging
.
debug
(
'
\u001B
[1m Analyzing
e
NB logfile
\u001B
[0m'
)
logging
.
debug
(
'
\u001B
[1m Analyzing
'
+
nodeB_prefix
+
'
NB logfile
\u001B
[0m'
)
logStatus
=
self
.
AnalyzeLogFile_eNB
(
self
.
eNBLogFile
)
if
(
logStatus
<
0
):
self
.
CreateHtmlTestRow
(
'N/A'
,
'KO'
,
logStatus
)
...
...
@@ -2485,16 +2483,16 @@ class SSHConnection():
optionsMsg
+=
self
.
htmlUEFailureMsg
optionsMsg
+=
'</pre>'
self
.
CreateHtmlTestRow
(
optionsMsg
,
'KO'
,
logStatus
,
'UE'
)
self
.
CreateHtmlTabFooter
(
False
)
sys
.
exit
(
1
)
# for NR-UE at the moment keep running
if
self
.
air_interface
==
'lte'
:
self
.
CreateHtmlTabFooter
(
False
)
sys
.
exit
(
1
)
else
:
optionsMsg
=
'<pre style="background-color:white"><b>Sniffing Successful</b>
\n
'
optionsMsg
+=
self
.
htmlUEFailureMsg
optionsMsg
+=
'</pre>'
self
.
CreateHtmlTestRow
(
optionsMsg
,
'OK'
,
ALL_PROCESSES_OK
)
self
.
UELogFile
=
''
else
:
self
.
CreateHtmlTestRow
(
'<pre style="background-color:white">No Log File to analyze</pre>'
,
'OK'
,
ALL_PROCESSES_OK
)
def
AutoTerminateUEandeNB
(
self
):
self
.
testCase_id
=
'AUTO-KILL-UE'
...
...
@@ -2818,9 +2816,7 @@ class SSHConnection():
self
.
GetAllUEDevices
(
terminate_ue_flag
)
self
.
GetAllCatMDevices
(
terminate_ue_flag
)
else
:
self
.
UEDevices
.
append
(
'doughq9rehg'
)
self
.
UEDevices
.
append
(
'dnsgiuahgia'
)
self
.
UEDevices
.
append
(
'uehgieng9'
)
self
.
UEDevices
.
append
(
'OAI-UE'
)
self
.
htmlUEConnected
=
len
(
self
.
UEDevices
)
i
=
0
...
...
@@ -3340,7 +3336,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
elif
SSH
.
EPCIPAddress
==
''
or
SSH
.
EPCUserName
==
''
or
SSH
.
EPCPassword
==
''
or
SSH
.
EPCType
==
''
or
SSH
.
EPCSourceCodePath
==
''
or
SSH
.
ADBIPAddress
==
''
or
SSH
.
ADBUserName
==
''
or
SSH
.
ADBPassword
==
''
:
Usage
()
sys
.
exit
(
'Insufficient Parameter'
)
if
(
SSH
.
EPCIPAddress
!=
''
):
if
(
SSH
.
EPCIPAddress
!=
''
)
and
(
SSH
.
EPCIPAddress
!=
'none'
)
:
SSH
.
copyout
(
SSH
.
EPCIPAddress
,
SSH
.
EPCUserName
,
SSH
.
EPCPassword
,
cwd
+
"/tcp_iperf_stats.awk"
,
"/tmp"
)
SSH
.
copyout
(
SSH
.
EPCIPAddress
,
SSH
.
EPCUserName
,
SSH
.
EPCPassword
,
cwd
+
"/active_net_interfaces.awk"
,
"/tmp"
)
else
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment