Commit 51dfd825 authored by Tomáš Peterka's avatar Tomáš Peterka

WIP: lte-standalone a unprivileged bundle of Amarisoft LTE stack

parent d2e8a850
#
# Deploy LTE instance
#
[buildout]
parts =
directory
publish-connection-parameter
lte-launcher
eggs-directory = {{ buildout['eggs-directory'] }}
develop-eggs-directory = {{ buildout['develop-eggs-directory'] }}
offline = true
[instance]
recipe = slapos.cookbook:slapconfiguration
computer = ${slap_connection:computer_id}
partition = ${slap_connection:partition_id}
url = ${slap_connection:server_url}
key = ${slap_connection:key_file}
cert = ${slap_connection:cert_file}
configuration.frequency
configuration.TRX
configuration.log_size = 50M
[directory]
recipe = slapos.cookbook:mkdirectory
home = ${buildout:directory}
mme = ${:home}/mme
ims = ${:home}/ims
enb = ${:home}/enb
etc = ${:home}/etc
var = ${:home}/var
run = ${:var}/run
script = ${:etc}/run
service = ${:etc}/service
promise = ${:etc}/promise
log = ${:var}/log
### MME ############################################################################################
[lte-mme-log]
recipe = slapos.cookbook:wrapper
command = {{ buildout['directory'] }}/ltelogs.sh {{ directory['log'] }}/mme.log
destination = ${directory:script}/lte-mme-log
mode = 0775
pidfile = {{ directory['log'] }}/mme.log.clean
remove_pidfile = true
[lte-mme-socket]
recipe = slapos.cookbook:wrapper
command = mkfifo {{ directory['run'] }}/mme.sock; cat > {{ directory['run'] }}/mme.sock
destination = ${directory:service}/lte-mme-socket
mode = 0775
cleanup_command = rm -f {{ directory['run'] }}/mme.sock
[lte-mme-service]
recipe = slapos.cookbook:wrapper
command = {{ directory['mme'] }}/ltemme \\
{{ directory['mme'] }}/config/mme.cfg \\
< {{ directory['run'] }}/mme.sock \\
wrapper-path = ${directory:script}/lte-mme
mode = 0775
pidfile = {{ directory['run'] }}/mme.pid
remove_pidfile = true
wait-for-files =
{{ directory['run'] }}/mme.sock
{{ directory['log'] }}/mme.log.clean
[lte-mme-service-log]
# MME binary needs upon startup on its STDIN a command where it should log
recipe = slapos.cookbook:wrapper
command = echo "log file.rotate={{ instance['configuration.log_size'] }},file.path={{ directory['log'] }}"\\
> {{ directory['run'] }}/mme.sock
destination = ${directory:script}/lte-mme-service-log
wait-for-files =
{{ directory['run'] }}/mme.sock
{{ directory['run'] }}/mme.pid
### IMS ############################################################################################
[lte-ims-service]
recipe = slapos.cookbook:wrapper
command = {{ directory['ims'] }}/ims \\
{{ directory['ims'] }}/config/ims.cfg \\
< {{ directory['run'] }}/ims.sock
wrapper-path = ${directory:script}/lte-ims
mode = 0775
pidfile = {{ directory['run'] }}/ims.pid
remove_pidfile = true
wait-for-files =
{{ directory['run'] }}/ims.sock
{{ directory['log'] }}/ims.log.clean
[lte-ims-log]
recipe = slapos.cookbook:wrapper
command = {{ buildout['directory'] }}/ltelogs.sh {{ directory['log'] }}/ims.log
destination = ${directory:script}/lte-ims-log
mode = 0775
pidfile = {{ directory['log'] }}/ims.log.clean
remove_pidfile = true
[lte-ims-socket]
recipe = slapos.cookbook:wrapper
command = mkfifo {{ directory['run'] }}/ims.sock; cat > {{ directory['run'] }}/ims.sock
destination = ${directory:service}/lte-ims-socket
mode = 0775
cleanup_command = rm -f {{ directory['run'] }}/ims.sock
[lte-ims-service-log]
# ims binary needs upon startup on its STDIN a command where it should log
recipe = slapos.cookbook:wrapper
command = echo "log file.rotate={{ instance['configuration.log_size'] }},file.path={{ directory['log'] }}"\\
> {{ directory['run'] }}/ims.sock
destination = ${directory:script}/lte-ims-service-log
wait-for-files =
{{ directory['run'] }}/ims.sock
{{ directory['run'] }}/ims.pid
[lte-register-ims-with-mme]
recipe = slapos.cookbook:wrapper
command = echo "imsconnect" > {{ directory['run'] }}/mme.sock; echo "t" > {{ directory['run'] }}/ims.sock;
destination = ${directory:script}/lte-ims-register
wait-for-files =
{{ directory['run'] }}/mme.sock
{{ directory['run'] }}/ims.sock
{{ directory['run'] }}/ims.pid
### eNodeB (enb) ###################################################################################
[lte-enb-service]
recipe = slapos.cookbook:wrapper
command = {{ directory['enb'] }}/enb \\
{{ directory['enb'] }}/config/enb.cfg \\
< {{ directory['run'] }}/enb.sock
wrapper-path = ${directory:script}/lte-enb
mode = 0775
pidfile = {{ directory['run'] }}/enb.pid
remove_pidfile = true
wait-for-files =
{{ directory['run'] }}/enb.sock
{{ directory['log'] }}/enb.log.clean
[lte-enb-log]
recipe = slapos.cookbook:wrapper
command = {{ buildout['directory'] }}/ltelogs.sh {{ directory['log'] }}/enb.log
destination = ${directory:script}/lte-enb-log
mode = 0775
pidfile = {{ directory['log'] }}/enb.log.clean
remove_pidfile = true
[lte-enb-socket]
recipe = slapos.cookbook:wrapper
command = mkfifo {{ directory['run'] }}/enb.sock; cat > {{ directory['run'] }}/enb.sock
destination = ${directory:service}/lte-enb-socket
mode = 0775
cleanup_command = rm -f {{ directory['run'] }}/enb.sock
[lte-enb-service-log]
# enb binary needs upon startup on its STDIN a command where it should log
recipe = slapos.cookbook:wrapper
command = echo "log file.rotate={{ instance['configuration.log_size'] }},file.path={{ directory['log'] }}"\\
> {{ directory['run'] }}/enb.sock; echo "t" > {{ directory['run'] }}/enb.sock
destination = ${directory:script}/lte-enb-service-log
wait-for-files =
{{ directory['run'] }}/enb.sock
{{ directory['run'] }}/enb.pid
#### continue for services MBMS and UE
#### using ltestart.jinja2.sh template from line 200
#!/bin/bash
# Copyright (C) 2012-2015 Amarisoft
# LTE system logger version 2016-10-13
# Path for multi environment support
export PATH="$PATH:/bin/:/usr/bin/:/usr/local/bin"
source /etc/ltestart.conf
while [ "$1" != "" ] ; do
if [ -e "$1" ] ; then
# Avoid storing logs with comments only
HAS_LOG=$(grep -v -l "#" $1)
if [ "$HAS_LOG" != "" ] ; then
DATE=$(date -u +%Y%m%d.%H:%M:%S | sed -e "s/ /-/g")
FILE=$(basename $1)
mv $1 "${LOG_PATH}/${FILE}.${DATE}"
else
rm -f $1
fi
fi
shift
done
#!/bin/bash
# Copyright (C) 2012-2016 Amarisoft
# LTE system starter version 2016-10-13
##################
# Default config #
##################
source {{ directory['etc'] }}/ltestart.conf
# Redirect IO
exec 0>&-
exec 1>>$LOG_FILE
exec 2>>$LOG_FILE
# Termination
function EndOfLTE {
echo "* Stopping LTE service"
# Quit programs and screen windows
for i in 0 1 2 3 ; do
sleep 0.2
{{ screen_bin }} -S lte -p $i -X stuff $'\nquit\n'
done
# Quit
for i in 0 1 2 3 ; do
sleep 0.2
{{ screen_bin }} -S lte -p $i -X stuff $'exit\n'
done
# Save logs
ltelogs.sh {{ directory['log'] }}/ims.log \
{{ directory['log'] }}/mme.log \
{{ directory['log'] }}/enb0.log \
{{ directory['log'] }}/mbmsgw.log
echo "* LTE service stopped"
exit 0
}
trap EndOfLTE KILL INT TERM
# Send command to window
function cmd
{
win="$1"
{{ screen_bin }} -S lte -p $win -X stuff $'\n' # Empty line in case of
while [ "$2" != "" ] ; do
{{ screen_bin }} -S lte -p $win -X stuff "$2"$'\n'
shift
done
}
# Path for multi environment support
export PATH="$PATH:/bin/:/usr/bin/:/usr/local/bin"
echo "* Start LTE service"
# Core dumps
#< In production we don't really want core dumps
#< ulimit -c unlimited
#< echo "/tmp/core" > /proc/sys/kernel/core_pattern
# Logs
LOG_CFG="file.rotate=$LOG_SIZE,file.path=$LOG_PATH"
# Init state
MME_STATE=""
ENB_STATE=""
MBMS_STATE=""
UE_STATE=""
# Poll
while [ 1 ] ; do
##########
# Screen #
##########
SCREEN=$({{ screen_bin }} -ls lte | grep -w lte)
if [ "$SCREEN" = "" ] ; then
echo "* Create screen and initialize windows"
# start a new screen session
{{ screen_bin }} -dm -S lte
# Add windows
sleep 0.1; {{ screen_bin }} -S lte -X screen
sleep 0.1; {{ screen_bin }} -S lte -X screen
sleep 0.1; {{ screen_bin }} -S lte -X screen
cmd 0 'printf "\\033k%s\\033\\\\" MME' 'clear'
cmd 1 'printf "\\033k%s\\033\\\\" eNB' 'clear'
cmd 2 'printf "\\033k%s\\033\\\\" MBMS' 'clear'
cmd 3 'printf "\\033k%s\\033\\\\" IMS' 'clear'
# Set HOME for UHD to find calibration files
cmd $ENB_WIN "export HOME={{ buildout['directory'] }}"
fi
# Update date
DATE=$(date -u +%Y%m%d-%H:%M:%S | sed -e "s/ /-/g")
S1CONNECT=0
#######
# MME #
#######
if [ -e "$MME_PATH/ltemme" ] ; then
# Init
if [ "$MME_STATE" != "done" ] ; then
echo "* Initialize MME with option '$MME_INIT'"
$MME_PATH/lte_init.sh $MME_INIT
if [ "$?" = "0" ] ; then
echo "* MME initialized"
MME_STATE="done"
else
# Configure at least locally to allow LTE local connections
if [ "$MME_STATE" != "LOCAL" ] ; then
echo "* Initialize MME with local interface"
$MME_PATH/lte_init.sh lo
MME_STATE="LOCAL"
fi
fi
fi
MME=$(pgrep ltemme)
if [ "$MME" = "" ] ; then
# "MME not running, start it here"
echo "* Starting MME"
ltelogs.sh {{ directory['log'] }}/mme.log
cmd $MME_WIN "cd $MME_PATH" "./ltemme config/mme.cfg" "log $LOG_CFG"
# Wait for MME to start
sleep 0.5
S1CONNECT=1
fi
#######
# IMS #
#######
if [ -e "$IMS_PATH/lteims" ] ; then
IMS=$(pgrep lteims)
if [ "$IMS" = "" ]; then
# IMS not running, start it here
echo "* Starting IMS"
ltelogs.sh {{ directory['log'] }}/ims.log
cmd $IMS_WIN "cd $IMS_PATH" "./lteims config/ims.cfg" "log $LOG_CFG"
sleep 0.5
cmd $MME_WIN "imsconnect"
cmd $IMS_WIN "t"
fi
fi
fi
#######
# eNB #
#######
if [ -e "$ENB_PATH/lteenb" ] ; then
# Init
if [ "$ENB_STATE" != "done" ] ; then
echo "* Initialize eNB with option '$ENB_INIT'"
$ENB_PATH/lte_init.sh $ENB_INIT
if [ "$?" = "0" ] ; then
ENB_STATE="done"
fi
fi
ENB=$(pgrep lteenb)
if [ "$ENB" = "" ]; then
# Test if Radio head is running to start eNB
if [ -e "${ENB_PATH}/config/rf_driver/rrh_check.sh" ] ; then
${ENB_PATH}/config/rf_driver/rrh_check.sh $RRH_CFG
RRH="$?"
else
RRH="0"
fi
if [ "$RRH" = "0" ] ; then
# "eNodeB not running, start it here"
echo "* Starting eNB"
ltelogs.sh {{ directory['log'] }}/enb0.log
cmd $ENB_WIN "cd $ENB_PATH" "./lteenb config/enb.cfg" "log $LOG_CFG" "t"
fi
else
# Force S1 connection ?
if [ "$S1CONNECT" = "1" ] ; then
cmd "ENB" "cd $ENB_PATH" "s1connect" "t"
fi
fi
fi
########
# MBMS #
########
if [ -d "$MBMS_PATH" ] ; then
# Init
if [ "$MBMS_STATE" != "done" ] ; then
echo "* Initialize MBMSGW with option '$MBMS_INIT'"
$MBMS_PATH/lte_init.sh $MBMS_INIT
if [ "$?" = "0" ] ; then
MBMS_STATE="done"
fi
fi
MBMS=$(pgrep ltembmsgw)
if [ "$MBMS" = "" ]; then
# MBMS not running, start it here
echo "* Starting MBMSGW"
ltelogs.sh {{ directory['log'] }}/mbmsgw.log
cmd $MBMS_WIN "cd $MBMS_PATH" "./ltembmsgw config/mbmsgw.cfg" "log $LOG_CFG"
fi
fi
######
# UE #
######
if [ -e "$UE_PATH/lteue" ] ; then
# Init
if [ "$UE_STATE" != "done" ] ; then
echo "* Initialize UE"
if [ -e "${UE_PATH}/config/rf_driver/rrh_check.sh" ] ; then
${UE_PATH}/config/rf_driver/rrh_check.sh $RRH_CFG
fi
$UE_PATH/lte_init.sh $UE_INIT
if [ "$?" = "0" ] ; then
UE_STATE="done"
fi
fi
fi
# Remove core dumps older than 30min
find /tmp/ -name "core*" -mmin 30 | xargs rm -f
# Compress logs if needed
if [ "$LOG_GZIP" = "1" ] ; then
LIST=$(find $LOG_PATH -type f -name "*log*" | grep -v "gz$")
for i in $LIST ; do
gzip $i
break; # One by one as it may last a while
done
fi
# Remove logs if too much
while [ $(du -ks $LOG_PATH | cut -d $'\t' -f1) -gt $LOG_PERSISTENT_SIZE ] ; do
FILES=$(ls -a $LOG_PATH)
for i in $FILES ; do
if [ -f $LOG_PATH/$i ] ; then
rm $LOG_PATH/$i;
break
fi
done
done
# 5s polling
sleep 5
done
LTE eNodeB software release
###########################
This is a try for standalone unprivileged run of Amarisoft's LTE stack.
The successful setup consists of
1. Ansible: compilation and installation of necessary kernel module: lte_trx_sdr
2. Initialization run as root (either by "format" or manualy)
3. Deployment of this Software Release.
Original install.sh script was replaced by software.cfg and instance.cfg to
setup the paths so that we can run more instances on one machine.
slapos.cookbook:wrapper modification
------------------------------------
This instance.cfg is using updated slapos.cookbook:wrapper with ``remove_pidfile``
and ``cleanup_command``. Both options add functionality to generated ``sh`` script
using ``trap`` for INT, TERM and KILL signal.
- ``remove_pidfile`` removes pidfile upon exit,
- ``cleanup_command``runs arbitrary cleanup command specified by the user.
instance.cfg explained
----------------------
instance.cfg is rather complicated because Amarisoft LTE stack consists of 4 binaries
* **lteenb** - eNodeB software is the server accepting connection from UI (user interfaces)
* **ltemme** - base (core) network which handles orchestration of eNodeBs in case UI switches from
one to another
* **lteims** - no idea
* **ltembmsgw** - no idea
Those binaries are started in foreground, originaly in screen. They *communicate with each other*
using ``stdin`` based on their inner state. Thus we use *named pipes* to enable the inteprocess
communication.
We don't want the binaries inside one screen because then we cannot easily control their resource
usage and we will not see them separately inside webrunner or have separate access to their services.
Every binary expects "log" command after startup. Let's show it on ``mme`` binary.
# ``lte-mme-log`` cleans up old logs
# ``lte-mme-socket`` opens a socket using mkfifo
# ``lte-mme-service`` launches the actual mme binary when the socket is available
# ``lte-mme-service-log`` writes the "log" command into mme binary when it launches
One good example is script ``lte-register-ims-with-mme`` which registers newly started ``ims``
within ``mme`` using mentioned socket.
[buildout]
extends =
../../stack/slapos.cfg
../../component/gzip/buildout.cfg
# ../../component/apache-php/buildout.cfg
parts =
slapos-cookbook
instance-profile
# apache-php
gzip
[instance-profile]
recipe = slapos.recipe.template:jinja2
template = ${:_profile_base_location_}/instance.jinja2.cfg
rendered = ${buildout:directory}/instance.cfg
mode = 0644
extensions = jinja2.ext.do
context =
section buildout buildout
[copy-to-instance]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:_buildout_section_name_}
destination = ${buildout:directory}/${:_buildout_section_name_}
[ltestart.jinja2.conf]
<= copy-to-instance
[lteenb-linux-2016-10-13.tar.gz]
<= copy-to-instance
[ltembmsgw-linux-2016-10-13.tar.gz]
<= copy-to-instance
[ltemme-linux-2016-10-13.tar.gz]
<= copy-to-instance
# lteots-linux-2016-10-13.tar.gz
# is just install utilities which we will not use
# trx_sdr-linux-2016-10-13.tar.gz
# is a kernel module thus needs to be installed in advance
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment