Commit 9b946a02 authored by Lu Xu's avatar Lu Xu 👀

Update Release Candidate

parents 6f952da3 d3ce078f
......@@ -27,26 +27,28 @@ environment =
url = https://releases.pagure.org/liberation-fonts/liberation-fonts-ttf-2.00.1.tar.gz
md5sum = 5c781723a0d9ed6188960defba8e91cf
# IPAex and IPA Font - Japanese fonts provided by IPA
# http://ipafont.ipa.go.jp/
# IPAex and IPA Fonts - Japanese fonts provided by IPA
# https://moji.or.jp/ipafont/
[ipaex-fonts]
<= fonts-base
url = https://osdn.net/frs/redir.php?f=ipafonts%2F57330%2FIPAexfont00201.zip
md5sum = 7bf84182a04a9632268dbcb03f100d05
url = https://archive.debian.org/debian-archive/debian/pool/main/f/fonts-ipaexfont/fonts-ipaexfont_00201.orig.tar.xz
md5sum = 4d75fe25053ea157b674d7cffb0fc001
[ipa-fonts]
<= fonts-base
url = https://osdn.net/frs/redir.php?f=ipafonts%2F51868%2FIPAfont00303.zip
md5sum = 39a828acf27790adbe4944dfb4d94bb1
url = https://archive.debian.org/debian-archive/debian/pool/main/f/fonts-ipafont/fonts-ipafont_00303.orig.tar.gz
md5sum = 0cd89e91c3930f1df3ba3d4b5d9fdef6
# OCR B Font - Optical Recognition Font from the Tsukurimashou Project
# https://tsukurimashou.osdn.jp/ocr.php
[ocrb-fonts]
<= fonts-base
url = https://osdn.net/frs/redir.php?f=tsukurimashou%2F56948%2Focr-0.2.zip
md5sum = 9f2acd83291a31dbe053912f4115db75
url = https://archive.debian.org/debian-archive/debian/pool/main/f/fonts-ocr-b/fonts-ocr-b_0.2~dfsg1.orig.tar.gz
md5sum = 4472f6a18bb0fb15bb77fc7504da63c2
[android-fonts]
<= fonts-base
url = http://archive.debian.org/debian-archive/debian/pool/main/f/fonts-android/fonts-android_4.3.orig.tar.xz
url = https://archive.debian.org/debian-archive/debian/pool/main/f/fonts-android/fonts-android_4.3.orig.tar.xz
md5sum = 2d41d5342eb5f61591ddeec5b80da74d
# The DejaVu fonts are a font family based upon Bitstream Vera v1.10. Its purpose is to
......
......@@ -6,7 +6,7 @@ parts = jsl
[jsl]
recipe = slapos.recipe.build
url = http://www.javascriptlint.com/download/jsl-0.3.0-src.tar.gz
url = https://src.fedoraproject.org/repo/pkgs/rpms/jsl/jsl-0.3.0-src.tar.gz/${:md5sum}/jsl-0.3.0-src.tar.gz
md5sum = 2b94ffa4fab07acabe0c5e73cd49bcdf
init =
import os
......
......@@ -3,9 +3,13 @@
[buildout]
extends =
../autoconf/buildout.cfg
../automake/buildout.cfg
../bzip2/buildout.cfg
../imagemagick/buildout.cfg
../jbigkit/buildout.cfg
../libtool/buildout.cfg
../m4/buildout.cfg
../patch/buildout.cfg
../zlib/buildout.cfg
parts =
......@@ -15,22 +19,30 @@ parts =
[libdmtx]
recipe = slapos.recipe.cmmi
shared = true
url = http://prdownloads.sourceforge.net/libdmtx/libdmtx-0.7.4.tar.bz2
md5sum = d3a4c0becd92895eb606dbdb78b023e2
pre-configure =
./autogen.sh
url = https://github.com/dmtx/libdmtx/archive/refs/tags/v0.7.4.tar.gz
md5sum = aee0184c1374242996c9991a3133ada9
configure-options =
--disable-static
environment =
PATH=${m4:location}/bin:${autoconf:location}/bin:${automake:location}/bin:${pkgconfig:location}/bin:${libtool:location}/bin:%(PATH)s
ACLOCAL_PATH=${pkgconfig:location}/share/aclocal:${libtool:location}/share/aclocal
[dmtx-utils]
recipe = slapos.recipe.cmmi
url = http://prdownloads.sourceforge.net/libdmtx/dmtx-utils-0.7.4.tar.bz2
md5sum = b132ab9fb1d289869469b8bb4959a08a
pre-configure =
./autogen.sh
url = https://github.com/dmtx/dmtx-utils/archive/refs/tags/v0.7.4.tar.gz
md5sum = cefffcdfd02d90b668dac6c24215a17c
configure-options =
--disable-static
patch-options = -p1
patches =
${:_profile_base_location_}/imagemagick-7.patch#e0ec31041be5a4f3551ab84696671110
${:_profile_base_location_}/imagemagick-7.patch#7fcbbfe7f15b92ac840efb2d13729582
environment =
PATH=${patch:location}/bin:${pkgconfig:location}/bin:%(PATH)s
PATH=${m4:location}/bin:${autoconf:location}/bin:${automake:location}/bin:${pkgconfig:location}/bin:${libtool:location}/bin:${patch:location}/bin:%(PATH)s
PKG_CONFIG_PATH=${imagemagick:location}/lib/pkgconfig:${libdmtx:location}/lib/pkgconfig
CPPFLAGS=-I${libdmtx:location}/include
LDFLAGS=-Wl,-rpath=${jbigkit:location}/lib -Wl,-rpath=${bzip2:location}/lib -Wl,-rpath=${zlib:location}/lib
LDFLAGS=-Wl,-rpath=${jbigkit:location}/lib -Wl,-rpath=${bzip2:location}/lib -Wl,-rpath=${zlib:location}/lib -Wl,-rpath=${libdmtx:location}/lib -L${libdmtx:location}/lib
ACLOCAL_PATH=${pkgconfig:location}/share/aclocal:${libtool:location}/share/aclocal
......@@ -10,64 +10,6 @@ diff -ur dmtx-utils-0.7.4.orig/configure.ac dmtx-utils-0.7.4/configure.ac
AC_SUBST(MAGICK_CFLAGS)
AC_SUBST(MAGICK_LIBS)
fi
diff -ur dmtx-utils-0.7.4.orig/configure dmtx-utils-0.7.4/configure
--- dmtx-utils-0.7.4.orig/configure 2011-06-03 07:13:53.000000000 +0200
+++ dmtx-utils-0.7.4/configure 2016-05-06 22:56:40.641701426 +0200
@@ -11074,12 +11074,12 @@
pkg_cv_MAGICK_CFLAGS="$MAGICK_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Wand >= 6.2.4\""; } >&5
- ($PKG_CONFIG --exists --print-errors "Wand >= 6.2.4") 2>&5
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"MagickWand >= 6.2.4\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "MagickWand >= 6.2.4") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- pkg_cv_MAGICK_CFLAGS=`$PKG_CONFIG --cflags "Wand >= 6.2.4" 2>/dev/null`
+ pkg_cv_MAGICK_CFLAGS=`$PKG_CONFIG --cflags "MagickWand >= 6.2.4" 2>/dev/null`
else
pkg_failed=yes
fi
@@ -11090,12 +11090,12 @@
pkg_cv_MAGICK_LIBS="$MAGICK_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Wand >= 6.2.4\""; } >&5
- ($PKG_CONFIG --exists --print-errors "Wand >= 6.2.4") 2>&5
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"MagickWand >= 6.2.4\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "MagickWand >= 6.2.4") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- pkg_cv_MAGICK_LIBS=`$PKG_CONFIG --libs "Wand >= 6.2.4" 2>/dev/null`
+ pkg_cv_MAGICK_LIBS=`$PKG_CONFIG --libs "MagickWand >= 6.2.4" 2>/dev/null`
else
pkg_failed=yes
fi
@@ -11115,18 +11115,18 @@
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
- MAGICK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "Wand >= 6.2.4" 2>&1`
+ MAGICK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "MagickWand >= 6.2.4" 2>&1`
else
- MAGICK_PKG_ERRORS=`$PKG_CONFIG --print-errors "Wand >= 6.2.4" 2>&1`
+ MAGICK_PKG_ERRORS=`$PKG_CONFIG --print-errors "MagickWand >= 6.2.4" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$MAGICK_PKG_ERRORS" >&5
- as_fn_error $? "dmtxread/dmtxwrite requires Wand >= 6.2.4" "$LINENO" 5
+ as_fn_error $? "dmtxread/dmtxwrite requires MagickWand >= 6.2.4" "$LINENO" 5
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- as_fn_error $? "dmtxread/dmtxwrite requires Wand >= 6.2.4" "$LINENO" 5
+ as_fn_error $? "dmtxread/dmtxwrite requires MagickWand >= 6.2.4" "$LINENO" 5
else
MAGICK_CFLAGS=$pkg_cv_MAGICK_CFLAGS
MAGICK_LIBS=$pkg_cv_MAGICK_LIBS
diff -ur dmtx-utils-0.7.4.orig/dmtxread/dmtxread.c dmtx-utils-0.7.4/dmtxread/dmtxread.c
--- dmtx-utils-0.7.4.orig/dmtxread/dmtxread.c 2011-06-03 07:13:10.000000000 +0200
+++ dmtx-utils-0.7.4/dmtxread/dmtxread.c 2016-05-06 23:17:08.190667778 +0200
......
......@@ -9,8 +9,8 @@ parts =
[libjpeg]
recipe = slapos.recipe.cmmi
shared = true
url = http://www.ijg.org/files/jpegsrc.v9d.tar.gz
md5sum = 693a4e10906e66467ca21f045547fe15
url = https://www.ijg.org/files/jpegsrc.v9e.tar.gz
md5sum = 2489f1597b046425f5fcd3cf2df7d85f
configure-options =
--disable-static
......
......@@ -9,8 +9,8 @@ parts =
[libzmq]
recipe = slapos.recipe.cmmi
shared = true
url = http://download.zeromq.org/zeromq-4.1.4.tar.gz
md5sum = a611ecc93fffeb6d058c0e6edf4ad4fb
url = https://github.com/zeromq/zeromq4-1/releases/download/v4.1.6/zeromq-4.1.6.tar.gz
md5sum = c89db4dbc0b90c34c9f4983cbff6d321
configure-options =
--without-documentation
environment =
......
......@@ -7,5 +7,5 @@ parts =
[perl-Image-ExifTool]
<= perl-CPAN-package
module = Image/Image-ExifTool
version = 12.30
md5sum = 1f5d66d62418c8b29eb0c0b7fd272b28
version = 12.60
md5sum = ab1b5d756aaa8188890afa5a16563f57
......@@ -20,8 +20,8 @@ parts =
[subversion]
recipe = slapos.recipe.cmmi
shared = true
url = https://downloads.apache.org/subversion/subversion-1.14.1.tar.bz2
md5sum = 2eccc2c7451397e01a13682600af9563
url = https://downloads.apache.org/subversion/subversion-1.14.2.tar.bz2
md5sum = 9927b167d1c67d663ca63125907f6f69
configure-options =
--disable-static
--with-apr=${apr:location}
......
......@@ -7,7 +7,7 @@ parts = tokyocabinet
[tokyocabinet]
recipe = slapos.recipe.cmmi
shared = true
url = http://fallabs.com/tokyocabinet/tokyocabinet-1.4.48.tar.gz
url = https://dbmx.net/tokyocabinet/tokyocabinet-1.4.48.tar.gz
md5sum = fd03df6965f8f56dd5b8518ca43b4f5e
configure-options =
......
......@@ -10,7 +10,7 @@ extends =
[xmlsec]
recipe = slapos.recipe.cmmi
url = https://www.aleksey.com/xmlsec/download/xmlsec1-1.2.34.tar.gz
url = https://www.aleksey.com/xmlsec/download/older-releases/xmlsec1-1.2.34.tar.gz
md5sum = 87b0074e7ae535e061acf8ef64dada1b
shared = true
configure-options =
......@@ -22,5 +22,5 @@ environment =
[xmlsec:python2]
# Newer versions are not compatible with python2 version of python-xmlsec
url = https://www.aleksey.com/xmlsec/download/xmlsec1-1.2.30.tar.gz
url = https://www.aleksey.com/xmlsec/download/older-releases/xmlsec1-1.2.30.tar.gz
md5sum = b66ec21e0a0ac331afb4b1bc5c9ef966
......@@ -279,7 +279,6 @@
"default": "virtio",
"enum": [
"ide",
"scsi",
"sd",
"mtd",
"floppy",
......
......@@ -53,7 +53,6 @@
"default": "virtio",
"enum": [
"ide",
"scsi",
"sd",
"mtd",
"floppy",
......
......@@ -30,11 +30,13 @@ import glob
import hashlib
import json
import os
import psutil
import re
import requests
import shutil
import subprocess
import tempfile
import time
import xml.etree.ElementTree as ET
from cryptography import x509
from cryptography.hazmat.backends import default_backend
......@@ -75,6 +77,141 @@ class ServicesTestCase(SlapOSInstanceTestCase):
self.assertIn(expected_process_name, process_names)
def test_monitor_httpd_normal_reboot(self):
# Start the monitor-httpd service
with self.slap.instance_supervisor_rpc as supervisor:
info, = [i for i in
supervisor.getAllProcessInfo() if ('monitor-httpd' in i['name']) and ('on-watch' in i['name'])]
partition = info['group']
if info['statename'] != "RUNNING":
monitor_httpd_process_name = f"{info['group']}:{info['name']}"
supervisor.startProcess(monitor_httpd_process_name)
for _retries in range(20):
time.sleep(1)
info, = [i for i in
supervisor.getAllProcessInfo() if ('monitor-httpd' in i['name']) and ('on-watch' in i['name'])]
if info['statename'] == "RUNNING":
break
else:
self.fail(f"the supervisord service '{monitor_httpd_process_name}' is not running")
# Get the partition path
partition_path_list = glob.glob(os.path.join(self.slap.instance_directory, '*'))
for partition_path in partition_path_list:
if os.path.exists(os.path.join(partition_path, 'etc', 'monitor-httpd.conf')):
self.partition_path = partition_path
break
# Make sure we are focusing the same httpd service
self.assertIn(partition, self.partition_path)
# Get the monitor-httpd-service
monitor_httpd_service_path = glob.glob(os.path.join(
self.partition_path, 'etc', 'service', 'monitor-httpd*'
))[0]
try:
output = subprocess.check_output([monitor_httpd_service_path], timeout=10, stderr=subprocess.STDOUT, text=True)
# If the httpd-monitor service is running
# and the monitor-httpd.pid contains the identical PID as the servicse
# run the monitor-httpd service can cause the "already running" error correctly
self.assertIn("already running", output)
except subprocess.CalledProcessError as e:
self.logger.debug("Unexpected error when running the monitor-httpd service:", e)
self.fail("Unexpected error when running the monitor-httpd service")
except subprocess.TimeoutExpired as e:
# Timeout means we run the httpd service corrrectly
# This is not the expected behaviour
self.logger.debug("Unexpected behaviour: We are not suppose to be able to run the httpd service in the test:", e)
# Kill the process that we started manually
# Get the pid of the monitor_httpd from the PID file
monitor_httpd_pid_file = os.path.join(self.partition_path, 'var', 'run', 'monitor-httpd.pid')
monitor_httpd_pid = ""
if os.path.exists(monitor_httpd_pid_file):
with open(monitor_httpd_pid_file, "r") as pid_file:
monitor_httpd_pid = pid_file.read()
try:
pid_to_kill = monitor_httpd_pid.strip('\n')
subprocess.run(["kill", "-9", str(pid_to_kill)], check=True)
self.logger.debug(f"Process with PID {pid_to_kill} killed.")
except subprocess.CalledProcessError as e:
self.logger.debug(f"Error killing process with PID {pid_to_kill}: {e}")
self.fail("Unexpected behaviour: We are not suppose to be able to run the httpd service in the test")
with self.slap.instance_supervisor_rpc as supervisor:
info, = [i for i in
supervisor.getAllProcessInfo() if ('monitor-httpd' in i['name']) and ('on-watch' in i['name'])]
partition = info['group']
if info['statename'] == "RUNNING":
monitor_httpd_process_name = f"{info['group']}:{info['name']}"
supervisor.stopProcess(monitor_httpd_process_name)
def test_monitor_httpd_crash_reboot(self):
# Get the partition path
partition_path_list = glob.glob(os.path.join(self.slap.instance_directory, '*'))
for partition_path in partition_path_list:
if os.path.exists(os.path.join(partition_path, 'etc', 'monitor-httpd.conf')):
self.partition_path = partition_path
break
# Get the pid file
monitor_httpd_pid_file = os.path.join(self.partition_path, 'var', 'run', 'monitor-httpd.pid')
with self.slap.instance_supervisor_rpc as supervisor:
info, = [i for i in
supervisor.getAllProcessInfo() if ('monitor-httpd' in i['name']) and ('on-watch' in i['name'])]
if info['statename'] == "RUNNING":
monitor_httpd_process_name = f"{info['group']}:{info['name']}"
supervisor.stopProcess(monitor_httpd_process_name)
# Write the PID of the infinite process to the pid file.
with open(monitor_httpd_pid_file, "w") as file:
file.write(str(os.getpid()))
# Get the monitor-httpd-service
monitor_httpd_service_path = glob.glob(os.path.join(
self.partition_path, 'etc', 'service', 'monitor-httpd*'
))[0]
monitor_httpd_service_is_running = False
# Create the subprocess
self.logger.debug("Ready to run the process in crash reboot")
try:
process = subprocess.Popen(monitor_httpd_service_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
stdout, stderr = '', ''
try:
# Wait for the process to finish, but with a timeout
stdout, stderr = process.communicate(timeout=3)
self.logger.debug("Communicated!")
except subprocess.TimeoutExpired:
monitor_httpd_service_is_running = True # We didn't get any output within 3 seconds, this means everything is fine.
# If the process times out, terminate it
try:
main_process = psutil.Process(process.pid)
child_processes = main_process.children(recursive=True)
for process in child_processes + [main_process]:
process.terminate()
psutil.wait_procs(child_processes + [main_process])
self.logger.debug(f"Processes with PID {process.pid} and its subprocesses terminated.")
except psutil.NoSuchProcess as e:
# This print will generate ResourceWarningm but it is normal in Python 3
# See https://github.com/giampaolo/psutil/blob/master/psutil/tests/test_process.py#L1526
self.logger.debug("No process found with PID: %s" % process.pid)
# "httpd (pid 21934) already running" means we start httpd failed
if "already running" in stdout:
self.fail("Unexepected output from the monitor-httpd process: %s" % stdout)
raise Exception("Unexepected output from the monitor-httpd process: %s" % stdout)
except subprocess.CalledProcessError as e:
self.logger.debug("Unexpected error when running the monitor-httpd service:", e)
self.fail("Unexpected error when running the monitor-httpd service")
self.assertTrue(monitor_httpd_service_is_running)
class MonitorTestMixin:
monitor_setup_url_key = 'monitor-setup-url'
......
......@@ -54,7 +54,7 @@ class enbWebSocket:
"rf": True
})
r = self.recv('stats')
self.logger.info('Samples stats', extra={'data': r})
self.logger.info('Samples stats', extra={'data': json.dumps(r)})
if __name__ == '__main__':
ws = enbWebSocket()
......
......@@ -16,31 +16,43 @@
[template]
filename = instance.cfg
md5sum = 50e83105328c6434ba94f77c5753cbf8
md5sum = bc60058a9407fc481b1a652b2f3b5498
[amarisoft-stats.jinja2.py]
_update_hash_filename_ = amarisoft-stats.jinja2.py
md5sum = 6e0a052bd0ca08cc0c7b4880d3deffcc
md5sum = c4d5e9fcf460d88bc2b4bcfbdfe554f7
[amarisoft-rf-info.jinja2.py]
_update_hash_filename_ = amarisoft-rf-info.jinja2.py
md5sum = c930c28365c685a6066f382c9b5d8893
[ncclient_common]
_update_hash_filename_ = ncclient_common.py
md5sum = f34a196e947fa58b141431a00cc744df
[lopcomm-rrh-stats.jinja2.py]
_update_hash_filename_ = lopcomm-rrh-stats.jinja2.py
md5sum = f0451b3c2494f103042bda04433c943d
md5sum = b861ef43beba4a0a2904e8c2aee04723
[lopcomm-rrh-config.jinja2.py]
_update_hash_filename_ = lopcomm-rrh-config.jinja2.py
md5sum = b34fe47a73890097fbc6ea6374aeb38d
md5sum = f2f550b68c8ab243ce1a4bb73a9abc1c
[lopcomm-rrh-software.jinja2.py]
_update_hash_filename_ = lopcomm-rrh-software.jinja2.py
md5sum = 860fa5e5bab65f414535c7e25f622a6c
[lopcomm-rrh-supervision.jinja2.py]
_update_hash_filename_ = lopcomm-rrh-supervision.jinja2.py
md5sum = a2ba0343ddb7f9cf2904a4c5c751f68a
[template-enb]
_update_hash_filename_ = instance-enb.jinja2.cfg
md5sum = 62252527eb4998de5bb23058dbbdbd75
md5sum = 8a47df7cfefa3876afea38ced2c5005f
[template-gnb]
_update_hash_filename_ = instance-gnb.jinja2.cfg
md5sum = b4d7406d9d7df7fafbbf0ddbc792f5fb
md5sum = e758c9358c49360ef0b3db946ab0f493
[template-core-network]
_update_hash_filename_ = instance-core-network.jinja2.cfg
......@@ -64,15 +76,15 @@ md5sum = dcaac06553a3222b14c0013a13f4a149
[enb.jinja2.cfg]
filename = config/enb.jinja2.cfg
md5sum = 1680fde9d6d5f8c1678fb11d7a891191
md5sum = e33bf40dfdb32d91d3a1b3f3a10ede34
[sib23.jinja2.asn]
filename = config/sib23.jinja2.asn
md5sum = 0af07bba51f8d4e773f9bfef4f2ca535
md5sum = a1973ba6e43d40e510d61d461c2d13ac
[gnb.jinja2.cfg]
filename = config/gnb.jinja2.cfg
md5sum = f1e7f37a9c0866c08237b03cecdcd2c7
md5sum = 2f7b70b6225ca94feaf1ba512643b0d1
[ltelogs.jinja2.sh]
filename = ltelogs.jinja2.sh
......@@ -84,7 +96,7 @@ md5sum = 48b577daa5b53c2cf7fe2d30ea9c0235
[dnsmasq.jinja2.cfg]
filename = config/dnsmasq.jinja2.cfg
md5sum = 5f67c7f750e7c7bd9b9839c527a06853
md5sum = ecf6081d1fc76a60ba57f042446bc161
[ims.jinja2.cfg]
filename = config/ims.jinja2.cfg
......@@ -104,7 +116,7 @@ md5sum = e435990eb0a0d4be41efa9bd16dce09b
[cu_config.jinja2.xml]
filename = netconf/cu_config.jinja2.xml
md5sum = 39ef850c68ea6cb1282176e718819c4a
md5sum = d10b063ad4edc760e154f7a8d63bea47
[software.cfg.html]
_update_hash_filename_ = gadget/software.cfg.html
......
Changelog
=========
Version 1.0.336 (2023-09-25)
-------------
* Support on Lopcomm RRH via netconf
- Lopcomm firmware auto-upgrade and verification
- Up to 4T4R
- Netconf access verification promise
- PA output power alarm
- Default value added for B1
* fix some bugs
Version 1.0.332 (2023-09-04)
-------------
......
{% if slapparameter_dict.get('rrh', '') == "Lopcomm ORAN" %}
{% if ru == "lopcomm" %}
dhcp-leasefile={{ directory['etc'] }}/dnsmasq.leases
port=5354
dhcp-range=::1,::1,constructor:{{ slap_configuration.get('tap-name', '') }},ra-names,64,12h
dhcp-range=::1,::1,constructor:{{ slap_configuration.get('tap-name', '') }},ra-names,64,5m
dhcp-host={{ slapparameter_dict.get('rrh_mac_addr', '00:0a:00:00:10:20') }},[{{ netaddr.IPAddress(slap_configuration.get('tap-ipv6-gateway', '')) }}]
dhcp-option=option6:dns-server,[{{ netaddr.IPAddress(slap_configuration.get('tap-ipv6-gateway', '')) + 1 }}],[{{ netaddr.IPAddress(slap_configuration.get('tap-ipv6-gateway', '')) + 2 }}]
dhcp-option=option6:domain-search,bbu.local
# option 17 used for RU callhome
# dhcp-option=option6:17,[{{ netaddr.IPAddress(slap_configuration.get('tap-ipv6-addr', '')) }}]
log-queries
log-dhcp
log-facility={{ directory['home'] }}/var/log/dnsmasq.log
enable-ra
ra-param=adv-send-advert
ra-param=adv-managed-flag
......
......@@ -35,14 +35,14 @@
{% endif %}
log_filename: "{{ directory['log'] }}/enb.log",
{% if slapparameter_dict.get('rrh', 'ORS') == "Lopcomm ORAN" %}
{% if ru == "lopcomm" %}
rf_driver: {
{%- if slapparameter_dict.get('disable_sdr', False) %}
name: "dummy",
{%- else %}
name: "sdr",
{%- endif %}
args: "dev0=
args: "dev0=
{%- for i, k in enumerate(cell_list) %}
{%- set cpri_port = cell_list[k].get('cpri_port_number', i) %}
{%- if i != 0 -%}
......@@ -92,7 +92,7 @@
},
tx_gain: 0,
rx_gain: 0,
{% elif slapparameter_dict.get('rrh', 'ORS') == "ORS" %}
{% elif bbu == "ors" %}
rf_driver: {
{%- if slapparameter_dict.get('disable_sdr', False) %}
name: "dummy",
......@@ -136,11 +136,15 @@
{% endif %}
],
{% if slapparameter_dict.get('mme_list', '') %}
{% if slapparameter_dict.get('use_ipv4', False) %}
gtp_addr: "{{ gtp_addr_v4 }}",
{% else %}
gtp_addr: "{{ gtp_addr_v6 }}",
{% endif %}
{% if slapparameter_dict.get('gtp_addr') %}
gtp_addr: "{{ slapparameter_dict.get('gtp_addr') }}",
{% else %}
{% if slapparameter_dict.get('use_ipv4', False) %}
gtp_addr: "{{ gtp_addr_v6 }}",
{% else %}
gtp_addr: "{{ gtp_addr_v4 }}",
{% endif %}
{% endif %}
{% else %}
gtp_addr: "127.0.1.1",
{% endif %}
......@@ -218,7 +222,7 @@
],
n_antenna_dl: N_ANTENNA_DL,
n_antenna_ul: N_ANTENNA_UL,
{% if slapparameter_dict.get('rrh', 'ORS') == "ORS" %}
{% if bbu == "ors" %}
manual_ref_signal_power: true,
{% endif %}
#if TDD == 1
......
......@@ -7,7 +7,7 @@
{%- endif %}
#define N_ANTENNA_DL {{ slapparameter_dict.get('n_antenna_dl', slap_configuration['configuration.default_n_antenna_dl']) }}
{% if slapparameter_dict.get('rrh', 'ORS') == "M2RU Sunwave" %}
{% if ru == "m2ru" %}
#define N_ANTENNA_UL {{ slapparameter_dict.get('n_antenna_ul', 1) }}
{% else %}
#define N_ANTENNA_UL {{ slapparameter_dict.get('n_antenna_ul', slap_configuration['configuration.default_n_antenna_dl']) }}
......@@ -19,7 +19,7 @@
log_options: "all.level=error,all.max_size=0,nas.level=debug,nas.max_size=1,ngap.level=debug,ngap.max_size=1,xnap.level=debug,xnap.max_size=1,rrc.level=debug,rrc.max_size=1,phy.level=info,file.rotate=1G,file.path=/dev/null",
{% endif %}
log_filename: "{{ directory['log'] }}/gnb.log",
{% if slapparameter_dict.get('rrh', 'ORS') == "M2RU Sunwave" %}
{% if ru == "m2ru" %}
rf_driver: {
{%- if slapparameter_dict.get('disable_sdr', False) %}
name: "dummy",
......@@ -140,7 +140,7 @@
bandwidth: {{ slapparameter_dict.get('nr_bandwidth', slap_configuration['configuration.default_nr_bandwidth']) }},
n_antenna_dl: N_ANTENNA_DL,
n_antenna_ul: N_ANTENNA_UL,
{%- if slapparameter_dict.get('rrh', 'ORS') == "ORS" %}
{%- if bbu == "ors" %}
manual_ref_signal_power: true,
{%- if one_watt == "True" %}
ss_pbch_block_power: {{ (tx_gain | int) - 54 }},
......@@ -257,7 +257,7 @@
prach_config_index: 160,
msg1_subcarrier_spacing: 30,
msg1_fdm: 1,
{% if slapparameter_dict.get('rrh', 'ORS') == "M2RU Sunwave" %}
{% if ru == "m2ru" %}
msg1_frequency_start: 0,
{% else %}
msg1_frequency_start: -1,
......@@ -273,7 +273,7 @@
cb_preambles_per_ssb: 8,
},
pdcch: {
{% if slapparameter_dict.get('rrh', 'ORS') == "M2RU Sunwave" %}
{% if ru == "m2ru" %}
n_rb_coreset0: 48,
n_symb_coreset0: 1,
{% endif %}
......@@ -281,7 +281,7 @@
dedicated_coreset: {
rb_start: -1,
l_crb: -1,
{% if slapparameter_dict.get('rrh', 'ORS') == "M2RU Sunwave" %}
{% if ru == "m2ru" %}
duration: 1,
{% else %}
duration: 0,
......@@ -311,7 +311,7 @@
dmrs_add_pos: 1,
dmrs_type: 1,
dmrs_max_len: 1,
{% if slapparameter_dict.get('rrh', 'ORS') == "M2RU Sunwave" %}
{% if ru == "m2ru" %}
k0: 0,
k1: [ 8, 7, 7, 6, 5, 4, 12, 11 ],
{% elif tdd_config == 3 %}
......@@ -553,7 +553,7 @@
mcs_table: "qam256",
mcs_table_tp: "qam256",
ldpc_max_its: 5,
{% if slapparameter_dict.get('rrh', 'ORS') == "M2RU Sunwave" %}
{% if ru == "m2ru" %}
k2: 4,
msg3_k2: 7,
{% elif tdd_config == 3 %}
......
......@@ -36,7 +36,7 @@
}
},
pdsch-ConfigCommon {
{% if slapparameter_dict.get('rrh', 'ORS') == "ORS" %}
{% if bbu == "ors" %}
{%- if one_watt == "True" %}
referenceSignalPower {{ (tx_gain | int) - 54 }}, /* patched by eNB */
{%- else %}
......
......@@ -56,10 +56,16 @@
"type": "number",
"default": 0
},
"cpri_port": {
"title": "CPRI Port Number",
"description": "CPRI Port Number",
"type": "number",
"default": 0
},
{%- endif %}
{%- if trx == 'cpri' %}
"cpri_mult": {
"title": "cpri_mult",
"title": "CPRI Mult",
"description": "Select the CPRI line bit rate in terms of multiple of option 1 (614.4 Mbps). E.g set 4 for option 3, 8 for option 5 and 16 for option 7.",
"type": "number",
"default": 16,
......@@ -113,19 +119,19 @@
"title": "CPRI RX Delay",
"description": "Delays between TX and RX position in CPRI frame. This should be set to the value of (T2a + T3a - Toffset) provided by the RRH specification.",
"type": "number",
"default": 0
"default": 25.11
},
"cpri_tx_delay": {
"title": "CPRI TX Delay",
"description": "Advances Start of Frame relative to PPS to compensate for delays in transmit line and RRH. This should be set to T12 + T2a.",
"type": "number",
"default": 0
"default": 14.71
},
"cpri_tx_dbm": {
"title": "CPRI TX dBm",
"description": "Optional floating points value in dBm (default 0). Needed by ENB/GNB to have a notion of actual output power. Computed from maximum power output of the RRH for a 0dBFS input signal (full scale). ",
"type": "number",
"default": 0
"default": 63
},
"cpri_port_number": {
"title": "CPRI Port Number",
......@@ -204,41 +210,35 @@
"INACTIVE"
]
},
"txa0cc00_center_frequency_earfcn": {
"title": "Lopcomm ORAN Center Frequency EARFCN (TXA0CC00)",
"description": "Lopcomm ORAN Center Frequency EARFCN (TXA0CC00)",
"type": "number",
"default": 300
},
"txa0cc00_center_frequency": {
"title": "Lopcomm ORAN Center Frequency in Hz (TXA0CC00)",
"description": "Lopcomm ORAN Center Frequency in Hz (TXA0CC00)",
"type": "number",
"default": 2140000000
},
"txa0cc00_bandwidth": {
"title": "Lopcomm ORAN bandwidth in Hz (TXA0CC00)",
"description": "Lopcomm ORAN bandwidth in Hz (TXA0CC00)",
"title": "Lopcomm ORAN DL Center Frequency in MHz (TXA0CC00)",
"description": "Lopcomm ORAN Center Frequency in MHz (TXA0CC00)",
"type": "number",
"default": 20000000
"default": 2140
},
"rxa0cc00_center_frequency_earfcn": {
"title": "Lopcomm ORAN Center Frequency EARFCN (RXA0CC00)",
"title": "Lopcomm ORAN UL Center Frequency EARFCN (RXA0CC00)",
"description": "Lopcomm ORAN Center Frequency EARFCN (RXA0CC00)",
"type": "number",
"default": 18300
},
"rxa0cc00_center_frequency": {
"title": "Lopcomm ORAN Center Frequency in Hz (RXA0CC00)",
"description": "Lopcomm ORAN Center Frequency in Hz (RXA0CC00)",
"title": "Lopcomm ORAN UL Center Frequency in MHz (RXA0CC00)",
"description": "Lopcomm ORAN Center Frequency in MHz (RXA0CC00)",
"type": "number",
"default": 1950000000
"default": 1950
},
"rxa0cc00_bandwidth": {
"title": "Lopcomm ORAN bandwidth in Hz (RXA0CC00)",
"description": "Lopcomm ORAN bandwidth in Hz (RXA0CC00)",
"txa0cc00_gain": {
"title": "ORAN Gain",
"description": "Lopcomm ORAN Gain (TXA0CC00)",
"type": "number",
"default": 20000000
"default": -20
},
"user-authorized-key": {
"title": "User Authorized Key",
"description": "SSH public key in order to connect to the SSH server of this instance.",
"textarea": true,
"type": "string"
},
{%- endif %}
"enb_id": {
......@@ -247,6 +247,12 @@
"type": "string",
"default": "0x1A2D0"
},
"gtp_addr": {
"title": "GTP Address",
"description": "String. Set the IP address (and optional port) on which the GTP-U packets are received. The default port is 2152. It is normally the IP address of the network interface connected to the core network.",
"type": "string",
"default": "127.0.1.1"
},
"mme_list": {
"title": "MME list",
"description": "Optionnal. List of MME to which the gNodeB is connected",
......
......@@ -10,12 +10,22 @@ parts =
{% endif %}
amarisoft-stats-service
amarisoft-rf-info-service
{% if slapparameter_dict.get('rrh', '') == "Lopcomm ORAN" %}
{% if ru == "lopcomm" %}
lopcomm-firmware-dl
lopcomm-rrh-stats-service
lopcomm-rrh-supervision-service
lopcomm-rrh-config-template
lopcomm-rrh-software-template
netconf-connection-promise
firmware-update-promise
rrh-netconf-socket-promise
lopcomm-cu-config
sshd-service
sshd-add-authorized-key
sshd-promise
check-lopcomm-vswr.py
check-lopcomm-pa-current.py
check-lopcomm-pa-output-power.py
check-lopcomm-lof.py
check-lopcomm-rssi.py
check-lopcomm-sync.py
......@@ -29,7 +39,9 @@ parts =
check-sdr-busy.py
check-baseband-latency.py
check-amarisoft-stats-log.py
{% if not ru == "lopcomm" %}
check-rx-saturated.py
{% endif %}
monitor-base
publish-connection-information
......@@ -267,6 +279,7 @@ json-log-output = ${directory:var}/log/lopcomm-rrh-stats.json.log
cfg-json-log-output = ${directory:var}/log/lopcomm-rrh-config.json.log
supervision-json-log-output = ${directory:var}/log/lopcomm-rrh-supervision.json.log
ncsession-json-log-output = ${directory:var}/log/lopcomm-rrh-ncsession.json.log
software-json-log-output = ${directory:var}/log/lopcomm-rrh-software.json.log
context =
section directory directory
section slap_configuration slap-configuration
......@@ -276,8 +289,10 @@ context =
key cfg_json_log_file :cfg-json-log-output
key supervision_json_log_file :supervision-json-log-output
key ncsession_json_log_file :ncsession-json-log-output
key software_json_log_file :software-json-log-output
raw testing {{ slapparameter_dict.get("testing", False) }}
raw python_path {{ buildout_directory}}/bin/pythonwitheggs
raw buildout_directory_path {{ buildout_directory }}
import netaddr netaddr
mode = 0775
url = {{ lopcomm_rrh_stats_template }}
......@@ -303,6 +318,7 @@ context =
key log_file :log-output
raw testing {{ slapparameter_dict.get("testing", False) }}
raw python_path {{ buildout_directory}}/bin/pythonwitheggs
raw buildout_directory_path {{ buildout_directory }}
raw CreateProcessingEle_template {{ CreateProcessingEle_template }}
key cu_config_template lopcomm-cu-config:output
import netaddr netaddr
......@@ -310,6 +326,68 @@ mode = 0775
url = {{ lopcomm_rrh_config_template }}
output = ${directory:script}/lopcomm-rrh-config.py
[lopcomm-rrh-software-template]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
log-output = ${directory:var}/log/lopcomm-rrh-software.log
software-reply-json-log-output = ${directory:var}/log/lopcomm-rrh-software-reply.json.log
remote-file-path = sftp://${user-info:pw-name}@[${slap-configuration:ipv6-random}]:${sshd-port:port}${lopcomm-firmware-dl:destination}
context =
section directory directory
section slap_configuration slap-configuration
key slapparameter_dict slap-configuration:configuration
key log_file :log-output
key software_reply_json_log_file :software-reply-json-log-output
key remote_file_path :remote-file-path
raw testing {{ slapparameter_dict.get("testing", False) }}
raw python_path {{ buildout_directory}}/bin/pythonwitheggs
raw buildout_directory_path {{ buildout_directory }}
raw etc_path ${directory:etc}
raw firmware_name ${lopcomm-firmware-dl:filename}
import netaddr netaddr
mode = 0775
url = {{ lopcomm_rrh_software_template }}
output = ${directory:script}/lopcomm-rrh-software.py
[lopcomm-rrh-supervision-template]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
log-output = ${directory:var}/log/lopcomm-rrh-supervision.log
supervision-reply-json-log-output = ${directory:var}/log/lopcomm-rrh-supervision-reply.json.log
context =
section directory directory
section slap_configuration slap-configuration
key slapparameter_dict slap-configuration:configuration
key log_file :log-output
key supervision_reply_json_log_file :supervision-reply-json-log-output
raw testing {{ slapparameter_dict.get("testing", False) }}
raw python_path {{ buildout_directory}}/bin/pythonwitheggs
raw buildout_directory_path {{ buildout_directory }}
raw etc_path ${directory:etc}
import netaddr netaddr
mode = 0775
url = {{ lopcomm_rrh_supervision_template }}
output = ${directory:bin}/lopcomm-rrh-supervision.py
[netconf-connection-promise]
<= monitor-promise-base
promise = check_command_execute
name = netconf-connection-promise.py
config-command = [ -f ${directory:etc}/is_netconf_connected ]
[firmware-update-promise]
<= monitor-promise-base
promise = check_command_execute
name = firmware-update-promise.py
config-command = [ -f ${directory:etc}/is_firmware_updated ]
[rrh-netconf-socket-promise]
<= monitor-promise-base
promise = check_socket_listening
name = rrh-netconf-socket-promise.py
config-host = ${slap-configuration:tap-ipv6-gateway}
config-port = 830
[amarisoft-stats-service]
recipe = slapos.cookbook:wrapper
command-line = ${amarisoft-stats-template:output}
......@@ -334,6 +412,81 @@ mode = 0775
hash-files =
${lopcomm-rrh-stats-template:output}
[lopcomm-rrh-supervision-service]
recipe = slapos.cookbook:wrapper
command-line = ${lopcomm-rrh-supervision-template:output}
wrapper-path = ${directory:service}/lopcomm-rrh-supervision
mode = 0775
hash-files =
${lopcomm-rrh-supervision-template:output}
[lopcomm-firmware-dl]
recipe = slapos.recipe.build:download
url = https://lab.nexedi.com/nexedi/ors-utils/raw/master/lopcomm-firmware/${:filename}
filename = PR.PRM61C70V1004.002.tar.gz
md5sum = 4e06fd62968f9f53fd819ef8d880a8f4
destination = ${directory:etc}/${:filename}
offline = false
[user-info]
recipe = slapos.cookbook:userinfo
# Deploy openssh-server
[sshd-port]
recipe = slapos.cookbook:free_port
minimum = 22222
maximum = 22231
ip = ${slap-configuration:ipv6-random}
[sshd-config]
recipe = slapos.recipe.template:jinja2
output = ${directory:etc}/sshd.conf
path_pid = ${directory:run}/sshd.pid
inline =
PidFile ${:path_pid}
Port ${sshd-port:port}
ListenAddress ${slap-configuration:ipv6-random}
Protocol 2
HostKey ${sshd-ssh-host-rsa-key:output}
HostKey ${sshd-ssh-host-ecdsa-key:output}
PasswordAuthentication no
PubkeyAuthentication yes
HostKeyAlgorithms ssh-rsa,ssh-dss,rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp521
AuthorizedKeysFile ${buildout:directory}/.ssh/authorized_keys
Subsystem sftp {{ openssh_location }}/libexec/sftp-server
[sshd-service]
recipe = slapos.cookbook:wrapper
command-line = {{ openssh_location }}/sbin/sshd -D -e -f ${sshd-config:output}
wrapper-path = ${directory:service}/sshd
hash-files = ${sshd-config:output}
environment =
HOME=${directory:home}
[sshd-add-authorized-key]
recipe = slapos.cookbook:dropbear.add_authorized_key
home = ${buildout:directory}
key = {{ slapparameter_dict.get("user-authorized-key", '') }}
[sshd-ssh-keygen-base]
recipe = plone.recipe.command
output = ${directory:etc}/${:_buildout_section_name_}
command = {{ openssh_output_keygen }} -f ${:output} -N '' ${:extra-args}
[sshd-ssh-host-rsa-key]
<=sshd-ssh-keygen-base
extra-args=-t rsa
[sshd-ssh-host-ecdsa-key]
<=sshd-ssh-keygen-base
extra-args=-t ecdsa -b 521
[sshd-promise]
<= monitor-promise-base
promise = check_socket_listening
name = sshd.py
config-host = ${slap-configuration:ipv6-random}
config-port = ${sshd-port:port}
[config-base]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
......@@ -380,13 +533,19 @@ websocket_url = ws://[${slap-configuration:ipv6-random}]:9001
{%- endif %}
enb-ipv6 = ${slap-configuration:ipv6-random}
enb-ipv4 = {{ lan_ipv4 }}
{% if bbu == "ors" %}
ors-version = {{ ors_version['ors-version'] }}
frequency-range-rating = {{ ors_version['range'] }}
current-tx-power-estimate = {{ ors_version['power-estimate'] }}
current-tx-gain = {{ ors_version['current-tx-gain'] }}
current-rx-gain = {{ ors_version['current-rx-gain'] }}
{% endif %}
current-earfcn = {{ ors_version['current-earfcn'] }}
monitor-gadget-url = ${:monitor-base-url}/gadget/software.cfg.html
{% if ru == "lopcomm" %}
ssh-command = ssh ${user-info:pw-name}@${slap-configuration:ipv6-random} -p ${sshd-port:port}
ssh-url = ssh://${user-info:pw-name}@[${slap-configuration:ipv6-random}]:${sshd-port:port}
{% endif %}
[monitor-instance-parameter]
{% if slapparameter_dict.get("name", None) %}
......@@ -443,6 +602,13 @@ config-testing = {{ slapparameter_dict.get("testing", False) }}
config-netconf-log = ${lopcomm-rrh-stats-template:json-log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[check-lopcomm-pa-output-power.py]
<= macro.promise
promise = check_lopcomm_pa_output_power
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-netconf-log = ${lopcomm-rrh-stats-template:json-log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[check-lopcomm-sync.py]
<= macro.promise
promise = check_lopcomm_sync
......
......@@ -35,6 +35,12 @@
"type": "number",
"default": 0
},
"cpri_port": {
"title": "CPRI Port Number",
"description": "CPRI Port Number",
"type": "number",
"default": 0
},
"cell_list": {
"title": "Cell List",
"description": "Cell List",
......@@ -79,6 +85,12 @@
"type": "string",
"default": "0x1A2D0"
},
"gtp_addr": {
"title": "GTP Address",
"description": "String. Set the IP address (and optional port) on which the GTP-U packets are received. The default port is 2152. It is normally the IP address of the network interface connected to the core network.",
"type": "string",
"default": "127.0.1.1"
},
"mme_list": {
"title": "MME list",
"description": "Optionnal. List of MME to which the gNodeB is connected",
......
......@@ -35,8 +35,14 @@
"type": "number",
"default": 0
},
"cpri_port": {
"title": "CPRI Port Number",
"description": "CPRI Port Number",
"type": "number",
"default": 0
},
"cpri_mult": {
"title": "cpri_mult",
"title": "CPRI Mult",
"description": "Select the CPRI line bit rate in terms of multiple of option 1 (614.4 Mbps). E.g set 4 for option 3, 8 for option 5 and 16 for option 7.",
"type": "number",
"default": 16,
......@@ -57,19 +63,19 @@
"title": "CPRI RX Delay",
"description": "Delays between TX and RX position in CPRI frame. This should be set to the value of (T2a + T3a - Toffset) provided by the RRH specification.",
"type": "number",
"default": 0
"default": 25.11
},
"cpri_tx_delay": {
"title": "CPRI TX Delay",
"description": "Advances Start of Frame relative to PPS to compensate for delays in transmit line and RRH. This should be set to T12 + T2a.",
"type": "number",
"default": 0
"default": 14.71
},
"cpri_tx_dbm": {
"title": "CPRI TX dBm",
"description": "Optional floating points value in dBm (default 0). Needed by ENB/GNB to have a notion of actual output power. Computed from maximum power output of the RRH for a 0dBFS input signal (full scale). ",
"type": "number",
"default": 0
"default": 63
},
"cpri_port_number": {
"title": "CPRI Port Number",
......@@ -131,41 +137,35 @@
"INACTIVE"
]
},
"txa0cc00_center_frequency_earfcn": {
"title": "Lopcomm ORAN Center Frequency EARFCN (TXA0CC00)",
"description": "Lopcomm ORAN Center Frequency EARFCN (TXA0CC00)",
"type": "number",
"default": 300
},
"txa0cc00_center_frequency": {
"title": "Lopcomm ORAN Center Frequency in Hz (TXA0CC00)",
"description": "Lopcomm ORAN Center Frequency in Hz (TXA0CC00)",
"type": "number",
"default": 2140000000
},
"txa0cc00_bandwidth": {
"title": "Lopcomm ORAN bandwidth in Hz (TXA0CC00)",
"description": "Lopcomm ORAN bandwidth in Hz (TXA0CC00)",
"title": "Lopcomm ORAN DL Center Frequency in MHz (TXA0CC00)",
"description": "Lopcomm ORAN Center Frequency in MHz (TXA0CC00)",
"type": "number",
"default": 20000000
"default": 2140
},
"rxa0cc00_center_frequency_earfcn": {
"title": "Lopcomm ORAN Center Frequency EARFCN (RXA0CC00)",
"title": "Lopcomm ORAN UL Center Frequency EARFCN (RXA0CC00)",
"description": "Lopcomm ORAN Center Frequency EARFCN (RXA0CC00)",
"type": "number",
"default": 18300
},
"rxa0cc00_center_frequency": {
"title": "Lopcomm ORAN Center Frequency in Hz (RXA0CC00)",
"description": "Lopcomm ORAN Center Frequency in Hz (RXA0CC00)",
"title": "Lopcomm ORAN UL Center Frequency in MHz (RXA0CC00)",
"description": "Lopcomm ORAN Center Frequency in MHz (RXA0CC00)",
"type": "number",
"default": 1950000000
"default": 1950
},
"rxa0cc00_bandwidth": {
"title": "Lopcomm ORAN bandwidth in Hz (RXA0CC00)",
"description": "Lopcomm ORAN bandwidth in Hz (RXA0CC00)",
"txa0cc00_gain": {
"title": "ORAN Gain",
"description": "Lopcomm ORAN Gain (TXA0CC00)",
"type": "number",
"default": 20000000
"default": -20
},
"user-authorized-key": {
"title": "User Authorized Key",
"description": "SSH public key in order to connect to the SSH server of this instance.",
"textarea": true,
"type": "string"
},
"enb_id": {
"title": "eNB ID",
......@@ -173,6 +173,12 @@
"type": "string",
"default": "0x1A2D0"
},
"gtp_addr": {
"title": "GTP Address",
"description": "String. Set the IP address (and optional port) on which the GTP-U packets are received. The default port is 2152. It is normally the IP address of the network interface connected to the core network.",
"type": "string",
"default": "127.0.1.1"
},
"mme_list": {
"title": "MME list",
"description": "Optionnal. List of MME to which the gNodeB is connected",
......
......@@ -74,6 +74,12 @@
"type": "string",
"default": "0x1A2D0"
},
"gtp_addr": {
"title": "GTP Address",
"description": "String. Set the IP address (and optional port) on which the GTP-U packets are received. The default port is 2152. It is normally the IP address of the network interface connected to the core network.",
"type": "string",
"default": "127.0.1.1"
},
"mme_list": {
"title": "MME list",
"description": "Optionnal. List of MME to which the gNodeB is connected",
......
......@@ -10,13 +10,6 @@ parts =
{% endif %}
amarisoft-stats-service
amarisoft-rf-info-service
{% if slapparameter_dict.get('rrh', '') == "Lopcomm ORAN" %}
lopcomm-rrh-stats-service
check-lopcomm-vswr.py
check-lopcomm-lof.py
check-lopcomm-rssi.py
check-cpri-lock.py
{% endif %}
check-sdr-busy.py
check-baseband-latency.py
check-amarisoft-stats-log.py
......@@ -324,34 +317,6 @@ config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("gnb_stats_fetch_period", 60) }}
[check-lopcomm-vswr.py]
<= macro.promise
promise = check_lopcomm_vswr
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-netconf-log = ${lopcomm-rrh-stats-template:json-log-output}
config-stats-period = {{ slapparameter_dict.get("gnb_stats_fetch_period", 60) }}
[check-lopcomm-rssi.py]
<= macro.promise
promise = check_lopcomm_rssi
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-netconf-log = ${lopcomm-rrh-stats-template:json-log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[check-lopcomm-lof.py]
<= macro.promise
promise = check_lopcomm_lof
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-netconf-log = ${lopcomm-rrh-stats-template:json-log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[check-cpri-lock.py]
<= macro.promise
promise = check_cpri_lock
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-rf-info-log = ${amarisoft-rf-info-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[check-rx-saturated.py]
<= macro.promise
promise = check_rx_saturated
......
......@@ -45,6 +45,12 @@
"type": "number",
"default": 0
},
"cpri_port": {
"title": "CPRI Port Number",
"description": "CPRI Port Number",
"type": "number",
"default": 0
},
"cell_list": {
"title": "Cell List",
"description": "Cell List",
......@@ -89,6 +95,12 @@
"type": "string",
"default": "0x1A2D0"
},
"gtp_addr": {
"title": "GTP Address",
"description": "String. Set the IP address (and optional port) on which the GTP-U packets are received. The default port is 2152. It is normally the IP address of the network interface connected to the core network.",
"type": "string",
"default": "127.0.1.1"
},
"mme_list": {
"title": "MME list",
"description": "Optionnal. List of MME to which the gNodeB is connected",
......
......@@ -45,8 +45,14 @@
"type": "number",
"default": 0
},
"cpri_port": {
"title": "CPRI Port Number",
"description": "CPRI Port Number",
"type": "number",
"default": 0
},
"cpri_mult": {
"title": "cpri_mult",
"title": "CPRI Mult",
"description": "Select the CPRI line bit rate in terms of multiple of option 1 (614.4 Mbps). E.g set 4 for option 3, 8 for option 5 and 16 for option 7.",
"type": "number",
"default": 16,
......@@ -67,19 +73,19 @@
"title": "CPRI RX Delay",
"description": "Delays between TX and RX position in CPRI frame. This should be set to the value of (T2a + T3a - Toffset) provided by the RRH specification.",
"type": "number",
"default": 0
"default": 25.11
},
"cpri_tx_delay": {
"title": "CPRI TX Delay",
"description": "Advances Start of Frame relative to PPS to compensate for delays in transmit line and RRH. This should be set to T12 + T2a.",
"type": "number",
"default": 0
"default": 14.71
},
"cpri_tx_dbm": {
"title": "CPRI TX dBm",
"description": "Optional floating points value in dBm (default 0). Needed by ENB/GNB to have a notion of actual output power. Computed from maximum power output of the RRH for a 0dBFS input signal (full scale). ",
"type": "number",
"default": 0
"default": 63
},
"cpri_port_number": {
"title": "CPRI Port Number",
......@@ -127,6 +133,12 @@
"type": "string",
"default": "0x1A2D0"
},
"gtp_addr": {
"title": "GTP Address",
"description": "String. Set the IP address (and optional port) on which the GTP-U packets are received. The default port is 2152. It is normally the IP address of the network interface connected to the core network.",
"type": "string",
"default": "127.0.1.1"
},
"mme_list": {
"title": "MME list",
"description": "Optionnal. List of MME to which the gNodeB is connected",
......
......@@ -84,6 +84,12 @@
"type": "string",
"default": "0x1A2D0"
},
"gtp_addr": {
"title": "GTP Address",
"description": "String. Set the IP address (and optional port) on which the GTP-U packets are received. The default port is 2152. It is normally the IP address of the network interface connected to the core network.",
"type": "string",
"default": "127.0.1.1"
},
"mme_list": {
"title": "MME list",
"description": "Optionnal. List of MME to which the gNodeB is connected",
......
......@@ -166,7 +166,7 @@ init =
options['tdd'] = get_sdr_info('t').decode()
options['one-watt'] = bool(options['version'] >= 4)
options['ors-version'] = "{} {} {}".format(
options['tdd'],
options['tdd'],
options['band'],
"2x1W" if options['one-watt'] else "2x0.5W",
)
......@@ -256,6 +256,8 @@ extra-context =
raw amarisoft_rf_info_template ${amarisoft-rf-info.jinja2.py:target}
raw lopcomm_rrh_stats_template ${lopcomm-rrh-stats.jinja2.py:target}
raw lopcomm_rrh_config_template ${lopcomm-rrh-config.jinja2.py:target}
raw lopcomm_rrh_software_template ${lopcomm-rrh-software.jinja2.py:target}
raw lopcomm_rrh_supervision_template ${lopcomm-rrh-supervision.jinja2.py:target}
raw CreateProcessingEle_template ${CreateProcessingEle.jinja2.xml:target}
raw cu_config_template ${cu_config.jinja2.xml:target}
raw openssl_location ${openssl:location}
......@@ -267,6 +269,8 @@ extra-context =
raw dnsmasq_location ${dnsmasq:location}
key dnsmasq_config_path dnsmasq-config:output
raw fluent_bit_location ${fluent-bit:location}
raw openssh_location ${openssh:location}
raw openssh_output_keygen ${openssh-output:keygen}
[dynamic-template-gnb]
< = jinja2-template-base
......@@ -370,4 +374,4 @@ context =
section directory directory
section slap_configuration slap-configuration
key slapparameter_dict slap-configuration:configuration
raw ru ${rf-mode:ru}
#!{{ python_path }}
import logging
import time
import xmltodict
from logging.handlers import RotatingFileHandler
from ncclient import manager
from ncclient.operations import RPCError
from ncclient.xml_ import *
from ncclient.devices.default import DefaultDeviceHandler
class LopcommNetconfClient:
def __init__(self):
log_file = "{{ log_file }}"
self.logger = logging.getLogger('logger')
self.logger.setLevel(logging.DEBUG)
handler = RotatingFileHandler(log_file, maxBytes=100000, backupCount=5)
self.logger.addHandler(handler)
formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
handler.setFormatter(formatter)
if {{ testing }}:
return
def connect(self, host, port, user, password):
if {{ testing }}:
return
self.address = (host, port)
self.logger.info('Connecting to %s, user %s...' % (self.address, user))
self.conn = manager.connect(host=host,
port=port,
username=user,
password=password,
timeout=1800,
device_params={
'name': 'default'
},
hostkey_verify=False)
self.logger.info('Connection to %s successful' % (self.address,))
def edit_config(self, config_files):
for config_file in config_files:
with open(config_file) as f:
config_xml = f.read()
try:
self.logger.info('Sending edit-config RPC request...')
self.conn.edit_config(target='running', config=config_xml)
self.logger.info('Edit-config RPC request sent successfully')
except RPCError as e:
self.logger.error('Error sending edit-config RPC request: %s' % e)
def close(self):
# Close not compatible between ncclient and netconf server
#self.conn.close()
pass
import sys
sys.path.append({{ repr(buildout_directory_path) }})
from ncclient_common import LopcommNetconfClient
if __name__ == '__main__':
nc = LopcommNetconfClient()
while True:
try:
nc.connect("{{ netaddr.IPAddress(slap_configuration.get('tap-ipv6-gateway', '')) }}", 830, "oranuser", "oranpassword")
nc.edit_config(["{{ CreateProcessingEle_template }}", "{{ cu_config_template }}"])
break
except Exception as e:
nc.logger.debug('Got exception, waiting 10 seconds before reconnecting...')
nc.logger.debug(e)
time.sleep(10)
finally:
nc.close()
nc = LopcommNetconfClient(log_file="{{ log_file }}")
while True:
try:
nc.connect("{{ netaddr.IPAddress(slap_configuration.get('tap-ipv6-gateway', '')) }}", 830, "oranuser", "oranpassword")
nc.edit_config(["{{ CreateProcessingEle_template }}", "{{ cu_config_template }}"])
break
except Exception as e:
nc.logger.debug('Got exception, waiting 10 seconds before reconnecting...')
nc.logger.debug(e)
time.sleep(10)
finally:
nc.close()
#!{{ python_path }}
import time
import sys
sys.path.append({{ repr(buildout_directory_path) }})
from ncclient_common import LopcommNetconfClient
if __name__ == '__main__':
nc = LopcommNetconfClient(log_file="{{ log_file }}")
while True:
try:
nc.connect("{{ netaddr.IPAddress(slap_configuration.get('tap-ipv6-gateway', '')) }}", 830, "oranuser", "oranpassword")
nc.nc.reset_device()
break
except Exception as e:
nc.logger.debug('Got exception, waiting 10 seconds before reconnecting...')
nc.logger.debug(e)
time.sleep(10)
finally:
nc.close()
#!{{ python_path }}
import time
import xmltodict
import sys
import re
import os
sys.path.append({{ repr(buildout_directory_path) }})
from ncclient_common import LopcommNetconfClient
if __name__ == '__main__':
nc = LopcommNetconfClient(
log_file="{{ log_file }}",
software_reply_json_log_file="{{ software_reply_json_log_file }}"
)
while True:
try:
firmware_check_file= os.path.join('{{etc_path}}','is_firmware_updated')
nc.connect("{{ netaddr.IPAddress(slap_configuration.get('tap-ipv6-gateway', '')) }}", 830, "oranuser", "oranpassword")
# Fetch software inventory
inventory_vars = nc.get_inventory()
nonrunning_slot_name = inventory_vars["nonrunning_slot_name"]
running_slot_name = inventory_vars["running_slot_name"]
active_nonrunning_slot_name = inventory_vars["active_nonrunning_slot_name"]
nonrunning_slot_name_build_version = inventory_vars["nonrunning_slot_name_build_version"]
running_slot_name_build_version = inventory_vars["running_slot_name_build_version"]
if running_slot_name and nonrunning_slot_name:
if running_slot_name:
nc.logger.info("One slot is running and one is non-running. Proceeding...")
if running_slot_name_build_version in "{{firmware_name}}":
if not os.path.exists(firmware_check_file):
open(firmware_check_file, "w").write('True')
nc.logger.info("Running slot's build-version %s is already updated. Skipping install." % running_slot_name_build_version)
else:
if os.path.exists(firmware_check_file):
os.remove(firmware_check_file)
nc.logger.info("Current build version: %s" % running_slot_name_build_version)
user_authorized_key ="""{{ slapparameter_dict.get('user-authorized-key', '') }}"""
match = re.match(r'ssh-rsa ([^\s]+)', user_authorized_key)
if match:
extracted_key = match.group(1)
else:
nc.logger.info("No valid key found in user authorized key.")
download_rpc_xml = f"""
<software-download xmlns="urn:o-ran:software-management:1.0">
<remote-file-path>{{remote_file_path}}</remote-file-path>
<server>
<keys>
<algorithm xmlns:ct="urn:ietf:params:xml:ns:yang:ietf-crypto-types">1024</algorithm>
<public-key>{extracted_key}</public-key>
</keys>
</server>
</software-download>
"""
download_reply_xml = nc.custom_rpc_request(download_rpc_xml)
nc.logger.info("Downloading software...")
time.sleep(60)
if download_reply_xml:
nc.logger.info("Download proceed.")
download_data = xmltodict.parse(download_reply_xml)
nc.software_reply_json_logger.info('', extra={'data': download_data})
install_rpc_xml = f"""
<software-install xmlns="urn:o-ran:software-management:1.0">
<slot-name>{nonrunning_slot_name}</slot-name>
<file-names>{{firmware_name}}</file-names>
</software-install>
"""
install_reply_xml = nc.custom_rpc_request(install_rpc_xml)
nc.logger.info("Installing software...")
time.sleep(60)
if install_reply_xml:
nc.logger.info("Installation proceed.")
install_data = xmltodict.parse(install_reply_xml)
nc.software_reply_json_logger.info('', extra={'data': install_data})
if nonrunning_slot_name_build_version in "{{firmware_name}}":
activate_rpc_xml = f"""
<software-activate xmlns="urn:o-ran:software-management:1.0">
<slot-name>{nonrunning_slot_name}</slot-name>
</software-activate>
"""
activate_reply_xml = nc.custom_rpc_request(activate_rpc_xml)
nc.logger.info("Activating software...")
time.sleep(60)
if activate_reply_xml:
nc.logger.info("Activation proceed.")
activate_data = xmltodict.parse(activate_reply_xml)
nc.software_reply_json_logger.info('', extra={'data': activate_data})
nc.get_inventory()
if nonrunning_slot_name_build_version in "{{firmware_name}}" and active_nonrunning_slot_name:
nc.logger.info("Active non-running slot has the updated build version. Resetting device.")
nc.reset_device()
break
except Exception as e:
nc.logger.debug('Got exception, waiting 10 seconds before reconnecting...')
nc.logger.debug(str(e))
time.sleep(10)
finally:
nc.close()
#!{{ python_path }}
import json
import logging
import time
import xmltodict
from logging.handlers import RotatingFileHandler
from ncclient import manager
from ncclient.xml_ import *
from ncclient.devices.default import DefaultDeviceHandler
class LopcommNetconfClient:
def __init__(self):
log_file = "{{ log_file }}"
json_log_file = "{{ json_log_file }}"
cfg_json_log_file = "{{ cfg_json_log_file }}"
supervision_json_log_file = "{{ supervision_json_log_file }}"
ncsession_json_log_file = "{{ ncsession_json_log_file }}"
self.logger = logging.getLogger('logger')
self.json_logger = logging.getLogger('json_logger')
self.cfg_json_logger = logging.getLogger('cfg_json_logger')
self.supervision_json_logger = logging.getLogger('supervision_json_logger')
self.ncsession_json_logger = logging.getLogger('ncsession_json_logger')
self.logger.setLevel(logging.DEBUG)
self.json_logger.setLevel(logging.DEBUG)
self.cfg_json_logger.setLevel(logging.DEBUG)
self.supervision_json_logger.setLevel(logging.DEBUG)
self.ncsession_json_logger.setLevel(logging.DEBUG)
json_handler = RotatingFileHandler(json_log_file, maxBytes=100000, backupCount=5)
json_formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
json_handler.setFormatter(json_formatter)
self.json_logger.addHandler(json_handler)
cfg_json_handler = RotatingFileHandler(cfg_json_log_file, maxBytes=100000, backupCount=5)
cfg_json_formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
cfg_json_handler.setFormatter(cfg_json_formatter)
self.cfg_json_logger.addHandler(cfg_json_handler)
supervision_json_handler = RotatingFileHandler(supervision_json_log_file, maxBytes=100000, backupCount=5)
supervision_json_formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
supervision_json_handler.setFormatter(supervision_json_formatter)
self.supervision_json_logger.addHandler(supervision_json_handler)
ncsession_json_handler = RotatingFileHandler(ncsession_json_log_file, maxBytes=100000, backupCount=5)
ncsession_json_formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
ncsession_json_handler.setFormatter(ncsession_json_formatter)
self.ncsession_json_logger.addHandler(ncsession_json_handler)
handler = RotatingFileHandler(log_file, maxBytes=100000, backupCount=5)
self.logger.addHandler(handler)
formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
handler.setFormatter(formatter)
if {{ testing }}:
return
def connect(self, host, port, user, password):
if {{ testing }}:
return
self.address = (host, port)
self.logger.info('Connecting to %s, user %s...' % (self.address, user))
self.conn = manager.connect(host=host,
port=port,
username=user,
password=password,
timeout=1800,
device_params={
'name': 'default'
},
hostkey_verify=False)
self.logger.info('Connection to %s successful' % (self.address,))
def subscribe(self):
# Filter not compatible between ncclient and netconf server
#result = self.conn.create_subscription(filter=('xpath', '/o-ran-fm:*'))
sub = self.conn.create_subscription()
self.logger.info('Subscription to %s successful' % (self.address,))
def get_notification(self):
result = None
while result == None:
self.logger.debug('Waiting for notification from %s...' % (self.address,))
result = self.conn.take_notification(block=True)
if result:
self.logger.debug('Got new notification from %s...' % (self.address,))
result_in_xml = result._raw
data_dict = xmltodict.parse(result_in_xml)
if 'alarm-notif' in data_dict['notification']:
self.json_logger.info('', extra={'data': data_dict})
elif 'supervision-notification' in data_dict['notification']:
self.supervision_json_logger.info('', extra={'data': data_dict})
elif 'netconf-session-start' or 'netconf-session-end' in data_dict['notification']:
self.ncsession_json_logger.info('', extra={'data': data_dict})
else:
self.cfg_json_logger.info('', extra={'data': data_dict})
def close(self):
# Close not compatible between ncclient and netconf server
#self.conn.close()
pass
import sys
sys.path.append({{ repr(buildout_directory_path) }})
from ncclient_common import LopcommNetconfClient
if __name__ == '__main__':
nc = LopcommNetconfClient()
while True:
try:
nc.connect("{{ netaddr.IPAddress(slap_configuration.get('tap-ipv6-gateway', '')) }}", 830, "oranuser", "oranpassword")
nc.subscribe()
while True:
nc.get_notification()
except Exception as e:
nc.logger.debug('Got exception, waiting 10 seconds before reconnecting...')
nc.logger.debug(e)
time.sleep(10)
finally:
nc.close()
nc = LopcommNetconfClient(
log_file="{{ log_file }}",
json_log_file="{{ json_log_file }}",
cfg_json_log_file="{{ cfg_json_log_file }}",
supervision_json_log_file="{{ supervision_json_log_file }}",
ncsession_json_log_file="{{ ncsession_json_log_file }}",
software_json_log_file="{{ software_json_log_file }}"
)
while True:
try:
nc.connect("{{ netaddr.IPAddress(slap_configuration.get('tap-ipv6-gateway', '')) }}", 830, "oranuser", "oranpassword")
nc.subscribe()
while True:
nc.get_notification()
except Exception as e:
nc.logger.debug('Got exception, waiting 10 seconds before reconnecting...')
nc.logger.debug(e)
time.sleep(10)
finally:
nc.close()
#!{{ python_path }}
import time
import xmltodict
import sys
import re
import os
sys.path.append({{ repr(buildout_directory_path) }})
from ncclient_common import LopcommNetconfClient
if __name__ == '__main__':
nc = LopcommNetconfClient(
log_file="{{ log_file }}",
supervision_reply_json_log_file="{{ supervision_reply_json_log_file }}"
)
try:
netconf_check_file = os.path.join('{{etc_path}}', 'is_netconf_connected')
nc.connect("{{ netaddr.IPAddress(slap_configuration.get('tap-ipv6-gateway', '')) }}", 830, "oranuser", "oranpassword")
supervision_subscription_rpc_xml = """
<create-subscription xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
<stream>o-ran-supervision</stream>
</create-subscription>
"""
nc.logger.info("Subscription creating...")
supervision_subscription_reply_xml = nc.custom_rpc_request(supervision_subscription_rpc_xml)
if supervision_subscription_reply_xml:
nc.logger.info("Subscription created")
supervision_subscription_data = xmltodict.parse(supervision_subscription_reply_xml)
nc.supervision_reply_json_logger.info('', extra={'data': supervision_subscription_data})
while True:
supervision_watchdog_rpc_xml = """
<supervision-watchdog-reset xmlns="urn:o-ran:supervision:1.0">
<supervision-notification-interval>60</supervision-notification-interval>
<guard-timer-overhead>10</guard-timer-overhead>
</supervision-watchdog-reset>
"""
nc.logger.info("NETCONF server replying...")
supervision_watchdog_reply_xml = nc.custom_rpc_request(supervision_watchdog_rpc_xml)
if supervision_watchdog_reply_xml:
if not os.path.exists(netconf_check_file):
open(netconf_check_file, "w").write('True')
nc.logger.info("NETCONF server replied")
supervision_watchdog_data = xmltodict.parse(supervision_watchdog_reply_xml)
nc.supervision_reply_json_logger.info('', extra={'data': supervision_watchdog_data})
# It must be the same interval as <supervision-notification-interval>
time.sleep(60)
else:
if os.path.exists(netconf_check_file):
os.remove(netconf_check_file)
else:
nc.logger.debug("Subscription failed.")
except Exception as e:
nc.logger.debug('Got exception, waiting 10 seconds before reconnecting...')
nc.logger.debug(str(e))
time.sleep(10)
finally:
nc.close()
\ No newline at end of file
import time
import logging
import xmltodict
from logging.handlers import RotatingFileHandler
from ncclient import manager
from ncclient.operations import RPCError
from ncclient.xml_ import *
from ncclient.devices.default import DefaultDeviceHandler
class LopcommNetconfClient:
def __init__(self, log_file, json_log_file=None, cfg_json_log_file=None, supervision_json_log_file=None, ncsession_json_log_file=None, software_json_log_file=None, software_reply_json_log_file=None, supervision_reply_json_log_file=None, testing=False):
self.logger = logging.getLogger('logger')
self.logger.setLevel(logging.DEBUG)
handler = RotatingFileHandler(log_file, maxBytes=100000, backupCount=5)
self.logger.addHandler(handler)
formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
handler.setFormatter(formatter)
if json_log_file:
self.json_logger = logging.getLogger('json_logger')
self.json_logger.setLevel(logging.DEBUG)
json_handler = RotatingFileHandler(json_log_file, maxBytes=100000, backupCount=5)
json_formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
json_handler.setFormatter(json_formatter)
self.json_logger.addHandler(json_handler)
self.cfg_json_logger = logging.getLogger('cfg_json_logger')
self.cfg_json_logger.setLevel(logging.DEBUG)
cfg_json_handler = RotatingFileHandler(cfg_json_log_file, maxBytes=100000, backupCount=5)
cfg_json_formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
cfg_json_handler.setFormatter(cfg_json_formatter)
self.cfg_json_logger.addHandler(cfg_json_handler)
self.supervision_json_logger = logging.getLogger('supervision_json_logger')
self.supervision_json_logger.setLevel(logging.DEBUG)
supervision_json_handler = RotatingFileHandler(supervision_json_log_file, maxBytes=100000, backupCount=5)
supervision_json_formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
supervision_json_handler.setFormatter(supervision_json_formatter)
self.supervision_json_logger.addHandler(supervision_json_handler)
self.ncsession_json_logger = logging.getLogger('ncsession_json_logger')
self.ncsession_json_logger.setLevel(logging.DEBUG)
ncsession_json_handler = RotatingFileHandler(ncsession_json_log_file, maxBytes=100000, backupCount=5)
ncsession_json_formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
ncsession_json_handler.setFormatter(ncsession_json_formatter)
self.ncsession_json_logger.addHandler(ncsession_json_handler)
self.software_json_logger = logging.getLogger('software_json_logger')
self.software_json_logger.setLevel(logging.DEBUG)
software_json_handler = RotatingFileHandler(software_json_log_file, maxBytes=100000, backupCount=5)
software_json_formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
software_json_handler.setFormatter(software_json_formatter)
self.software_json_logger.addHandler(software_json_handler)
else:
self.json_logger = None
self.cfg_json_logger = None
self.supervision_json_logger = None
self.ncsession_json_logger = None
self.software_json_logger = None
if supervision_reply_json_log_file:
self.supervision_reply_json_logger = logging.getLogger('supervision_reply_json_logger')
self.supervision_reply_json_logger.setLevel(logging.DEBUG)
supervision_reply_json_handler = RotatingFileHandler(supervision_reply_json_log_file, maxBytes=100000, backupCount=5)
supervision_reply_json_formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
supervision_reply_json_handler.setFormatter(supervision_reply_json_formatter)
self.supervision_reply_json_logger.addHandler(supervision_reply_json_handler)
else:
self.supervision_reply_json_logger = None
if software_reply_json_log_file:
self.software_reply_json_logger = logging.getLogger('software_reply_json_logger')
self.software_reply_json_logger.setLevel(logging.DEBUG)
software_reply_json_handler = RotatingFileHandler(software_reply_json_log_file, maxBytes=100000, backupCount=5)
software_reply_json_formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
software_reply_json_handler.setFormatter(software_reply_json_formatter)
self.software_reply_json_logger.addHandler(software_reply_json_handler)
else:
self.software_reply_json_logger = None
if testing:
return
def connect(self, host, port, user, password):
self.address = (host, port)
self.logger.info('Connecting to %s, user %s...' % (self.address, user))
self.conn = manager.connect(host=host,
port=port,
username=user,
password=password,
timeout=1800,
device_params={
'name': 'default'
},
hostkey_verify=False)
self.logger.info('Connection to %s successful' % (self.address,))
def subscribe(self):
sub = self.conn.create_subscription()
self.logger.info('Subscription to %s successful' % (self.address,))
def get_notification(self):
result = None
while result == None:
self.logger.debug('Waiting for notification from %s...' % (self.address,))
result = self.conn.take_notification(block=True)
if result:
self.logger.debug('Got new notification from %s...' % (self.address,))
result_in_xml = result._raw
data_dict = xmltodict.parse(result_in_xml)
if 'alarm-notif' in data_dict['notification']:
self.json_logger.info('', extra={'data': data_dict})
elif 'supervision-notification' in data_dict['notification']:
self.supervision_json_logger.info('', extra={'data': data_dict})
elif 'netconf-session-start' in data_dict['notification'] or 'netconf-session-end' in data_dict['notification']:
self.ncsession_json_logger.info('', extra={'data': data_dict})
elif any(event in data_dict['notification'] for event in ['install-event', 'activation-event', 'download-event']):
self.software_json_logger.info('', extra={'data': data_dict})
else:
self.cfg_json_logger.info('', extra={'data': data_dict})
def edit_config(self, config_files):
for config_file in config_files:
with open(config_file) as f:
config_xml = f.read()
try:
self.logger.info('Sending edit-config RPC request...')
self.conn.edit_config(target='running', config=config_xml)
self.logger.info('Edit-config RPC request sent successfully')
except RPCError as e:
self.logger.error('Error sending edit-config RPC request: %s' % e)
def custom_rpc_request(self, rpc_xml):
try:
self.logger.info('Sending custom RPC request...')
response = self.conn.dispatch(to_ele(rpc_xml))
if response.ok:
self.logger.info('Custom RPC request sent successfully')
return response.xml
else:
self.logger.error('Error sending custom RPC request: %s' % response.error)
except RPCError as e:
self.logger.error('Error sending custom RPC request: %s' % e)
def reset_device(self):
self.logger.info('Resetting...')
reset_rpc_xml = """
<reset xmlns="urn:o-ran:operations:1.0">
</reset>
"""
reset_reply_xml = self.custom_rpc_request(reset_rpc_xml)
if reset_reply_xml:
reset_data = xmltodict.parse(reset_reply_xml)
self.software_reply_json_logger.info('', extra={'data': reset_data})
self.logger.info('Wait 60 second then reboot!')
time.sleep(60)
def get_inventory(self):
self.logger.info('Fetching software inventory...')
inventory_rpc_xml = """
<get xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<filter type="subtree">
<software-inventory xmlns="urn:o-ran:software-management:1.0" />
</filter>
</get>
"""
inventory_reply_xml = self.custom_rpc_request(inventory_rpc_xml)
if inventory_reply_xml:
self.logger.info('Finish fetching software inventory.')
inventory_data = xmltodict.parse(inventory_reply_xml)
self.software_reply_json_logger.info('', extra={'data': inventory_data})
nonrunning_slot_name = None
running_slot_name = None
active_nonrunning_slot_name = None
nonrunning_slot_name_build_version = None
running_slot_name_build_version = None
software_slots = inventory_data['nc:rpc-reply']['data']['software-inventory']['software-slot']
for slot in software_slots:
if slot['running'] == 'false':
nonrunning_slot_name = slot['name']
nonrunning_slot_name_build_version = slot['build-version']
if slot['running'] == 'true':
running_slot_name = slot['name']
running_slot_name_build_version = slot['build-version']
elif slot['active'] == 'true' and slot['running'] == 'false':
active_nonrunning_slot_name = slot['name']
return {
"nonrunning_slot_name": nonrunning_slot_name,
"running_slot_name": running_slot_name,
"active_nonrunning_slot_name": active_nonrunning_slot_name,
"nonrunning_slot_name_build_version": nonrunning_slot_name_build_version,
"running_slot_name_build_version": running_slot_name_build_version
}
def close(self):
# Close not compatible between ncclient and netconf server
#self.conn.close()
pass
<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<user-plane-configuration xmlns="urn:o-ran:uplane-conf-option8:1.0">
<!-- t[r]x-links -->
<xc:config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<user-plane-configuration xc:operation="replace" xmlns="urn:o-ran:uplane-conf-option8:1.0">
<!-- low-level-t[r]x-links -->
<tx-links>
<name>TXA0P00C00</name>
<processing-element>PE0</processing-element>
<tx-array-carrier>TXA0CC00</tx-array-carrier>
<tx-endpoint>TXA0P00C00</tx-endpoint>
</tx-links>
{% if slapparameter_dict.get('n_antenna_dl') == 4 %}
<tx-links>
<name>TXA0P01C00</name>
<processing-element>PE0</processing-element>
<tx-array-carrier>TXA0CC00</tx-array-carrier>
<tx-endpoint>TXA0P01C00</tx-endpoint>
</tx-links>
{% endif %}
<tx-links>
<name>TXA0P01C00</name>
<name>TXA0P00C01</name>
<processing-element>PE0</processing-element>
<tx-array-carrier>TXA0CC00</tx-array-carrier>
<tx-endpoint>TXA0P01C00</tx-endpoint>
<tx-endpoint>TXA0P00C01</tx-endpoint>
</tx-links>
{% if slapparameter_dict.get('n_antenna_dl') == 4 %}
<tx-links>
<name>TXA0P01C01</name>
<processing-element>PE0</processing-element>
<tx-array-carrier>TXA0CC00</tx-array-carrier>
<tx-endpoint>TXA0P01C01</tx-endpoint>
</tx-links>
{% endif %}
<rx-links>
<name>RXA0P00C00</name>
<processing-element>PE0</processing-element>
......@@ -25,19 +41,46 @@
<rx-array-carrier>RXA0CC00</rx-array-carrier>
<rx-endpoint>PRACH0P00C00</rx-endpoint>
</rx-links>
{% if slapparameter_dict.get('n_antenna_dl') == 4 %}
<rx-links>
<name>RXA0P01C00</name>
<processing-element>PE0</processing-element>
<rx-array-carrier>RXA0CC00</rx-array-carrier>
<rx-endpoint>RXA0P01C00</rx-endpoint>
</rx-links>
<rx-links>
<name>PRACH0P01C00</name>
<processing-element>PE0</processing-element>
<rx-array-carrier>RXA0CC00</rx-array-carrier>
<rx-endpoint>PRACH0P01C00</rx-endpoint>
</rx-links>
{% endif %}
<rx-links>
<name>RXA0P01C00</name>
<name>RXA0P00C01</name>
<processing-element>PE0</processing-element>
<rx-array-carrier>RXA0CC00</rx-array-carrier>
<rx-endpoint>RXA0P01C00</rx-endpoint>
<rx-endpoint>RXA0P00C01</rx-endpoint>
</rx-links>
<rx-links>
<name>PRACH0P01C00</name>
<name>PRACH0P00C01</name>
<processing-element>PE0</processing-element>
<rx-array-carrier>RXA0CC00</rx-array-carrier>
<rx-endpoint>PRACH0P01C00</rx-endpoint>
<rx-endpoint>PRACH0P00C01</rx-endpoint>
</rx-links>
{% if slapparameter_dict.get('n_antenna_dl') == 4 %}
<rx-links>
<name>RXA0P01C01</name>
<processing-element>PE0</processing-element>
<rx-array-carrier>RXA0CC00</rx-array-carrier>
<rx-endpoint>RXA0P01C01</rx-endpoint>
</rx-links>
<rx-links>
<name>PRACH0P01C01</name>
<processing-element>PE0</processing-element>
<rx-array-carrier>RXA0CC00</rx-array-carrier>
<rx-endpoint>PRACH0P01C01</rx-endpoint>
</rx-links>
<!-- t[r]x-endpoints -->
{% endif %}
<tx-endpoints>
<name>TXA0P00C00</name>
<e-axcid>
......@@ -48,8 +91,20 @@
<eaxc-id>0</eaxc-id>
</e-axcid>
</tx-endpoints>
{% if slapparameter_dict.get('n_antenna_dl') == 4 %}
<tx-endpoints>
<name>TXA0P01C00</name>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3968</band-sector-bitmask>
<ccid-bitmask>112</ccid-bitmask>
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>2</eaxc-id>
</e-axcid>
</tx-endpoints>
{% endif %}
<tx-endpoints>
<name>TXA0P01C00</name>
<name>TXA0P00C01</name>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3968</band-sector-bitmask>
......@@ -58,6 +113,18 @@
<eaxc-id>1</eaxc-id>
</e-axcid>
</tx-endpoints>
{% if slapparameter_dict.get('n_antenna_dl') == 4 %}
<tx-endpoints>
<name>TXA0P01C01</name>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3968</band-sector-bitmask>
<ccid-bitmask>112</ccid-bitmask>
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>3</eaxc-id>
</e-axcid>
</tx-endpoints>
{% endif %}
<rx-endpoints>
<name>RXA0P00C00</name>
<e-axcid>
......@@ -67,7 +134,6 @@
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>0</eaxc-id>
</e-axcid>
<non-time-managed-delay-enabled>false</non-time-managed-delay-enabled>
</rx-endpoints>
<rx-endpoints>
<name>PRACH0P00C00</name>
......@@ -78,10 +144,31 @@
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>8</eaxc-id>
</e-axcid>
<non-time-managed-delay-enabled>false</non-time-managed-delay-enabled>
</rx-endpoints>
{% if slapparameter_dict.get('n_antenna_dl') == 4 %}
<rx-endpoints>
<name>RXA0P01C00</name>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3968</band-sector-bitmask>
<ccid-bitmask>112</ccid-bitmask>
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>2</eaxc-id>
</e-axcid>
</rx-endpoints>
<rx-endpoints>
<name>PRACH0P01C00</name>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3968</band-sector-bitmask>
<ccid-bitmask>112</ccid-bitmask>
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>9</eaxc-id>
</e-axcid>
</rx-endpoints>
{% endif %}
<rx-endpoints>
<name>RXA0P01C00</name>
<name>RXA0P00C01</name>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3968</band-sector-bitmask>
......@@ -89,37 +176,56 @@
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>1</eaxc-id>
</e-axcid>
<non-time-managed-delay-enabled>false</non-time-managed-delay-enabled>
</rx-endpoints>
<rx-endpoints>
<name>PRACH0P01C00</name>
<name>PRACH0P00C01</name>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3968</band-sector-bitmask>
<ccid-bitmask>112</ccid-bitmask>
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>9</eaxc-id>
<eaxc-id>24</eaxc-id>
</e-axcid>
<non-time-managed-delay-enabled>false</non-time-managed-delay-enabled>
</rx-endpoints>
<!-- t[r]x-array-carriers -->
{% if slapparameter_dict.get('n_antenna_dl') == 4 %}
<rx-endpoints>
<name>RXA0P01C01</name>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3968</band-sector-bitmask>
<ccid-bitmask>112</ccid-bitmask>
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>3</eaxc-id>
</e-axcid>
</rx-endpoints>
<rx-endpoints>
<name>PRACH0P01C01</name>
<e-axcid>
<o-du-port-bitmask>61440</o-du-port-bitmask>
<band-sector-bitmask>3968</band-sector-bitmask>
<ccid-bitmask>112</ccid-bitmask>
<ru-port-bitmask>15</ru-port-bitmask>
<eaxc-id>25</eaxc-id>
</e-axcid>
</rx-endpoints>
{% endif %}
<tx-array-carriers>
<name>TXA0CC00</name>
<absolute-frequency-center>{{ slapparameter_dict.get('txa0cc00_center_frequency_earfcn', 300) }}</absolute-frequency-center>
<center-of-channel-bandwidth>{{ slapparameter_dict.get('txa0cc00_center_frequency', 2140000000) }}</center-of-channel-bandwidth>
<channel-bandwidth>{{ slapparameter_dict.get('txa0cc00_bandwidth', 20000000) }}</channel-bandwidth>
<absolute-frequency-center>{{ slapparameter_dict.get('dl_earfcn', 300) }}</absolute-frequency-center>
<center-of-channel-bandwidth>{{ 1000000*slapparameter_dict.get('txa0cc00_center_frequency', 2140) }}</center-of-channel-bandwidth>
<channel-bandwidth>{{ {'1.4 MHz': 1400000, '3 MHz': 3000000, '5 MHz': 5000000, '10 MHz': 10000000, '15 MHz': 15000000, '20 MHz': 20000000}.get(slapparameter_dict.get('bandwidth'), '20 MHz') }}</channel-bandwidth>
<active>{{ slapparameter_dict.get('txa0cc00_active', 'INACTIVE') }}</active>
<rw-type>LTE</rw-type>
<rw-duplex-scheme>FDD</rw-duplex-scheme>
<gain>0</gain>
<gain>{{ slapparameter_dict.get('txa0cc00_gain', '-20') }}</gain>
<downlink-radio-frame-offset>0</downlink-radio-frame-offset>
<downlink-sfn-offset>0</downlink-sfn-offset>
</tx-array-carriers>
<rx-array-carriers>
<name>RXA0CC00</name>
<absolute-frequency-center>{{ slapparameter_dict.get('rxa0cc00_center_frequency_earfcn', 18300) }}</absolute-frequency-center>
<center-of-channel-bandwidth>{{ slapparameter_dict.get('rxa0cc00_center_frequency', 1950000000) }}</center-of-channel-bandwidth>
<channel-bandwidth>{{ slapparameter_dict.get('rxa0cc00_bandwidth', 20000000) }}</channel-bandwidth>
<center-of-channel-bandwidth>{{ 1000000*slapparameter_dict.get('rxa0cc00_center_frequency', 1950) }}</center-of-channel-bandwidth>
<channel-bandwidth>{{ {'1.4 MHz': 1400000, '3 MHz': 3000000, '5 MHz': 5000000, '10 MHz': 10000000, '15 MHz': 15000000, '20 MHz': 20000000}.get(slapparameter_dict.get('bandwidth'), '20 MHz') }}</channel-bandwidth>
<active>{{ slapparameter_dict.get('rxa0cc00_active', 'INACTIVE') }}</active>
<downlink-radio-frame-offset>0</downlink-radio-frame-offset>
<downlink-sfn-offset>0</downlink-sfn-offset>
......@@ -127,4 +233,4 @@
<n-ta-offset>0</n-ta-offset>
</rx-array-carriers>
</user-plane-configuration>
</config>
\ No newline at end of file
</xc:config>
......@@ -14,11 +14,13 @@ extends =
../../component/git/buildout.cfg
../../component/dnsmasq/buildout.cfg
../../component/fluent-bit/buildout.cfg
../../component/openssh/buildout.cfg
parts +=
template
slapos-cookbook
ltelogs.jinja2.sh
ncclient_common
# copy all configs by default
mme.jinja2.cfg
dnsmasq.jinja2.cfg
......@@ -56,6 +58,10 @@ output = ${buildout:directory}/template.cfg
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:_update_hash_filename_}
[ncclient_common]
<= download-base
destination = ${buildout:directory}/ncclient_common.py
[amarisoft-stats.jinja2.py]
<= download-base
......@@ -68,6 +74,12 @@ url = ${:_profile_base_location_}/${:_update_hash_filename_}
[lopcomm-rrh-config.jinja2.py]
<= download-base
[lopcomm-rrh-software.jinja2.py]
<= download-base
[lopcomm-rrh-supervision.jinja2.py]
<= download-base
[template-enb]
<= download-base
......
......@@ -142,8 +142,9 @@ def test_enb_conf(self):
with open(conf_file, 'r') as f:
conf = yaml.load(f)
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
if 'tx_gain' in conf and 'rx_gain' in conf:
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
self.assertEqual(conf['cell_default']['inactivity_timer'], enb_param_dict['inactivity_timer'])
self.assertEqual(conf['cell_default']['uldl_config'], 6)
self.assertEqual(conf['cell_list'][0]['dl_earfcn'], enb_param_dict['dl_earfcn'])
......@@ -151,6 +152,7 @@ def test_enb_conf(self):
self.assertEqual(conf['cell_list'][0]['n_id_cell'], enb_param_dict['pci'])
self.assertEqual(conf['cell_list'][0]['tac'], int(enb_param_dict['tac'], 16))
self.assertEqual(conf['cell_list'][0]['root_sequence_index'], int(enb_param_dict['root_sequence_index']))
self.assertEqual(conf['cell_list'][0]['cell_id'], 0)
for p in conf['cell_default']['plmn_list']:
for n in "plmn attach_without_pdn reserved".split():
self.assertEqual(p[n], enb_param_dict['plmn_list'][p['plmn']][n])
......
......@@ -142,8 +142,9 @@ def test_enb_conf(self):
with open(conf_file, 'r') as f:
conf = yaml.load(f)
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
if 'tx_gain' in conf and 'rx_gain' in conf:
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
self.assertEqual(conf['cell_default']['inactivity_timer'], enb_param_dict['inactivity_timer'])
self.assertEqual(conf['cell_default']['uldl_config'], 6)
self.assertEqual(conf['cell_list'][0]['dl_earfcn'], enb_param_dict['dl_earfcn'])
......@@ -151,6 +152,7 @@ def test_enb_conf(self):
self.assertEqual(conf['cell_list'][0]['n_id_cell'], enb_param_dict['pci'])
self.assertEqual(conf['cell_list'][0]['tac'], int(enb_param_dict['tac'], 16))
self.assertEqual(conf['cell_list'][0]['root_sequence_index'], int(enb_param_dict['root_sequence_index']))
self.assertEqual(conf['cell_list'][0]['cell_id'], 0)
for p in conf['cell_default']['plmn_list']:
for n in "plmn attach_without_pdn reserved".split():
self.assertEqual(p[n], enb_param_dict['plmn_list'][p['plmn']][n])
......
......@@ -142,8 +142,9 @@ def test_enb_conf(self):
with open(conf_file, 'r') as f:
conf = yaml.load(f)
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
if 'tx_gain' in conf and 'rx_gain' in conf:
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
self.assertEqual(conf['cell_default']['inactivity_timer'], enb_param_dict['inactivity_timer'])
self.assertEqual(conf['cell_default']['uldl_config'], 6)
self.assertEqual(conf['cell_list'][0]['dl_earfcn'], enb_param_dict['dl_earfcn'])
......@@ -151,6 +152,7 @@ def test_enb_conf(self):
self.assertEqual(conf['cell_list'][0]['n_id_cell'], enb_param_dict['pci'])
self.assertEqual(conf['cell_list'][0]['tac'], int(enb_param_dict['tac'], 16))
self.assertEqual(conf['cell_list'][0]['root_sequence_index'], int(enb_param_dict['root_sequence_index']))
self.assertEqual(conf['cell_list'][0]['cell_id'], 0)
for p in conf['cell_default']['plmn_list']:
for n in "plmn attach_without_pdn reserved".split():
self.assertEqual(p[n], enb_param_dict['plmn_list'][p['plmn']][n])
......
......@@ -142,8 +142,9 @@ def test_enb_conf(self):
with open(conf_file, 'r') as f:
conf = yaml.load(f)
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
if 'tx_gain' in conf and 'rx_gain' in conf:
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
self.assertEqual(conf['cell_default']['inactivity_timer'], enb_param_dict['inactivity_timer'])
self.assertEqual(conf['cell_default']['uldl_config'], 6)
self.assertEqual(conf['cell_list'][0]['dl_earfcn'], enb_param_dict['dl_earfcn'])
......@@ -151,6 +152,7 @@ def test_enb_conf(self):
self.assertEqual(conf['cell_list'][0]['n_id_cell'], enb_param_dict['pci'])
self.assertEqual(conf['cell_list'][0]['tac'], int(enb_param_dict['tac'], 16))
self.assertEqual(conf['cell_list'][0]['root_sequence_index'], int(enb_param_dict['root_sequence_index']))
self.assertEqual(conf['cell_list'][0]['cell_id'], 0)
for p in conf['cell_default']['plmn_list']:
for n in "plmn attach_without_pdn reserved".split():
self.assertEqual(p[n], enb_param_dict['plmn_list'][p['plmn']][n])
......
......@@ -142,8 +142,9 @@ def test_enb_conf(self):
with open(conf_file, 'r') as f:
conf = yaml.load(f)
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
if 'tx_gain' in conf and 'rx_gain' in conf:
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
self.assertEqual(conf['cell_default']['inactivity_timer'], enb_param_dict['inactivity_timer'])
self.assertEqual(conf['cell_default']['uldl_config'], 6)
self.assertEqual(conf['cell_list'][0]['dl_earfcn'], enb_param_dict['dl_earfcn'])
......@@ -151,6 +152,7 @@ def test_enb_conf(self):
self.assertEqual(conf['cell_list'][0]['n_id_cell'], enb_param_dict['pci'])
self.assertEqual(conf['cell_list'][0]['tac'], int(enb_param_dict['tac'], 16))
self.assertEqual(conf['cell_list'][0]['root_sequence_index'], int(enb_param_dict['root_sequence_index']))
self.assertEqual(conf['cell_list'][0]['cell_id'], 0)
for p in conf['cell_default']['plmn_list']:
for n in "plmn attach_without_pdn reserved".split():
self.assertEqual(p[n], enb_param_dict['plmn_list'][p['plmn']][n])
......
......@@ -142,8 +142,9 @@ def test_enb_conf(self):
with open(conf_file, 'r') as f:
conf = yaml.load(f)
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
if 'tx_gain' in conf and 'rx_gain' in conf:
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
self.assertEqual(conf['cell_default']['inactivity_timer'], enb_param_dict['inactivity_timer'])
self.assertEqual(conf['cell_default']['uldl_config'], 6)
self.assertEqual(conf['cell_list'][0]['dl_earfcn'], enb_param_dict['dl_earfcn'])
......@@ -151,6 +152,7 @@ def test_enb_conf(self):
self.assertEqual(conf['cell_list'][0]['n_id_cell'], enb_param_dict['pci'])
self.assertEqual(conf['cell_list'][0]['tac'], int(enb_param_dict['tac'], 16))
self.assertEqual(conf['cell_list'][0]['root_sequence_index'], int(enb_param_dict['root_sequence_index']))
self.assertEqual(conf['cell_list'][0]['cell_id'], 0)
for p in conf['cell_default']['plmn_list']:
for n in "plmn attach_without_pdn reserved".split():
self.assertEqual(p[n], enb_param_dict['plmn_list'][p['plmn']][n])
......
......@@ -142,8 +142,9 @@ def test_enb_conf(self):
with open(conf_file, 'r') as f:
conf = yaml.load(f)
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
if 'tx_gain' in conf and 'rx_gain' in conf:
self.assertEqual(conf['tx_gain'], enb_param_dict['tx_gain'])
self.assertEqual(conf['rx_gain'], enb_param_dict['rx_gain'])
self.assertEqual(conf['cell_default']['inactivity_timer'], enb_param_dict['inactivity_timer'])
self.assertEqual(conf['cell_default']['uldl_config'], 6)
self.assertEqual(conf['cell_list'][0]['dl_earfcn'], enb_param_dict['dl_earfcn'])
......@@ -151,6 +152,7 @@ def test_enb_conf(self):
self.assertEqual(conf['cell_list'][0]['n_id_cell'], enb_param_dict['pci'])
self.assertEqual(conf['cell_list'][0]['tac'], int(enb_param_dict['tac'], 16))
self.assertEqual(conf['cell_list'][0]['root_sequence_index'], int(enb_param_dict['root_sequence_index']))
self.assertEqual(conf['cell_list'][0]['cell_id'], 0)
for p in conf['cell_default']['plmn_list']:
for n in "plmn attach_without_pdn reserved".split():
self.assertEqual(p[n], enb_param_dict['plmn_list'][p['plmn']][n])
......
......@@ -18,7 +18,7 @@ md5sum = 7be0c21751f8385ef876c3d7192d4057
[template-re6stnet]
filename = instance-re6stnet.cfg.in
md5sum = 84320356634f8d241fc827683d211bb8
md5sum = 01a24f1983a1d40f31c4b36b7a2448fe
[template-apache-conf]
filename = apache.conf.in
......
......@@ -107,6 +107,7 @@ recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:services}/re6st-registry
pidfile = ${directory:run}/registry.pid
command-line = {{ bin_directory }}/re6st-registry @${re6st-registry-conf:output}
hash-existing-files = ${re6st-registry-conf:output}
[cron-entry-re6st-backup]
recipe = slapos.cookbook:cron.d
......
......@@ -42,7 +42,7 @@ md5sum = 43556e5bca8336dd543ae8068512aa6d
[template-my-cnf]
filename = my.cnf.in
md5sum = c0bde08ec6bd6d333315a15026266b65
md5sum = 2c553103f1196f95e4b6d0716a1e0638
[template-mariadb-initial-setup]
filename = mariadb_initial_setup.sql.in
......
......@@ -50,6 +50,10 @@ max_connections = {{ parameter_dict['max-connection-count'] }}
# doesn't use "insert ... select" (in any number of queries) pattern.
innodb_locks_unsafe_for_binlog = 1
# disable innodb_change_buffering to prevent potential risk of crash or data corruption,
# that is default from 10.5.14.
innodb_change_buffering = none
{% set log_bin = parameter_dict['binlog-path'] -%}
{% if log_bin -%}
log_bin = {{ log_bin }}
......@@ -74,6 +78,7 @@ relay-log = mariadb-relay-bin
{{x}}innodb_flush_log_at_trx_commit = 0
{{x}}innodb_flush_method = nosync
{{x}}innodb_doublewrite = 0
{{x}}innodb_change_buffering = all
{{x}}sync_frm = 0
character_set_server = {{ parameter_dict['character-set-server'] }}
......
......@@ -810,7 +810,7 @@ Products.GenericSetup = 2.3.0
Products.MailHost = 4.13
Products.MimetypesRegistry = 2.1.8
Products.PluggableAuthService = 2.8.1
Products.PluginRegistry = 1.6
Products.PluginRegistry = 1.11
Products.PythonScripts = 4.15
Products.Sessions = 4.15
Products.SiteErrorLog = 5.7
......
......@@ -42,7 +42,7 @@ md5sum = f45dc4568b63de39f49b8fecca5deef1
[template-my-cnf]
filename = my.cnf.in
md5sum = c0bde08ec6bd6d333315a15026266b65
md5sum = 2c553103f1196f95e4b6d0716a1e0638
[template-mariadb-initial-setup]
filename = mariadb_initial_setup.sql.in
......
......@@ -50,6 +50,10 @@ max_connections = {{ parameter_dict['max-connection-count'] }}
# doesn't use "insert ... select" (in any number of queries) pattern.
innodb_locks_unsafe_for_binlog = 1
# disable innodb_change_buffering to prevent potential risk of crash or data corruption,
# that is default from 10.5.14.
innodb_change_buffering = none
{% set log_bin = parameter_dict['binlog-path'] -%}
{% if log_bin -%}
log_bin = {{ log_bin }}
......@@ -74,6 +78,7 @@ relay-log = mariadb-relay-bin
{{x}}innodb_flush_log_at_trx_commit = 0
{{x}}innodb_flush_method = nosync
{{x}}innodb_doublewrite = 0
{{x}}innodb_change_buffering = all
{{x}}sync_frm = 0
character_set_server = {{ parameter_dict['character-set-server'] }}
......
......@@ -51,6 +51,10 @@ filename = monitor.conf.in
[monitor-httpd-cors]
<= monitor-download-base
filename = httpd-cors.cfg.in
[template-monitor-httpd-wrapper]
<= monitor-download-base
filename = template-monitor-httpd-wrapper.sh.in
# End templates files
[monitor-template]
......@@ -82,6 +86,7 @@ context =
raw python_executable ${buildout:executable}
raw python_with_eggs ${buildout:bin-directory}/${monitor-eggs:interpreter}
raw template_wrapper ${monitor-template-wrapper:location}/${monitor-template-wrapper:filename}
raw template_monitor_httpd_wrapper ${template-monitor-httpd-wrapper:location}/${template-monitor-httpd-wrapper:filename}
raw check_disk_space ${buildout:bin-directory}/check-free-disk
raw bin_directory ${buildout:directory}/bin
......
......@@ -14,12 +14,16 @@
# not need these here).
[monitor2-template]
filename = instance-monitor.cfg.jinja2.in
md5sum = 255b4f5f2d960ec958899114cef4cfd9
md5sum = dda9b2355134517dae601cc20709685a
[monitor-httpd-conf]
_update_hash_filename_ = templates/monitor-httpd.conf.in
md5sum = 0540fc5cc439a06079e9e724a5a55a70
[template-monitor-httpd-wrapper]
_update_hash_filename_ = templates/template-monitor-httpd-wrapper.sh.in
md5sum = 45929a22527b71620555326f4dd78c34
[monitor-template-wrapper]
_update_hash_filename_ = templates/wrapper.in
md5sum = e8566c00b28f6f86adde11b6b6371403
......
......@@ -67,9 +67,22 @@ hash-existing-files = ${buildout:directory}/software_release/buildout.cfg
recipe = slapos.cookbook:certificate_authority.request
key-file = ${monitor-httpd-conf-parameter:key-file}
cert-file = ${monitor-httpd-conf-parameter:cert-file}
executable = ${monitor-httpd-wrapper:wrapper-path}
executable = ${monitor-httpd-service-wrapper:output}
wrapper = ${directory:bin}/ca-monitor-httpd
[monitor-httpd-service-wrapper]
recipe = slapos.recipe.template:jinja2
url = {{ template_monitor_httpd_wrapper }}
output = ${directory:bin}/monitor-httpd-service-wrapper
pid-file = ${monitor-httpd-conf-parameter:pid-file}
monitor-httpd-wrapper-path = ${monitor-httpd-wrapper:wrapper-path}
monitor-httpd-conf = ${monitor-httpd-conf:output}
context =
key pid_file :pid-file
key monitor_httpd_wrapper_path :monitor-httpd-wrapper-path
key monitor_httpd_conf :monitor-httpd-conf
raw dash_binary {{ dash_executable_location }}
[ca-monitor-httpd-service]
recipe = slapos.cookbook:wrapper
command-line = ${ca-monitor-httpd:wrapper}
......
#!{{ dash_binary }}
# BEWARE: This file is operated by slapos node
# BEWARE: It will be overwritten automatically
pid_file="{{ pid_file }}"
monitor_httpd_conf_file={{ monitor_httpd_conf }}
if [ -f "$pid_file" ]; then
pid=$(cat "$pid_file")
result=$(ps aux | grep "^\S*\s*$pid\s")
# The process with the specified PID is running
if [ -n "$result" ]; then
echo "there is a process running with the same pid"
# Get the command line of the process and replace null characters with spaces
cmdline=$(tr '\0' ' ' < "/proc/$pid/cmdline")
# There is a process running with the pid,
# but it is not one using our monitor-httpd.conf
if ! expr "$cmdline" : ".*$monitor_httpd_conf_file" > /dev/null; then
echo "The process is not running with the monitor_httpd_conf"
rm -f {{ pid_file }};
fi
fi
fi
exec {{ monitor_httpd_wrapper_path }} "$@"
......@@ -304,7 +304,7 @@ slapos.rebootstrap = 4.5
slapos.recipe.build = 0.56
slapos.recipe.cmmi = 0.19
slapos.recipe.template = 5.1
slapos.toolbox = 0.137
slapos.toolbox = 0.139
smmap = 5.0.0
sniffio = 1.3.0
sortedcontainers = 2.4.0
......@@ -365,7 +365,7 @@ pyparsing = 2.2.0
pyrsistent = 0.16.1
requests = 2.27.1
selectors34 = 1.2
slapos.toolbox = 0.128
slapos.toolbox = 0.128.1
smmap = 0.9.0
smmap2 = 2.0.5
traitlets = 4.3.3
......
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