summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--example/default-suites.conf3
-rw-r--r--example/resources.conf.prod15
-rw-r--r--example/scenarios/mod-bts0-trxdversion0.conf4
-rwxr-xr-xselftest/suite_test.py29
-rw-r--r--src/osmo_gsm_tester/bts_osmotrx.py108
-rw-r--r--src/osmo_gsm_tester/process.py9
-rw-r--r--src/osmo_gsm_tester/resource.py1
-rw-r--r--src/osmo_gsm_tester/test.py6
8 files changed, 148 insertions, 27 deletions
diff --git a/example/default-suites.conf b/example/default-suites.conf
index f93c933..05967d6 100644
--- a/example/default-suites.conf
+++ b/example/default-suites.conf
@@ -45,6 +45,7 @@
- voice:trx-b200+mod-bts0-ts-tchh+cfg-codec-hr3
- voice:trx-b200+mod-bts0-dynts-ipa+cfg-codec-fr-any
- voice:trx-b200+mod-bts0-dynts-osmo
+- voice:trx-b200+mod-bts0-trxdversion0
- voice:trx-b200+mod-bts0-numtrx2+mod-bts0-chanallocdescend
- gprs:trx-b200
- gprs:trx-b200+mod-bts0-egprs
@@ -103,12 +104,10 @@
- voice:trx-lms+mod-bts0-ts-tchh+cfg-codec-hr3
- voice:trx-lms+mod-bts0-dynts-ipa+cfg-codec-fr-any
- voice:trx-lms+mod-bts0-dynts-osmo
-- voice:trx-lms+mod-bts0-numtrx2+mod-bts0-chanallocdescend
- gprs:trx-lms
- gprs:trx-lms+mod-bts0-egprs
- gprs:trx-lms+mod-bts0-dynts-ipa
- gprs:trx-lms+mod-bts0-dynts-osmo
-- gprs:trx-lms+mod-bts0-numtrx2+mod-bts0-chanallocdescend
- dynts:trx-lms+mod-bts0-dynts67-ipa+cfg-codec-fr-any
- dynts:trx-lms+mod-bts0-dynts67-osmo
diff --git a/example/resources.conf.prod b/example/resources.conf.prod
index b0a679e..0bf9f45 100644
--- a/example/resources.conf.prod
+++ b/example/resources.conf.prod
@@ -70,12 +70,17 @@ bts:
band: GSM-1800
ciphers: [a5_0, a5_1]
trx_list:
- - arfcn: 878
+ - power_supply:
+ type: 'intellinet'
+ device: '10.42.42.250'
+ port: '5'
osmo_trx:
- launch_trx: false
- clock_reference: external
- trx_ip: 10.42.42.112
- max_trxd_version: 0
+ type: sc5
+ launch_trx: true
+ remote_user: root
+ clock_reference: external
+ trx_ip: 10.42.42.112
+ max_trxd_version: 0
- label: OCTBTS 3500
type: osmo-bts-octphy
diff --git a/example/scenarios/mod-bts0-trxdversion0.conf b/example/scenarios/mod-bts0-trxdversion0.conf
new file mode 100644
index 0000000..67e5653
--- /dev/null
+++ b/example/scenarios/mod-bts0-trxdversion0.conf
@@ -0,0 +1,4 @@
+modifiers:
+ bts:
+ - osmo_trx:
+ max_trxd_version: 0
diff --git a/selftest/suite_test.py b/selftest/suite_test.py
index db19ccc..115d76e 100755
--- a/selftest/suite_test.py
+++ b/selftest/suite_test.py
@@ -1,10 +1,26 @@
#!/usr/bin/env python3
import os
import _prep
-from osmo_gsm_tester import log, suite, config, report
+import shutil
+from osmo_gsm_tester import log, suite, config, report, util
config.ENV_CONF = './suite_test'
+example_trial_dir = os.path.join('test_trial_tmp')
+
+class FakeTrial(log.Origin):
+ def __init__(self):
+ super().__init__(log.C_TST, 'trial')
+ self.dir = util.Dir(example_trial_dir)
+ self._run_dir = None
+
+ def get_run_dir(self):
+ if self._run_dir is not None:
+ return self._run_dir
+ self._run_dir = util.Dir(self.dir.new_child('test_run'))
+ self._run_dir.mkdir()
+ return self._run_dir
+
#log.style_change(trace=True)
print('- non-existing suite dir')
@@ -20,7 +36,7 @@ assert(isinstance(s_def, suite.SuiteDefinition))
print(config.tostr(s_def.conf))
print('- run hello world test')
-trial = log.Origin(log.C_TST, 'trial')
+trial = FakeTrial()
s = suite.SuiteRun(trial, 'test_suite', s_def)
results = s.run_tests('hello_world.py')
print(report.suite_to_text(s))
@@ -43,7 +59,7 @@ output = report.suite_to_text(s)
print(output)
print('- test with half empty scenario')
-trial = log.Origin(log.C_TST, 'trial')
+trial = FakeTrial()
scenario = config.Scenario('foo', 'bar')
scenario['resources'] = { 'bts': [{'type': 'osmo-bts-trx'}] }
s = suite.SuiteRun(trial, 'test_suite', s_def, [scenario])
@@ -51,7 +67,7 @@ results = s.run_tests('hello_world.py')
print(report.suite_to_text(s))
print('- test with scenario')
-trial = log.Origin(log.C_TST, 'trial')
+trial = FakeTrial()
scenario = config.Scenario('foo', 'bar')
scenario['resources'] = { 'bts': [{ 'times': '2', 'type': 'osmo-bts-trx', 'trx_list': [{'nominal_power': '10'}, {'nominal_power': '12'}]}, {'type': 'sysmo'}] }
s = suite.SuiteRun(trial, 'test_suite', s_def, [scenario])
@@ -59,7 +75,7 @@ results = s.run_tests('hello_world.py')
print(report.suite_to_text(s))
print('- test with scenario and modifiers')
-trial = log.Origin(log.C_TST, 'trial')
+trial = FakeTrial()
scenario = config.Scenario('foo', 'bar')
scenario['resources'] = { 'bts': [{ 'times': '2', 'type': 'osmo-bts-trx', 'trx_list': [{'nominal_power': '10'}, {'nominal_power': '12'}]}, {'type': 'sysmo'}] }
scenario['modifiers'] = { 'bts': [{ 'times': '2', 'trx_list': [{'nominal_power': '20'}, {'nominal_power': '20'}]}, {'type': 'sysmo'}] }
@@ -70,4 +86,7 @@ results = s.run_tests('hello_world.py')
print(report.suite_to_text(s))
print('\n- graceful exit.')
+#deleting generated tmp trial dir:
+shutil.rmtree(example_trial_dir, ignore_errors=True)
+
# vim: expandtab tabstop=4 shiftwidth=4
diff --git a/src/osmo_gsm_tester/bts_osmotrx.py b/src/osmo_gsm_tester/bts_osmotrx.py
index b3738d2..554a236 100644
--- a/src/osmo_gsm_tester/bts_osmotrx.py
+++ b/src/osmo_gsm_tester/bts_osmotrx.py
@@ -22,6 +22,7 @@ import stat
import pprint
from abc import ABCMeta, abstractmethod
from . import log, config, util, template, process, bts_osmo
+from . import powersupply
from .event_loop import MainLoop
class OsmoBtsTrx(bts_osmo.OsmoBtsMainUnit):
@@ -39,6 +40,7 @@ class OsmoBtsTrx(bts_osmo.OsmoBtsMainUnit):
self.run_dir = None
self.inst = None
self.trx = None
+ self.pwsup_list = []
self.env = {}
self.gen_conf = {}
@@ -92,6 +94,20 @@ class OsmoBtsTrx(bts_osmo.OsmoBtsMainUnit):
self.dbg(r)
f.write(r)
+ self.pwsup_list = [None] * self.num_trx()
+ # Construct trx_list appending with empty dicts if needed:
+ conf_trx_list = self.conf.get('trx_list', [])
+ conf_trx_list = conf_trx_list + [{}] * (self.num_trx() - len(conf_trx_list))
+ for trx_i in range(self.num_trx()):
+ pwsup_opt = conf_trx_list[trx_i].get('power_supply', {})
+ if not pwsup_opt:
+ self.dbg('no power_supply configured for TRX %d' % trx_i)
+ continue
+ pwsup_type = pwsup_opt.get('type')
+ if not pwsup_type:
+ raise log.Error('No type attribute provided in power_supply conf for TRX %d!' % trx_i)
+ self.pwsup_list[trx_i] = powersupply.get_instance_by_type(pwsup_type, pwsup_opt)
+
def launch_trx_enabled(self):
return util.str2bool(self.gen_conf['osmo_bts_trx'].get('osmo_trx', {}).get('launch_trx'))
@@ -109,6 +125,15 @@ class OsmoBtsTrx(bts_osmo.OsmoBtsMainUnit):
def conf_for_osmotrx(self):
return dict(osmo_trx=self.gen_conf['osmo_bts_trx'].get('osmo_trx', {}))
+ def cleanup(self):
+ i = 0
+ for pwsup in self.pwsup_list:
+ if pwsup:
+ self.dbg('Powering off TRX %d' % i)
+ pwsup.power_set(False)
+ i = i + 1
+ self.pwsup_list = []
+
###################
# PUBLIC (test API included)
###################
@@ -121,6 +146,14 @@ class OsmoBtsTrx(bts_osmo.OsmoBtsMainUnit):
self.run_dir = util.Dir(self.suite_run.get_test_run_dir().new_dir(self.name()))
self.configure()
+ # Power cycle all TRX if needed (right now only TRX0 for SC5):
+ i = 0
+ for pwsup in self.pwsup_list:
+ if pwsup:
+ self.dbg('Powering cycling TRX %d' % i)
+ pwsup.power_cycle(1.0)
+ i = i + 1
+
if self.launch_trx_enabled():
self.trx = OsmoTrx.get_instance_by_type(self.get_osmo_trx_type(), self.suite_run, self.conf_for_osmotrx())
self.trx.start(keepalive)
@@ -138,37 +171,61 @@ class OsmoBtsTrx(bts_osmo.OsmoBtsMainUnit):
'-i', self.bsc.addr())
self.suite_run.poll()
-class OsmoTrx(log.Origin, metaclass=ABCMeta):
- CONF_OSMO_TRX = 'osmo-trx.cfg'
- REMOTE_DIR = '/osmo-gsm-tester-trx/last_run'
- WRAPPER_SCRIPT = 'ssh_sigkiller.sh'
+################################################################################
+# TRX
+################################################################################
+class Trx(log.Origin, metaclass=ABCMeta):
##############
# PROTECTED
##############
- def __init__(self, suite_run, conf):
- super().__init__(log.C_RUN, self.binary_name())
+ def __init__(self, suite_run, conf, name):
+ super().__init__(log.C_RUN, name)
self.suite_run = suite_run
self.conf = conf
- self.env = {}
- self.log("OSMOTRX CONF: %r" % conf)
+ self.run_dir = util.Dir(self.suite_run.get_test_run_dir().new_dir(self.name()))
self.listen_ip = conf.get('osmo_trx', {}).get('trx_ip')
- self.bts_ip = conf.get('osmo_trx', {}).get('bts_ip')
self.remote_user = conf.get('osmo_trx', {}).get('remote_user', None)
- self.run_dir = None
- self.inst = None
- self.proc_trx = None
@classmethod
def get_instance_by_type(cls, type, suite_run, conf):
KNOWN_OSMOTRX_TYPES = {
'uhd': OsmoTrxUHD,
'lms': OsmoTrxLMS,
+ 'sc5': TrxSC5
}
osmo_trx_class = KNOWN_OSMOTRX_TYPES.get(type)
return osmo_trx_class(suite_run, conf)
+##############
+# PUBLIC (test API included)
+##############
+ @abstractmethod
+ def start(self, keepalive=False):
+ pass
+
+ @abstractmethod
+ def trx_ready(self):
+ pass
+
+class OsmoTrx(Trx, metaclass=ABCMeta):
+
+ CONF_OSMO_TRX = 'osmo-trx.cfg'
+ REMOTE_DIR = '/osmo-gsm-tester-trx/last_run'
+ WRAPPER_SCRIPT = 'ssh_sigkiller.sh'
+
+##############
+# PROTECTED
+##############
+ def __init__(self, suite_run, conf):
+ super().__init__(suite_run, conf, self.binary_name())
+ self.env = {}
+ self.log("OSMOTRX CONF: %r" % conf)
+ self.bts_ip = conf.get('osmo_trx', {}).get('bts_ip')
+ self.inst = None
+ self.proc_trx = None
+
@abstractmethod
def binary_name(self):
'Used by base class. Subclass can create different OsmoTRX implementations.'
@@ -242,7 +299,6 @@ class OsmoTrx(log.Origin, metaclass=ABCMeta):
# PUBLIC (test API included)
##############
def start(self, keepalive=False):
- self.run_dir = util.Dir(self.suite_run.get_test_run_dir().new_dir(self.name()))
self.configure()
self.inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst('osmo-trx')))
if not self.remote_user:
@@ -293,4 +349,30 @@ class OsmoTrxLMS(OsmoTrx):
def binary_name(self):
return OsmoTrxLMS.BIN_TRX
+class TrxSC5(Trx):
+
+ def __init__(self, suite_run, conf):
+ super().__init__(suite_run, conf, "sc5-trx")
+ self.ready = False
+
+ def start(self, keepalive=False):
+ name = "ssh_sc5_ccli"
+ run_dir = self.run_dir.new_dir(name)
+ popen_args = ('/cx/bin/ccli', '-c', 'gsm.unlock')
+ proc = process.RemoteProcess(name, run_dir, self.remote_user, self.listen_ip, None,
+ popen_args)
+ keep_trying = 10
+ while keep_trying > 0:
+ if proc.respawn_sync(raise_nonsuccess=False) == 0 and 'OK' in (proc.get_stdout() or ''):
+ break
+ keep_trying = keep_trying - 1
+ self.log('Configuring SC5 TRX failed, retrying %d more times' % keep_trying)
+ MainLoop.sleep(self, 5)
+ if keep_trying == 0:
+ raise log.Error('Failed configuring SC5!')
+ self.ready = True
+
+ def trx_ready(self):
+ return self.ready
+
# vim: expandtab tabstop=4 shiftwidth=4
diff --git a/src/osmo_gsm_tester/process.py b/src/osmo_gsm_tester/process.py
index 4b22d0c..b73673f 100644
--- a/src/osmo_gsm_tester/process.py
+++ b/src/osmo_gsm_tester/process.py
@@ -205,7 +205,14 @@ class Process(log.Origin):
assert not self.is_running()
self.result = None
self.killed = None
- self.launch()
+ return self.launch()
+
+ def respawn_sync(self, raise_nonsuccess=True):
+ self.dbg('respawn_sync')
+ assert not self.is_running()
+ self.result = None
+ self.killed = None
+ return self.launch_sync(raise_nonsuccess)
def _poll_termination(self, time_to_wait_for_term=5):
wait_step = 0.001
diff --git a/src/osmo_gsm_tester/resource.py b/src/osmo_gsm_tester/resource.py
index aa41b98..1b18076 100644
--- a/src/osmo_gsm_tester/resource.py
+++ b/src/osmo_gsm_tester/resource.py
@@ -60,7 +60,6 @@ RESOURCES_SCHEMA = {
'bts[].num_trx': schema.UINT,
'bts[].max_trx': schema.UINT,
'bts[].trx_list[].addr': schema.IPV4,
- 'bts[].trx_list[].arfcn': schema.INT,
'bts[].trx_list[].hw_addr': schema.HWADDR,
'bts[].trx_list[].net_device': schema.STR,
'bts[].trx_list[].nominal_power': schema.UINT,
diff --git a/src/osmo_gsm_tester/test.py b/src/osmo_gsm_tester/test.py
index 6f141f1..4d4353a 100644
--- a/src/osmo_gsm_tester/test.py
+++ b/src/osmo_gsm_tester/test.py
@@ -42,6 +42,7 @@ class Test(log.Origin):
self.duration = 0
self.fail_type = None
self.fail_message = None
+ self.log_target = None
def get_run_dir(self):
if self._run_dir is None:
@@ -50,6 +51,7 @@ class Test(log.Origin):
def run(self):
try:
+ self.log_target = log.FileLogTarget(self.get_run_dir().new_child('log')).set_all_levels(log.L_DBG).style_change(trace=True)
log.large_separator(self.suite_run.trial.name(), self.suite_run.name(), self.name(), sublevel=3)
self.status = Test.UNKNOWN
self.start_timestamp = time.time()
@@ -81,6 +83,10 @@ class Test(log.Origin):
# when the program is aborted by a signal (like Ctrl-C), escalate to abort all.
self.err('TEST RUN ABORTED: %s' % type(e).__name__)
raise
+ finally:
+ if self.log_target:
+ self.log_target.remove()
+ self.log_target = None
def name(self):
l = log.get_line_for_src(self.path)