parent
1dc9a04bc1
commit
bc1ed88304
@ -0,0 +1,103 @@
|
||||
# osmo_gsm_tester: specifics for running an osmocon
|
||||
#
|
||||
# Copyright (C) 2018 by sysmocom - s.f.m.c. GmbH
|
||||
#
|
||||
# Author: Pau Espin Pedrol <pespin@sysmocom.de>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from . import log, util, process
|
||||
from .event_loop import MainLoop
|
||||
|
||||
class Osmocon(log.Origin):
|
||||
suite_run = None
|
||||
run_dir = None
|
||||
process = None
|
||||
sk_tmp_dir = None
|
||||
|
||||
FIRMWARE_FILE="opt/osmocom-bb/target/firmware/board/compal_e88/layer1.compalram.bin"
|
||||
|
||||
def __init__(self, suite_run, conf):
|
||||
serial_device = conf.get('serial_device')
|
||||
if serial_device is None:
|
||||
raise log.Error('osmocon_phone contains no attr "serial_device"')
|
||||
self.serial_device = os.path.realpath(serial_device)
|
||||
super().__init__(log.C_RUN, 'osmocon_%s' % os.path.basename(self.serial_device))
|
||||
self.suite_run = suite_run
|
||||
self.conf = conf
|
||||
self.sk_tmp_dir = tempfile.mkdtemp('', 'ogtosmoconsk')
|
||||
if len(self.l2_socket_path().encode()) > 107:
|
||||
raise log.Error('Path for l2 socket is longer than max allowed len for unix socket path (107):', self.l2_socket_path())
|
||||
if len(self.loader_socket_path().encode()) > 107:
|
||||
raise log.Error('Path for loader socket is longer than max allowed len for unix socket path (107):', self.loader_socket_path())
|
||||
|
||||
def l2_socket_path(self):
|
||||
return os.path.join(self.sk_tmp_dir, 'osmocom_l2')
|
||||
|
||||
def loader_socket_path(self):
|
||||
return os.path.join(self.sk_tmp_dir, 'osmocom_loader')
|
||||
|
||||
def start(self):
|
||||
self.log('Resetting the phone')
|
||||
# TODO: make sure the pone is powered off before starting osmocon
|
||||
|
||||
self.log('Starting osmocon')
|
||||
self.run_dir = util.Dir(self.suite_run.get_test_run_dir().new_dir(self.name()))
|
||||
|
||||
inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst('osmocom-bb')))
|
||||
|
||||
binary = inst.child('sbin', 'osmocon')
|
||||
if not os.path.isfile(binary):
|
||||
raise RuntimeError('Binary missing: %r' % binary)
|
||||
lib = inst.child('lib')
|
||||
if not os.path.isdir(lib):
|
||||
raise RuntimeError('No lib/ in %r' % inst)
|
||||
|
||||
env = { 'LD_LIBRARY_PATH': util.prepend_library_path(lib) }
|
||||
|
||||
firmware_path = os.path.join(str(inst), Osmocon.FIRMWARE_FILE)
|
||||
if not os.path.isfile(firmware_path):
|
||||
raise RuntimeError('Binary missing: %r' % firmware_path)
|
||||
self.dbg(run_dir=self.run_dir, binary=binary, env=env)
|
||||
self.process = process.Process(self.name(), self.run_dir,
|
||||
(binary, '-p', self.serial_device,
|
||||
'-m', 'c123xor',
|
||||
'-s', self.l2_socket_path(),
|
||||
'-l', self.loader_socket_path(),
|
||||
firmware_path),
|
||||
env=env)
|
||||
self.suite_run.remember_to_stop(self.process)
|
||||
self.process.launch()
|
||||
self.log('Waiting for osmocon to be up and running')
|
||||
MainLoop.wait(self, os.path.exists, self.l2_socket_path())
|
||||
|
||||
def running(self):
|
||||
return not self.process.terminated()
|
||||
|
||||
def cleanup(self):
|
||||
if self.sk_tmp_dir:
|
||||
try:
|
||||
os.remove(self.l2_socket_path())
|
||||
except OSError:
|
||||
pass
|
||||
try:
|
||||
os.remove(self.loader_socket_path())
|
||||
except OSError:
|
||||
pass
|
||||
os.rmdir(self.sk_tmp_dir)
|
||||
|
||||
# vim: expandtab tabstop=4 shiftwidth=4
|
@ -0,0 +1,20 @@
|
||||
This directory contains a set of scripts and osmo-gsm-tester testsuites to run
|
||||
osmo-ttcn3-hacks.git BTS_tests.ttcn (https://git.osmocom.org/osmo-ttcn3-hacks/tree/bts).
|
||||
|
||||
The idea is to set up automatically the following components:
|
||||
TTCN3 <-> osmocon (osmocom-bb) <-> motorola C123 <-> RF network <-> BTS_TO_TEST <-> TTCN3 + osmo-bsc
|
||||
|
||||
* A jenkins job builds a docker image containing a built BTS_tests TTCN testsuite.
|
||||
* Another jenkins job retrieves the artifacts from osmo-gsm-tester-build jobs
|
||||
plus one for required osmocon binary. This job then calls osmo-gsm-tester/ttcn3/jenkins-run.sh, which will:
|
||||
** Pull the above mentioned docker image containing BTS_Tests.
|
||||
** Start osmo-gsm-tester with OSMO_GSM_TESTER_OPTS=osmo-gsm-tester/ttcn3/paths.conf,
|
||||
that contains mostly same stuff as regular osmo-gsm-tester jobs, but with a
|
||||
different testsuite containing 1 test "ttcn3_bts_tests.py".
|
||||
** The test "ttcn3_bts_tests.py" does the following:
|
||||
*** Start and manage all osmocom required components to run BTS_Tests: osmo-bts, osmo-bsc, osmocon, etc.
|
||||
*** Generate the BTS_Tests.cfg required by BTS_Tests from a template to adapt to dynamic bits set by osmo-gsm-tester.
|
||||
*** Launch script osmo-gsm-tester/ttcn3/suites/ttcn3_bts_tests/scripts/run_ttcn3_docker.sh with parameters and wait for it to finish.
|
||||
This script will start and manage the lifecycle of the docker container running BTS_Tests
|
||||
|
||||
See OS#3155 for more information regarding this topic.
|
@ -0,0 +1 @@
|
||||
- ttcn3_bts_tests:trx
|
@ -0,0 +1 @@
|
||||
../example/defaults.conf
|
@ -0,0 +1,58 @@
|
||||
#!/bin/sh
|
||||
set -e -x
|
||||
base="$PWD"
|
||||
|
||||
time_start="$(date '+%F %T')"
|
||||
|
||||
prepare_docker() {
|
||||
OLDPWD=$PWD
|
||||
|
||||
# update docker-playground and update the BSC and bsc-test containers (if needed)
|
||||
DIR=~/jenkins/docker-playground
|
||||
if [ ! -d "$DIR" ]; then
|
||||
mkdir -p ~/jenkins/ && cd ~/jenkins
|
||||
git clone git://git.osmocom.org/docker-playground
|
||||
fi
|
||||
cd $DIR
|
||||
git remote prune origin; git fetch; git checkout -f -B master origin/master
|
||||
cd $DIR/debian-stretch-titan && make
|
||||
docker pull laforge/debian-stretch-titan:latest # HACK
|
||||
cd $DIR/ttcn3-bts-test && make
|
||||
# execute the script to start containers, read results, ...
|
||||
#cd $DIR/ttcn3-bts-test && sh -x ./jenkins.sh
|
||||
PWD=$OLDPWD
|
||||
}
|
||||
|
||||
docker pull registry.sysmocom.de/ttcn3-bts-test
|
||||
|
||||
# remove older trial dirs and *-run.tgz, if any
|
||||
trial_dir_prefix="trial-"
|
||||
rm -rf "$trial_dir_prefix"* || true
|
||||
|
||||
# Expecting *.tgz artifacts to be copied to this workspace from the various
|
||||
# jenkins-*.sh runs, via jenkins job configuration. Compose a trial dir:
|
||||
trial_dir="${trial_dir_prefix}$BUILD_NUMBER"
|
||||
mkdir -p "$trial_dir"
|
||||
|
||||
mv *.tgz "$trial_dir"
|
||||
cat *.md5 >> "$trial_dir/checksums.md5"
|
||||
rm *.md5
|
||||
|
||||
# OSMO_GSM_TESTER_OPTS is a way to pass in e.g. logging preferences from the
|
||||
# jenkins build job.
|
||||
# On failure, first clean up below and then return the exit code.
|
||||
exit_code="1"
|
||||
if python3 -u "$(which osmo-gsm-tester.py)" "$trial_dir" $OSMO_GSM_TESTER_OPTS ; then
|
||||
exit_code="0"
|
||||
fi
|
||||
|
||||
# no need to keep extracted binaries
|
||||
rm -rf "$trial_dir/inst" || true
|
||||
|
||||
# tar up all results for archiving (optional)
|
||||
cd "$trial_dir"
|
||||
journalctl -u ofono -o short-precise --since "${time_start}" > "$(readlink last_run)/ofono.log"
|
||||
tar czf "$base/${trial_dir}-run.tgz" "$(readlink last_run)"
|
||||
tar czf "$base/${trial_dir}-bin.tgz" *.md5 *.tgz
|
||||
|
||||
exit $exit_code
|
@ -0,0 +1,3 @@
|
||||
state_dir: '/var/tmp/osmo-gsm-tester/state'
|
||||
suites_dir: './suites'
|
||||
scenarios_dir: './scenarios'
|
@ -0,0 +1 @@
|
||||
../example/resources.conf.prod
|
@ -0,0 +1 @@
|
||||
../example/resources.conf.rnd
|
@ -0,0 +1 @@
|
||||
../../example/scenarios/trx.conf
|
@ -0,0 +1,25 @@
|
||||
[ORDERED_INCLUDE]
|
||||
"/osmo-ttcn3-hacks/Common.cfg"
|
||||
"/osmo-ttcn3-hacks/bts/BTS_Tests.default"
|
||||
|
||||
[LOGGING]
|
||||
|
||||
[TESTPORT_PARAMETERS]
|
||||
*.BTSVTY.CTRL_HOSTNAME := "${btsvty_ctrl_hostname}"
|
||||
|
||||
[MODULE_PARAMETERS]
|
||||
BTS_Tests.mp_rsl_ip := "172.18.9.10"
|
||||
BTS_Tests.mp_bb_trxc_ip := "127.0.0.1"
|
||||
BTS_Tests.mp_pcu_socket := "/data/unix_pcu/pcu_bts"
|
||||
BTS_Tests.mp_bb_trxc_port := -1
|
||||
L1CTL_PortType.m_l1ctl_sock_path := "/data/unix_l2/osmocom_l2"
|
||||
BTS_Tests.mp_ctrl_ip := "${btsvty_ctrl_hostname}"
|
||||
BTS_Tests.mp_rxlev_exp := 1
|
||||
BTS_Tests.mp_tolerance_rxlev := 10;
|
||||
BTS_Tests.mp_tolerance_rxqual := 1;
|
||||
BTS_Tests.mp_trx0_arfcn := 868
|
||||
|
||||
[MAIN_CONTROLLER]
|
||||
|
||||
[EXECUTE]
|
||||
BTS_Tests.control
|
@ -0,0 +1,86 @@
|
||||
#!/bin/sh
|
||||
set -x
|
||||
|
||||
RUNDIR="$1"
|
||||
JUNIT_TTCN3_DST_FILE="$2"
|
||||
L2_SOCKET_PATH="$3"
|
||||
PCU_SOCKET_PATH="$4"
|
||||
|
||||
# Absolute path to this script
|
||||
SCRIPT=$(readlink -f "$0")
|
||||
# Absolute path this script is in
|
||||
SCRIPTPATH=$(dirname "$SCRIPT")
|
||||
|
||||
VOL_BASE_DIR="$RUNDIR/logs"
|
||||
rm -rf "$VOL_BASE_DIR"
|
||||
mkdir -p "$VOL_BASE_DIR"
|
||||
|
||||
if [ "x$BUILD_TAG" = "x" ]; then
|
||||
BUILD_TAG=nonjenkins
|
||||
fi
|
||||
|
||||
REPO_USER="registry.sysmocom.de"
|
||||
SUITE_NAME="ttcn3-bts-test"
|
||||
NET_NAME=$SUITE_NAME
|
||||
DOCKER_NAME="$BUILD_TAG-$SUITE_NAME"
|
||||
|
||||
network_create() {
|
||||
NET=$1
|
||||
echo Creating network $NET_NAME
|
||||
docker network create --internal --subnet $NET $NET_NAME
|
||||
}
|
||||
|
||||
network_remove() {
|
||||
echo Removing network $NET_NAME
|
||||
docker network remove $NET_NAME
|
||||
}
|
||||
|
||||
child_ps=0
|
||||
forward_kill() {
|
||||
sig="$1"
|
||||
echo "Caught signal SIG$sig!"
|
||||
if [ "$child_ps" != "0" ]; then
|
||||
echo "Killing $child_ps with SIG$sig!"
|
||||
docker kill ${DOCKER_NAME}
|
||||
fi
|
||||
exit 130
|
||||
}
|
||||
forward_kill_int() {
|
||||
forward_kill "INT"
|
||||
}
|
||||
forward_kill_term() {
|
||||
forward_kill "TERM"
|
||||
}
|
||||
# Don't use 'set -e', otherwise traps are not triggered!
|
||||
trap forward_kill_int INT
|
||||
trap forward_kill_term TERM
|
||||
|
||||
network_create 172.18.9.0/24
|
||||
|
||||
mkdir $VOL_BASE_DIR/bts-tester
|
||||
echo "SCRIPTPATH=$SCRIPTPATH PWD=$PWD"
|
||||
cp $RUNDIR/BTS_Tests.cfg $VOL_BASE_DIR/bts-tester/
|
||||
|
||||
echo Starting container with BTS testsuite
|
||||
docker kill ${DOCKER_NAME}
|
||||
docker run --rm \
|
||||
--network $NET_NAME --ip 172.18.9.10 \
|
||||
-e "TTCN3_PCAP_PATH=/data" \
|
||||
--mount type=bind,source=$VOL_BASE_DIR/bts-tester,destination=/data \
|
||||
--mount type=bind,source="$(dirname "$L2_SOCKET_PATH")",destination=/data/unix_l2 \
|
||||
--mount type=bind,source="$(dirname "$PCU_SOCKET_PATH")",destination=/data/unix_pcu \
|
||||
--name ${DOCKER_NAME} \
|
||||
$REPO_USER/${SUITE_NAME} &
|
||||
child_ps=$!
|
||||
echo "$$: waiting for $child_ps"
|
||||
wait "$child_ps"
|
||||
child_exit_code="$?"
|
||||
echo "ttcn3 docker exited with code $child_exit_code"
|
||||
|
||||
network_remove
|
||||
|
||||
echo "Copying TTCN3 junit file to $JUNIT_TTCN3_DST_FILE"
|
||||
cp $VOL_BASE_DIR/bts-tester/junit-xml-*.log $JUNIT_TTCN3_DST_FILE
|
||||
sed -i "s#classname='BTS_Tests'#classname='$(basename $JUNIT_TTCN3_DST_FILE)'#g" $JUNIT_TTCN3_DST_FILE
|
||||
|
||||
exit $child_exit_code
|
@ -0,0 +1,7 @@
|
||||
resources:
|
||||
ip_address:
|
||||
- times: 7 # msc, bsc, hlr, stp, mgw, sgsn, ggsn
|
||||
bts:
|
||||
- times: 1
|
||||
osmocon_phone:
|
||||
- times: 1
|
@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
from mako.template import Template
|
||||
|
||||
from osmo_gsm_tester.testenv import *
|
||||
|
||||
hlr_dummy = suite.hlr()
|
||||
mgw_dummy = suite.mgw()
|
||||
stp_dummy = suite.stp()
|
||||
msc_dummy = suite.msc(hlr_dummy, mgw_dummy, stp_dummy)
|
||||
ggsn_dummy = suite.ggsn()
|
||||
sgsn_dummy = suite.sgsn(hlr_dummy, ggsn_dummy)
|
||||
bsc = suite.bsc(msc_dummy, mgw_dummy, stp_dummy)
|
||||
bts = suite.bts()
|
||||
osmocon = suite.osmocon()
|
||||
|
||||
bts.set_num_trx(1)
|
||||
bts.set_trx_phy_channel(0, 0, 'CCCH+SDCCH4')
|
||||
bts.set_trx_phy_channel(0, 1, 'TCH/F')
|
||||
bts.set_trx_phy_channel(0, 2, 'TCH/F')
|
||||
bts.set_trx_phy_channel(0, 3, 'TCH/F_PDCH')
|
||||
bts.set_trx_phy_channel(0, 4, 'TCH/F_TCH/H_PDCH')
|
||||
bts.set_trx_phy_channel(0, 5, 'TCH/H')
|
||||
bts.set_trx_phy_channel(0, 6, 'SDCCH8')
|
||||
bts.set_trx_phy_channel(0, 7, 'PDCH')
|
||||
|
||||
print('Starting CNI')
|
||||
hlr_dummy.start()
|
||||
stp_dummy.start()
|
||||
msc_dummy.start()
|
||||
mgw_dummy.start()
|
||||
|
||||
bsc.set_rsl_ip('172.18.9.10')
|
||||
bsc.bts_add(bts)
|
||||
sgsn_dummy.bts_add(bts)
|
||||
|
||||
bsc.start()
|
||||
bts.start(keepalive=True)
|
||||
|
||||
print('Starting osmocon')
|
||||
osmocon.start()
|
||||
|
||||
own_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
script_file = os.path.join(own_dir, 'scripts', 'run_ttcn3_docker.sh')
|
||||
bts_tmpl_file = os.path.join(own_dir, 'scripts', 'BTS_Tests.cfg.tmpl')
|
||||
script_run_dir = test.get_run_dir().new_dir('ttcn3')
|
||||
bts_cfg_file = os.path.join(str(script_run_dir), 'BTS_Tests.cfg')
|
||||
junit_ttcn3_dst_file = os.path.join(str(suite.trial.get_run_dir()), 'trial-') + suite.name() + '.xml'
|
||||
docker_cmd = (script_file, str(script_run_dir), junit_ttcn3_dst_file, osmocon.l2_socket_path(), bts.pcu_socket_path())
|
||||
|
||||
print('Creating template')
|
||||
mytemplate = Template(filename=bts_tmpl_file)
|
||||
r = mytemplate.render(btsvty_ctrl_hostname=bts.remote_addr())
|
||||
with open(bts_cfg_file, 'w') as f:
|
||||
f.write(r)
|
||||
|
||||
|
||||
print('Starting TTCN3 tests')
|
||||
proc = process.Process('ttcn3', script_run_dir, docker_cmd)
|
||||
try:
|
||||
proc.launch()
|
||||
print('Starting TTCN3 launched, waiting until it finishes')
|
||||
proc.wait(timeout=3600)
|
||||
except Exception as e:
|
||||
proc.terminate()
|
||||
raise e
|
||||
|
||||
if proc.result != 0:
|
||||
raise RuntimeError("run_ttcn3_docker.sh exited with error code %d" % proc.result)
|
||||
|
||||
print('Done')
|
Loading…
Reference in new issue