Commit 14406615 authored by Jérome Perrin's avatar Jérome Perrin

Merge remote-tracking branch 'upstream/master' into zope4py2

parents b28731f7 e8c05247
...@@ -475,6 +475,12 @@ ...@@ -475,6 +475,12 @@
], ],
"title": "Centos 8.2004 Minimal x86_64" "title": "Centos 8.2004 Minimal x86_64"
}, },
{
"const": [
"https://shacache.nxdcdn.com/8017c532ed74586b718662d8b11cf8c34fa638b0affd0413ed38623989b8f98ffd0bcb475246e279ea2f3c194a3e33c55e0f376a9727de13e4bfd87e75e47b5d#e8d2a77c51b599c10651608a5d8c286f"
],
"title": "Ubuntu Jammy 22.04.1 Live Server x86_64"
},
{ {
"const": [ "const": [
"https://shacache.nxdcdn.com/302c990c6d69575ff24c96566e5c7e26bf36908abb0cd546e22687c46fb07bf8dba595bf77a9d4fd9ab63e75c0437c133f35462fd41ea77f6f616140cd0e5e6a#f3a306f40e4a313fb5a584d73b3dee8f" "https://shacache.nxdcdn.com/302c990c6d69575ff24c96566e5c7e26bf36908abb0cd546e22687c46fb07bf8dba595bf77a9d4fd9ab63e75c0437c133f35462fd41ea77f6f616140cd0e5e6a#f3a306f40e4a313fb5a584d73b3dee8f"
......
...@@ -332,6 +332,12 @@ ...@@ -332,6 +332,12 @@
], ],
"title": "Centos 8.2004 Minimal x86_64" "title": "Centos 8.2004 Minimal x86_64"
}, },
{
"const": [
"https://shacache.nxdcdn.com/8017c532ed74586b718662d8b11cf8c34fa638b0affd0413ed38623989b8f98ffd0bcb475246e279ea2f3c194a3e33c55e0f376a9727de13e4bfd87e75e47b5d#e8d2a77c51b599c10651608a5d8c286f"
],
"title": "Ubuntu Jammy 22.04.1 Live Server x86_64"
},
{ {
"const": [ "const": [
"https://shacache.nxdcdn.com/302c990c6d69575ff24c96566e5c7e26bf36908abb0cd546e22687c46fb07bf8dba595bf77a9d4fd9ab63e75c0437c133f35462fd41ea77f6f616140cd0e5e6a#f3a306f40e4a313fb5a584d73b3dee8f" "https://shacache.nxdcdn.com/302c990c6d69575ff24c96566e5c7e26bf36908abb0cd546e22687c46fb07bf8dba595bf77a9d4fd9ab63e75c0437c133f35462fd41ea77f6f616140cd0e5e6a#f3a306f40e4a313fb5a584d73b3dee8f"
......
#!{{ python_path }}
import json
import logging
from logging.handlers import RotatingFileHandler
import time
from websocket import create_connection
class enbWebSocket:
def __init__(self):
log_file = "{{ log_file }}"
self.logger = logging.getLogger('logger')
self.logger.setLevel(logging.INFO)
handler = RotatingFileHandler(log_file, maxBytes=30000, backupCount=2)
formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
handler.setFormatter(formatter)
self.logger.addHandler(handler)
if {{ testing }}:
return
self.ws_url = "ws://127.0.1.2:9001"
self.ws = create_connection(self.ws_url)
def close(self):
if {{ testing }}:
return
self.ws.close()
def send(self, msg):
self.ws.send(json.dumps(msg))
def recv(self, message_type):
for i in range(1,20):
r = json.loads(self.ws.recv())
if r['message'] == message_type:
return r
def stats(self):
if {{ testing }}:
r = {
'message': 'rf',
'rf_info': "CPRI: x16 HW SW\n"
}
else:
self.send({
"message": "rf",
"rf_info": True
})
r = self.recv('rf')
self.logger.info('RF info', extra={'data': r})
if __name__ == '__main__':
ws = enbWebSocket()
try:
while True:
ws.stats()
time.sleep({{ stats_period }})
finally:
ws.close()
...@@ -16,43 +16,51 @@ ...@@ -16,43 +16,51 @@
[template] [template]
filename = instance.cfg filename = instance.cfg
md5sum = ed72fb7c36b0bc046df177e4d6f3bf12 md5sum = 4af831f81760b37250fa50ad3812142a
[amarisoft-stats.jinja2.py] [amarisoft-stats.jinja2.py]
_update_hash_filename_ = amarisoft-stats.jinja2.py _update_hash_filename_ = amarisoft-stats.jinja2.py
md5sum = 6e0a052bd0ca08cc0c7b4880d3deffcc md5sum = 6e0a052bd0ca08cc0c7b4880d3deffcc
[amarisoft-rf-info.jinja2.py]
_update_hash_filename_ = amarisoft-rf-info.jinja2.py
md5sum = c930c28365c685a6066f382c9b5d8893
[lopcomm-rrh-stats.jinja2.py]
_update_hash_filename_ = lopcomm-rrh-stats.jinja2.py
md5sum = 39e191080722ac13ebc56b1e6350eb8f
[template-lte-enb-epc] [template-lte-enb-epc]
_update_hash_filename_ = instance-enb-epc.jinja2.cfg _update_hash_filename_ = instance-enb-epc.jinja2.cfg
md5sum = 833667743c693b8d5f78a2527b275a9e md5sum = bb4435f433e100fede09ff921d42c927
[template-lte-enb] [template-lte-enb]
_update_hash_filename_ = instance-enb.jinja2.cfg _update_hash_filename_ = instance-enb.jinja2.cfg
md5sum = c4584b338d26f57d5c9384956be36677 md5sum = 31707b64ab531c60fc99287238130c5b
[template-lte-gnb-epc] [template-lte-gnb-epc]
_update_hash_filename_ = instance-gnb-epc.jinja2.cfg _update_hash_filename_ = instance-gnb-epc.jinja2.cfg
md5sum = 1f0b18cb6d70466d002b378bb931e7da md5sum = 9a0e36188b23831bec3cb53b226baa66
[template-lte-epc] [template-lte-epc]
_update_hash_filename_ = instance-epc.jinja2.cfg _update_hash_filename_ = instance-epc.jinja2.cfg
md5sum = 99c05a34678adb5a70aa64ecf2ee4e35 md5sum = acc9176fd9abe1d04c60a08cdd520eee
[template-lte-gnb] [template-lte-gnb]
_update_hash_filename_ = instance-gnb.jinja2.cfg _update_hash_filename_ = instance-gnb.jinja2.cfg
md5sum = 954dd1409b0256874f9524a40b880e47 md5sum = 6695165ae0e5116073a802f10aba3d94
[template-lte-mme] [template-lte-mme]
_update_hash_filename_ = instance-mme.jinja2.cfg _update_hash_filename_ = instance-mme.jinja2.cfg
md5sum = 728f4d3ae248710c23e4b73eea4d628e md5sum = 400accb9d5bc104b1b122a7b9bc3a261
[template-lte-ue-lte] [template-lte-ue-lte]
_update_hash_filename_ = instance-ue-lte.jinja2.cfg _update_hash_filename_ = instance-ue-lte.jinja2.cfg
md5sum = 8888be35fa6e6f3e69d9373002a0e06e md5sum = 5c1f78588a0d7447807c10765552a6e7
[template-lte-ue-nr] [template-lte-ue-nr]
_update_hash_filename_ = instance-ue-nr.jinja2.cfg _update_hash_filename_ = instance-ue-nr.jinja2.cfg
md5sum = 94ca609dc564d7ed95db09e1fa029208 md5sum = 5b032c3c9dbbd5b8552b0ebd8dcc9acf
[ue_db.jinja2.cfg] [ue_db.jinja2.cfg]
filename = config/ue_db.jinja2.cfg filename = config/ue_db.jinja2.cfg
...@@ -60,7 +68,7 @@ md5sum = dcaac06553a3222b14c0013a13f4a149 ...@@ -60,7 +68,7 @@ md5sum = dcaac06553a3222b14c0013a13f4a149
[enb.jinja2.cfg] [enb.jinja2.cfg]
filename = config/enb.jinja2.cfg filename = config/enb.jinja2.cfg
md5sum = 1d0bbfa1cd22740db4f1034588c946eb md5sum = 0b2a37e6902fd5ad3d6b37e11eebec69
[sib23.asn] [sib23.asn]
filename = config/sib23.asn filename = config/sib23.asn
...@@ -68,7 +76,7 @@ md5sum = b377dac7f1fcf94fb9ce9ebed617f36a ...@@ -68,7 +76,7 @@ md5sum = b377dac7f1fcf94fb9ce9ebed617f36a
[gnb.jinja2.cfg] [gnb.jinja2.cfg]
filename = config/gnb.jinja2.cfg filename = config/gnb.jinja2.cfg
md5sum = 2e051b91c39542152bc679ec78cb5926 md5sum = cbbbdeda9ddaaf5957d91ef31afe6051
[ltelogs.jinja2.sh] [ltelogs.jinja2.sh]
filename = ltelogs.jinja2.sh filename = ltelogs.jinja2.sh
...@@ -76,7 +84,7 @@ md5sum = 1ba2e065bdf14a6411e95e80db17dcfd ...@@ -76,7 +84,7 @@ md5sum = 1ba2e065bdf14a6411e95e80db17dcfd
[mme.jinja2.cfg] [mme.jinja2.cfg]
filename = config/mme.jinja2.cfg filename = config/mme.jinja2.cfg
md5sum = 21e24367dd8213a00f6c777df33d5c03 md5sum = f002f908d9af8b4089dad0c64742dde6
[ims.jinja2.cfg] [ims.jinja2.cfg]
filename = config/ims.jinja2.cfg filename = config/ims.jinja2.cfg
...@@ -89,31 +97,3 @@ md5sum = 31c166f0a1b6d664f92b8f318b233d9a ...@@ -89,31 +97,3 @@ md5sum = 31c166f0a1b6d664f92b8f318b233d9a
[ue-nr.jinja2.cfg] [ue-nr.jinja2.cfg]
filename = config/ue-nr.jinja2.cfg filename = config/ue-nr.jinja2.cfg
md5sum = b3078deab008d7e81ddd88ac02b8b698 md5sum = b3078deab008d7e81ddd88ac02b8b698
[sdr-busy-promise]
_update_hash_filename_ = promise/check_sdr_busy.py
md5sum = b0c65aefa60a9d5b9f7e7b38383db48b
[cell-gain-saturated-promise]
_update_hash_filename_ = promise/check_cell_gain_saturated.py
md5sum = 764ca8913ea40964382848cf3233c1f7
[rx-saturated-promise]
_update_hash_filename_ = promise/check_rx_saturated.py
md5sum = 40cf5389fd91845f4426ef159fb20fc0
[baseband-latency-promise]
_update_hash_filename_ = promise/check_baseband_latency.py
md5sum = 4f115e2d9bde9f268c77264dc0deb2a3
[amarisoft-stats-log-promise]
_update_hash_filename_ = promise/check_amarisoft_stats_log.py
md5sum = 5bf57a9074ea5b054d999789cbbe2c87
[cpu-temperature-promise]
_update_hash_filename_ = promise/check_cpu_temperature.py
md5sum = 6812310b65c2d95815afc2b034a5f90f
[interface-up-promise]
_update_hash_filename_ = promise/check_interface_up.py
md5sum = 44ae5693f62b7a4dbc98f700f68d8600
Changelog
=========
Version 1.0.308 (2023-02-09)
-------------
* Add support for IPv6 in UEs if available
* Use latest amarisoft version on ORS if available
* Add gnb_id_bits parameter
* Use promises from slapos.toolbox repository
* Rotate and add timestamps in enb-output.log, gnb-output.log, mme-output.log etc...
* Add support for Lopcomm RRH
* Remove UE power emission limitation
\ No newline at end of file
...@@ -6,6 +6,20 @@ ...@@ -6,6 +6,20 @@
log_options: "all.level=error,all.max_size=0,nas.level=debug,nas.max_size=1,s1ap.level=debug,s1ap.max_size=1,x2ap.level=debug,x2ap.max_size=1,rrc.level=debug,rrc.max_size=1,phy.level=info,file.rotate=1G,file.path=/dev/null", log_options: "all.level=error,all.max_size=0,nas.level=debug,nas.max_size=1,s1ap.level=debug,s1ap.max_size=1,x2ap.level=debug,x2ap.max_size=1,rrc.level=debug,rrc.max_size=1,phy.level=info,file.rotate=1G,file.path=/dev/null",
log_filename: "{{ directory['log'] }}/enb.log", log_filename: "{{ directory['log'] }}/enb.log",
{% if slapparameter_dict.get('rrh', '') == "Lopcomm ORAN" %}
rf_driver: {
name: "sdr",
args: "dev0=/dev/sdr0@0",
cpri_mapping: "hw",
cpri_mult: 16,
cpri_rx_delay: 0,
cpri_tx_delay: 0,
ifname: "{{ slap_configuration.get('tap-name', '') }}",
cpri_debug: 2,
},
tx_gain: 0,
rx_gain: 0,
{% else %}
rf_driver: { rf_driver: {
name: "sdr", name: "sdr",
args: "dev0=/dev/sdr0", args: "dev0=/dev/sdr0",
...@@ -13,6 +27,7 @@ ...@@ -13,6 +27,7 @@
}, },
tx_gain: {{ slapparameter_dict.get('tx_gain', slap_configuration['configuration.default_lte_tx_gain']) }}, tx_gain: {{ slapparameter_dict.get('tx_gain', slap_configuration['configuration.default_lte_tx_gain']) }},
rx_gain: {{ slapparameter_dict.get('rx_gain', slap_configuration['configuration.default_lte_rx_gain']) }}, rx_gain: {{ slapparameter_dict.get('rx_gain', slap_configuration['configuration.default_lte_rx_gain']) }},
{% endif %}
com_addr: "127.0.1.2:9001", com_addr: "127.0.1.2:9001",
mme_list: [ mme_list: [
...@@ -76,10 +91,13 @@ ...@@ -76,10 +91,13 @@
cell_default: { cell_default: {
n_antenna_dl: N_ANTENNA_DL, n_antenna_dl: N_ANTENNA_DL,
n_antenna_ul: N_ANTENNA_UL, n_antenna_ul: N_ANTENNA_UL,
{% if slapparameter_dict.get('rrh', '') == "Lopcomm ORAN" %}
// uldl_config: 2,
// sp_config: 7,
{% else %}
uldl_config: 2, uldl_config: 2,
sp_config: 7, sp_config: 7,
{% endif %}
n_rb_dl: N_RB_DL, n_rb_dl: N_RB_DL,
cyclic_prefix: "normal", cyclic_prefix: "normal",
...@@ -134,7 +152,11 @@ ...@@ -134,7 +152,11 @@
pucch_dedicated: { pucch_dedicated: {
n1_pucch_sr_count: 11, n1_pucch_sr_count: 11,
cqi_pucch_n_rb: 1, cqi_pucch_n_rb: 1,
{% if slapparameter_dict.get('rrh', '') == "Lopcomm ORAN" %}
// tdd_ack_nack_feedback_mode: "multiplexing",
{% else %}
tdd_ack_nack_feedback_mode: "multiplexing", tdd_ack_nack_feedback_mode: "multiplexing",
{% endif %}
}, },
pusch_dedicated: { pusch_dedicated: {
......
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
gtp_addr: "127.0.1.1", gtp_addr: "127.0.1.1",
{% endif %} {% endif %}
gnb_id_bits: 28, gnb_id_bits: {{ slapparameter_dict.get('gnb_id_bits', 28) }},
gnb_id: {{ slapparameter_dict.get('gnb_id', '0x12345') }}, gnb_id: {{ slapparameter_dict.get('gnb_id', '0x12345') }},
nr_support: true, nr_support: true,
......
...@@ -50,7 +50,17 @@ ...@@ -50,7 +50,17 @@
pdn_list: [ pdn_list: [
{ {
{% if slap_configuration.get('tun-ipv6-network', '') %}
pdn_type: "ipv4v6",
first_ipv6_prefix: "{{ netaddr.IPAddress(slap_configuration.get('tun-ipv6-addr', '')) + 1 }}",
last_ipv6_prefix: "{{ netaddr.IPAddress(netaddr.IPNetwork(slap_configuration.get('tun-ipv6-network', '')).last) - 1 }}",
dns_addr: ["8.8.8.8", "2001:4860:4860::8888"],
{% else %}
pdn_type: "ipv4", pdn_type: "ipv4",
dns_addr: "8.8.8.8",
{% endif %}
tun_ifname: "{{ slap_configuration.get('tun-name', '') }}", tun_ifname: "{{ slap_configuration.get('tun-name', '') }}",
access_point_name: ["default", "internet", "ims", "sos"], access_point_name: ["default", "internet", "ims", "sos"],
{% if slap_configuration.get('tun-name', '') %} {% if slap_configuration.get('tun-name', '') %}
...@@ -58,7 +68,6 @@ ...@@ -58,7 +68,6 @@
last_ip_addr: "{{ netaddr.IPAddress(netaddr.IPNetwork(slap_configuration.get('tun-ipv4-network', '')).last) - 1 }}", last_ip_addr: "{{ netaddr.IPAddress(netaddr.IPNetwork(slap_configuration.get('tun-ipv4-network', '')).last) - 1 }}",
{% endif %} {% endif %}
ip_addr_shift: 2, ip_addr_shift: 2,
dns_addr: "8.8.8.8",
p_cscf_addr: ["{{ slap_configuration.get('tun-ipv4-addr', '') }}"], p_cscf_addr: ["{{ slap_configuration.get('tun-ipv4-addr', '') }}"],
erabs: [ erabs: [
......
...@@ -14,7 +14,7 @@ parts = ...@@ -14,7 +14,7 @@ parts =
directory directory
lte-enb-request lte-enb-request
lte-mme-request lte-mme-request
cpu-temperature-promise check-cpu-temperature.py
publish-connection-information publish-connection-information
{% for part in part_list -%} {% for part in part_list -%}
{{ ' %s' % part }} {{ ' %s' % part }}
...@@ -87,17 +87,19 @@ return = monitor-base-url ...@@ -87,17 +87,19 @@ return = monitor-base-url
lte-mme-request = ${lte-mme-request:connection-monitor-base-url} lte-mme-request = ${lte-mme-request:connection-monitor-base-url}
lte-enb-request = ${lte-enb-request:connection-monitor-base-url} lte-enb-request = ${lte-enb-request:connection-monitor-base-url}
[cpu-temperature-promise] [macro.promise]
recipe = slapos.cookbook:promise.plugin <= monitor-promise-base
eggs = name = ${:_buildout_section_name_}
slapos.core
python-dateutil [check-cpu-temperature.py]
file = {{ cpu_temperature_promise }} <= macro.promise
output = ${directory:plugins}/check-cpu-temperature.py promise = check_cpu_temperature
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }} config-frequency = {{ slapparameter_dict.get("promise_cpu_temperature_frequency", 5) }}
config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold", 80) }} config-max-spot-temp = {{ slapparameter_dict.get("promise_cpu_max_spot_temp", 90) }}
config-max-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold_duration", 600) }} config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_max_avg_temp", 80) }}
config-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temp_duration", 600) }}
config-avg-flag-file = ${directory:var}/promise_cpu_avg_flag_file
[publish-connection-information] [publish-connection-information]
recipe = slapos.cookbook:publish.serialised recipe = slapos.cookbook:publish.serialised
......
...@@ -23,6 +23,16 @@ ...@@ -23,6 +23,16 @@
"type": "boolean" "type": "boolean"
}, },
{%- endif %} {%- endif %}
"rrh": {
"title": "RRH",
"description": "RRH",
"type": "string",
"default": "SDR",
"enum": [
"SDR",
"Lopcomm ORAN"
]
},
"tx_gain": { "tx_gain": {
"title": "Tx gain", "title": "Tx gain",
"description": "Tx gain (in dB)", "description": "Tx gain (in dB)",
...@@ -144,20 +154,20 @@ ...@@ -144,20 +154,20 @@
"type": "number", "type": "number",
"default": 7 "default": 7
}, },
"promise_cpu_temperature_threshold": { "promise_cpu_max_spot_temp": {
"title": "CPU temperature promise threshold", "title": "Maximum CPU spot temperature",
"description": "Temperature threshold above which CPU temperature promise will fail", "description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number", "type": "number",
"default": 90 "default": 90
}, },
"promise_cpu_avg_temperature_threshold": { "promise_cpu_max_avg_temp": {
"title": "Average CPU temperature promise threshold", "title": "Maximum average CPU temperature",
"description": "If average temperature over specified duration reaches this threshold, promise will fail", "description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number", "type": "number",
"default": 80 "default": 80
}, },
"promise_cpu_avg_temperature_threshold_duration": { "promise_cpu_avg_temp_period": {
"title": "Average CPU temperature promise threshold duration", "title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold", "description": "Duration during which average temperature should not exceed specified threshold",
"type": "number", "type": "number",
"default": 600 "default": 600
......
...@@ -5,14 +5,20 @@ parts = ...@@ -5,14 +5,20 @@ parts =
lte-enb-config lte-enb-config
lte-enb-service lte-enb-service
amarisoft-stats-service amarisoft-stats-service
sdr-busy-promise amarisoft-rf-info-service
cell-gain-saturated-promise {% if slapparameter_dict.get('rrh', '') == "Lopcomm ORAN" %}
rx-saturated-promise lopcomm-rrh-stats-service
baseband-latency-promise check-lopcomm-vswr.py
amarisoft-stats-log-promise check-lopcomm-lof.py
check-lopcomm-rssi.py
check-cpri-lock.py
{% endif %}
{% if not slapparameter_dict.get("sub-instance", False) %} {% if not slapparameter_dict.get("sub-instance", False) %}
cpu-temperature-promise check-cpu-temperature.py
{% endif %} {% endif %}
check-sdr-busy.py
check-baseband-latency.py
check-amarisoft-stats-log.py
monitor-base monitor-base
publish-connection-information publish-connection-information
...@@ -82,16 +88,19 @@ offline = false ...@@ -82,16 +88,19 @@ offline = false
[lte-enb-sh-wrapper] [lte-enb-sh-wrapper]
recipe = slapos.recipe.template recipe = slapos.recipe.template
output = ${directory:bin}/${:_buildout_section_name_} output = ${directory:bin}/${:_buildout_section_name_}
enb-log = ${directory:log}/enb-output.log
inline = inline =
#!/bin/sh #!/bin/sh
{% if not slapparameter_dict.get("testing", False) %} {% if not slapparameter_dict.get("testing", False) %}
sudo /opt/amarisoft/rm-tmp-lte; sudo /opt/amarisoft/rm-tmp-lte;
sudo /opt/amarisoft/init-sdr; sudo /opt/amarisoft/init-sdr;
sudo /opt/amarisoft/init-enb; sudo /opt/amarisoft/init-enb;
{{ enb }}/lteenb ${directory:etc}/enb.cfg >> ${directory:log}/enb-output.log 2>> ${directory:log}/enb-output.log (echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting eNB software..." && echo) >> ${:enb-log};
tail -c 1M ${:enb-log} > ${:enb-log}.tmp;
mv ${:enb-log}.tmp ${:enb-log};
{{ enb }}/lteenb ${directory:etc}/enb.cfg >> ${:enb-log} 2>> ${:enb-log};
{% endif %} {% endif %}
### eNodeB (enb)
[lte-enb-service] [lte-enb-service]
recipe = slapos.cookbook:wrapper recipe = slapos.cookbook:wrapper
init = ${ltelogs:output} ${directory:log}/enb.log; sleep 2 init = ${ltelogs:output} ${directory:log}/enb.log; sleep 2
...@@ -122,7 +131,37 @@ mode = 0775 ...@@ -122,7 +131,37 @@ mode = 0775
url = {{ amarisoft_stats_template }} url = {{ amarisoft_stats_template }}
output = ${directory:bin}/amarisoft-stats.py output = ${directory:bin}/amarisoft-stats.py
### eNodeB (enb) [amarisoft-rf-info-template]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
log-output = ${directory:var}/log/amarisoft-rf-info.json.log
context =
section directory directory
key slapparameter_dict slap-configuration:configuration
key log_file :log-output
raw stats_period {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
raw testing {{ slapparameter_dict.get("testing", False) }}
raw python_path {{ buildout_directory}}/bin/pythonwitheggs
mode = 0775
url = {{ amarisoft_rf_info_template }}
output = ${directory:bin}/amarisoft-rf-info.py
[lopcomm-rrh-stats-template]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
log-output = ${directory:var}/log/lopcomm-rrh-stats.log
json-log-output = ${directory:var}/log/lopcomm-rrh-stats.json.log
context =
section directory directory
key slapparameter_dict slap-configuration:configuration
key log_file :log-output
key json_log_file :json-log-output
raw testing {{ slapparameter_dict.get("testing", False) }}
raw python_path {{ buildout_directory}}/bin/pythonwitheggs
mode = 0775
url = {{ lopcomm_rrh_stats_template }}
output = ${directory:bin}/lopcomm-rrh-stats.py
[amarisoft-stats-service] [amarisoft-stats-service]
recipe = slapos.cookbook:wrapper recipe = slapos.cookbook:wrapper
command-line = ${amarisoft-stats-template:output} command-line = ${amarisoft-stats-template:output}
...@@ -131,6 +170,22 @@ mode = 0775 ...@@ -131,6 +170,22 @@ mode = 0775
hash-files = hash-files =
${amarisoft-stats-template:output} ${amarisoft-stats-template:output}
[amarisoft-rf-info-service]
recipe = slapos.cookbook:wrapper
command-line = ${amarisoft-rf-info-template:output}
wrapper-path = ${directory:service}/amarisoft-rf-info
mode = 0775
hash-files =
${amarisoft-rf-info-template:output}
[lopcomm-rrh-stats-service]
recipe = slapos.cookbook:wrapper
command-line = ${lopcomm-rrh-stats-template:output}
wrapper-path = ${directory:service}/lopcomm-rrh-stats
mode = 0775
hash-files =
${lopcomm-rrh-stats-template:output}
[config-base] [config-base]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do extensions = jinja2.ext.do
...@@ -164,68 +219,74 @@ monitor-title = {{ slapparameter_dict['name'] | string }} ...@@ -164,68 +219,74 @@ monitor-title = {{ slapparameter_dict['name'] | string }}
password = {{ slapparameter_dict['monitor-password'] | string }} password = {{ slapparameter_dict['monitor-password'] | string }}
{% endif %} {% endif %}
[sdr-busy-promise] [macro.promise]
recipe = slapos.cookbook:promise.plugin <= monitor-promise-base
eggs = slapos.core name = ${:_buildout_section_name_}
file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py [check-cpu-temperature.py]
<= macro.promise
promise = check_cpu_temperature
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-frequency = {{ slapparameter_dict.get("promise_cpu_temperature_frequency", 5) }}
config-max-spot-temp = {{ slapparameter_dict.get("promise_cpu_max_spot_temp", 90) }}
config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_max_avg_temp", 80) }}
config-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temp_duration", 600) }}
config-avg-flag-file = ${directory:var}/promise_cpu_avg_flag_file
[check-sdr-busy.py]
<= macro.promise
promise = check_sdr_busy
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }} config-sdr = {{ sdr }}
[cell-gain-saturated-promise] [check-baseband-latency.py]
recipe = slapos.cookbook:promise.plugin <= macro.promise
eggs = promise = check_baseband_latency
slapos.core
python-dateutil
file = {{ cell_gain_saturated_promise }}
output = ${directory:plugins}/check-cell-gain-saturated.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output} config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }} config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
config-min-txrx-delay = {{ slapparameter_dict.get("min_txrx_delay", 5) }}
[rx-saturated-promise] [check-amarisoft-stats-log.py]
recipe = slapos.cookbook:promise.plugin <= macro.promise
eggs = promise = check_amarisoft_stats_log
slapos.core output = ${directory:plugins}/check-amarisoft-stats-log.py
python-dateutil
file = {{ rx_saturated_promise }}
output = ${directory:plugins}/check-rx-saturated.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output} config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }} config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
config-max-rx-sample-db = {{ slapparameter_dict.get("max_rx_sample_db", 0) }}
[baseband-latency-promise] [check-lopcomm-vswr.py]
recipe = slapos.cookbook:promise.plugin <= macro.promise
eggs = promise = check_lopcomm_vswr
slapos.core
python-dateutil
file = {{ baseband_latency_promise }}
output = ${directory:plugins}/check-baseband-latency.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output} config-netconf-log = ${lopcomm-rrh-stats-template:json-log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }} config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
config-min-txrx-delay = {{ slapparameter_dict.get("min_txrx_delay", 5) }}
config-avg-txrx-delay = {{ slapparameter_dict.get("avg_txrx_delay", 7) }} [check-lopcomm-rssi.py]
<= macro.promise
[amarisoft-stats-log-promise] promise = check_lopcomm_rssi
recipe = slapos.cookbook:promise.plugin config-testing = {{ slapparameter_dict.get("testing", False) }}
eggs = config-netconf-log = ${lopcomm-rrh-stats-template:json-log-output}
slapos.core config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
python-dateutil
file = {{ amarisoft_stats_log_promise }} [check-lopcomm-lof.py]
output = ${directory:plugins}/check-amarisoft-stats-log.py <= macro.promise
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output} 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) }} config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[cpu-temperature-promise] [check-cpri-lock.py]
recipe = slapos.cookbook:promise.plugin <= macro.promise
eggs = promise = check_cpri_lock
slapos.core
python-dateutil
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }} config-amarisoft-rf-info-log = ${amarisoft-rf-info-template:log-output}
config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold", 80) }} config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
config-max-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold_duration", 600) }}
[check-rx-saturated.py]
<= macro.promise
promise = check_rx_saturated
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
config-max-rx-sample-db = {{ slapparameter_dict.get("max_rx_sample_db", 0) }}
...@@ -13,9 +13,7 @@ info = Your SIM card has been attached to service ${slap-configuration:instance- ...@@ -13,9 +13,7 @@ info = Your SIM card has been attached to service ${slap-configuration:instance-
parts = parts =
directory directory
lte-mme-request lte-mme-request
{% if not slapparameter_dict.get("sub-instance", False) %} check-cpu-temperature.py
cpu-temperature-promise
{% endif %}
publish-connection-information publish-connection-information
{% for part in part_list -%} {% for part in part_list -%}
{{ ' %s' % part }} {{ ' %s' % part }}
...@@ -76,17 +74,19 @@ config-slave-list = {{ dumps(slave_instance_list) }} ...@@ -76,17 +74,19 @@ config-slave-list = {{ dumps(slave_instance_list) }}
[monitor-base-url-dict] [monitor-base-url-dict]
lte-mme-request = ${lte-mme-request:connection-monitor-base-url} lte-mme-request = ${lte-mme-request:connection-monitor-base-url}
[cpu-temperature-promise] [macro.promise]
recipe = slapos.cookbook:promise.plugin <= monitor-promise-base
eggs = name = ${:_buildout_section_name_}
slapos.core
python-dateutil [check-cpu-temperature.py]
file = {{ cpu_temperature_promise }} <= macro.promise
output = ${directory:plugins}/check-cpu-temperature.py promise = check_cpu_temperature
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }} config-frequency = {{ slapparameter_dict.get("promise_cpu_temperature_frequency", 5) }}
config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold", 80) }} config-max-spot-temp = {{ slapparameter_dict.get("promise_cpu_max_spot_temp", 90) }}
config-max-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold_duration", 600) }} config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_max_avg_temp", 80) }}
config-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temp_duration", 600) }}
config-avg-flag-file = ${directory:var}/promise_cpu_avg_flag_file
[publish-connection-information] [publish-connection-information]
recipe = slapos.cookbook:publish.serialised recipe = slapos.cookbook:publish.serialised
......
...@@ -14,7 +14,7 @@ parts = ...@@ -14,7 +14,7 @@ parts =
directory directory
lte-gnb-request lte-gnb-request
lte-mme-request lte-mme-request
cpu-temperature-promise check-cpu-temperature.py
publish-connection-information publish-connection-information
{% for part in part_list -%} {% for part in part_list -%}
{{ ' %s' % part }} {{ ' %s' % part }}
...@@ -87,17 +87,19 @@ return = monitor-base-url ...@@ -87,17 +87,19 @@ return = monitor-base-url
lte-mme-request = ${lte-mme-request:connection-monitor-base-url} lte-mme-request = ${lte-mme-request:connection-monitor-base-url}
lte-gnb-request = ${lte-gnb-request:connection-monitor-base-url} lte-gnb-request = ${lte-gnb-request:connection-monitor-base-url}
[cpu-temperature-promise] [macro.promise]
recipe = slapos.cookbook:promise.plugin <= monitor-promise-base
eggs = name = ${:_buildout_section_name_}
slapos.core
python-dateutil [check-cpu-temperature.py]
file = {{ cpu_temperature_promise }} <= macro.promise
output = ${directory:plugins}/check-cpu-temperature.py promise = check_cpu_temperature
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }} config-frequency = {{ slapparameter_dict.get("promise_cpu_temperature_frequency", 5) }}
config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold", 80) }} config-max-spot-temp = {{ slapparameter_dict.get("promise_cpu_max_spot_temp", 90) }}
config-max-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold_duration", 600) }} config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_max_avg_temp", 80) }}
config-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temp_duration", 600) }}
config-avg-flag-file = ${directory:var}/promise_cpu_avg_flag_file
[publish-connection-information] [publish-connection-information]
recipe = slapos.cookbook:publish.serialised recipe = slapos.cookbook:publish.serialised
......
...@@ -87,6 +87,12 @@ ...@@ -87,6 +87,12 @@
"type": "string", "type": "string",
"default": "0x12345" "default": "0x12345"
}, },
"gnb_id_bits": {
"title": "gNB ID bits",
"description": "Number of bits for the gNodeB global identifier. (range 22 to 32)",
"type": "number",
"default": 28
},
"pci": { "pci": {
"title": "Physical Cell ID", "title": "Physical Cell ID",
"description": "Physical Cell ID", "description": "Physical Cell ID",
...@@ -172,9 +178,9 @@ ...@@ -172,9 +178,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses", "description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean" "type": "boolean"
}, },
"enb_stats_fetch_period": { "gnb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)", "title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics", "description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number", "type": "number",
"default": 60 "default": 60
}, },
......
...@@ -5,13 +5,20 @@ parts = ...@@ -5,13 +5,20 @@ parts =
lte-gnb-config lte-gnb-config
lte-enb-service lte-enb-service
amarisoft-stats-service amarisoft-stats-service
sdr-busy-promise amarisoft-rf-info-service
cell-gain-saturated-promise {% if slapparameter_dict.get('rrh', '') == "Lopcomm ORAN" %}
rx-saturated-promise lopcomm-rrh-stats-service
amarisoft-stats-log-promise check-lopcomm-vswr.py
check-lopcomm-lof.py
check-lopcomm-rssi.py
check-cpri-lock.py
{% endif %}
{% if not slapparameter_dict.get("sub-instance", False) %} {% if not slapparameter_dict.get("sub-instance", False) %}
cpu-temperature-promise check-cpu-temperature.py
{% endif %} {% endif %}
check-sdr-busy.py
check-baseband-latency.py
check-amarisoft-stats-log.py
monitor-base monitor-base
publish-connection-information publish-connection-information
...@@ -82,13 +89,18 @@ offline = false ...@@ -82,13 +89,18 @@ offline = false
[lte-enb-sh-wrapper] [lte-enb-sh-wrapper]
recipe = slapos.recipe.template recipe = slapos.recipe.template
output = ${directory:bin}/${:_buildout_section_name_} output = ${directory:bin}/${:_buildout_section_name_}
gnb-log = ${directory:log}/gnb-output.log
inline = inline =
#!/bin/sh #!/bin/sh
{% if not slapparameter_dict.get("testing", False) %} {% if not slapparameter_dict.get("testing", False) %}
sudo /opt/amarisoft/rm-tmp-lte; sudo /opt/amarisoft/rm-tmp-lte;
sudo /opt/amarisoft/init-sdr; sudo /opt/amarisoft/init-sdr;
sudo /opt/amarisoft/init-enb; sudo /opt/amarisoft/init-enb;
{{ enb }}/lteenb ${directory:etc}/gnb.cfg >> ${directory:log}/gnb-output.log 2>> ${directory:log}/gnb-output.log (echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting gNB software..." && echo) >> ${:gnb-log};
tail -c 1M ${:gnb-log} > ${:gnb-log}.tmp;
mv ${:gnb-log}.tmp ${:gnb-log};
{{ enb }}/lteenb ${directory:etc}/gnb.cfg >> ${:gnb-log} 2>> ${:gnb-log};
{% endif %} {% endif %}
### eNodeB (enb) ### eNodeB (enb)
...@@ -115,14 +127,28 @@ context = ...@@ -115,14 +127,28 @@ context =
section directory directory section directory directory
key slapparameter_dict slap-configuration:configuration key slapparameter_dict slap-configuration:configuration
key log_file :log-output key log_file :log-output
raw stats_period {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }} raw stats_period {{ slapparameter_dict.get("gnb_stats_fetch_period", 60) }}
raw testing {{ slapparameter_dict.get("testing", False) }} raw testing {{ slapparameter_dict.get("testing", False) }}
raw python_path {{ buildout_directory}}/bin/pythonwitheggs raw python_path {{ buildout_directory}}/bin/pythonwitheggs
mode = 0775 mode = 0775
url = {{ amarisoft_stats_template }} url = {{ amarisoft_stats_template }}
output = ${directory:bin}/amarisoft-stats.py output = ${directory:bin}/amarisoft-stats.py
### eNodeB (enb) [amarisoft-rf-info-template]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
log-output = ${directory:var}/log/amarisoft-rf-info.json.log
context =
section directory directory
key slapparameter_dict slap-configuration:configuration
key log_file :log-output
raw stats_period {{ slapparameter_dict.get("gnb_stats_fetch_period", 60) }}
raw testing {{ slapparameter_dict.get("testing", False) }}
raw python_path {{ buildout_directory}}/bin/pythonwitheggs
mode = 0775
url = {{ amarisoft_rf_info_template }}
output = ${directory:bin}/amarisoft-rf-info.py
[amarisoft-stats-service] [amarisoft-stats-service]
recipe = slapos.cookbook:wrapper recipe = slapos.cookbook:wrapper
command-line = ${amarisoft-stats-template:output} command-line = ${amarisoft-stats-template:output}
...@@ -131,6 +157,14 @@ mode = 0775 ...@@ -131,6 +157,14 @@ mode = 0775
hash-files = hash-files =
${amarisoft-stats-template:output} ${amarisoft-stats-template:output}
[amarisoft-rf-info-service]
recipe = slapos.cookbook:wrapper
command-line = ${amarisoft-rf-info-template:output}
wrapper-path = ${directory:service}/amarisoft-rf-info
mode = 0775
hash-files =
${amarisoft-rf-info-template:output}
[config-base] [config-base]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do extensions = jinja2.ext.do
...@@ -163,68 +197,74 @@ monitor-title = {{ slapparameter_dict['name'] | string }} ...@@ -163,68 +197,74 @@ monitor-title = {{ slapparameter_dict['name'] | string }}
password = {{ slapparameter_dict['monitor-password'] | string }} password = {{ slapparameter_dict['monitor-password'] | string }}
{% endif %} {% endif %}
[sdr-busy-promise] [macro.promise]
recipe = slapos.cookbook:promise.plugin <= monitor-promise-base
eggs = slapos.core name = ${:_buildout_section_name_}
file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py [check-cpu-temperature.py]
<= macro.promise
promise = check_cpu_temperature
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-frequency = {{ slapparameter_dict.get("promise_cpu_temperature_frequency", 5) }}
config-max-spot-temp = {{ slapparameter_dict.get("promise_cpu_max_spot_temp", 90) }}
config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_max_avg_temp", 80) }}
config-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temp_duration", 600) }}
config-avg-flag-file = ${directory:var}/promise_cpu_avg_flag_file
[check-sdr-busy.py]
<= macro.promise
promise = check_sdr_busy
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }} config-sdr = {{ sdr }}
[cell-gain-saturated-promise] [check-baseband-latency.py]
recipe = slapos.cookbook:promise.plugin <= macro.promise
eggs = promise = check_baseband_latency
slapos.core
python-dateutil
file = {{ cell_gain_saturated_promise }}
output = ${directory:plugins}/check-cell-gain-saturated.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output} config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }} config-stats-period = {{ slapparameter_dict.get("gnb_stats_fetch_period", 60) }}
config-min-txrx-delay = {{ slapparameter_dict.get("min_txrx_delay", 5) }}
[rx-saturated-promise] [check-amarisoft-stats-log.py]
recipe = slapos.cookbook:promise.plugin <= macro.promise
eggs = promise = check_amarisoft_stats_log
slapos.core output = ${directory:plugins}/check-amarisoft-stats-log.py
python-dateutil
file = {{ rx_saturated_promise }}
output = ${directory:plugins}/check-rx-saturated.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output} 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) }} config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
config-max-rx-sample-db = {{ slapparameter_dict.get("max_rx_sample_db", 0) }}
[baseband-latency-promise] [check-lopcomm-lof.py]
recipe = slapos.cookbook:promise.plugin <= macro.promise
eggs = promise = check_lopcomm_lof
slapos.core
python-dateutil
file = {{ baseband_latency_promise }}
output = ${directory:plugins}/check-baseband-latency.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output} config-netconf-log = ${lopcomm-rrh-stats-template:json-log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }} config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
config-min-txrx-delay = {{ slapparameter_dict.get("min_txrx_delay", 5) }}
config-avg-txrx-delay = {{ slapparameter_dict.get("avg_txrx_delay", 7) }} [check-cpri-lock.py]
<= macro.promise
[amarisoft-stats-log-promise] promise = check_cpri_lock
recipe = slapos.cookbook:promise.plugin config-testing = {{ slapparameter_dict.get("testing", False) }}
eggs = config-amarisoft-rf-info-log = ${amarisoft-rf-info-template:log-output}
slapos.core
python-dateutil
file = {{ amarisoft_stats_log_promise }}
output = ${directory:plugins}/check-amarisoft-stats-log.py
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }} config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[cpu-temperature-promise] [check-rx-saturated.py]
recipe = slapos.cookbook:promise.plugin <= macro.promise
eggs = promise = check_rx_saturated
slapos.core
python-dateutil
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }} config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold", 80) }} config-stats-period = {{ slapparameter_dict.get("gnb_stats_fetch_period", 60) }}
config-max-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold_duration", 600) }} config-max-rx-sample-db = {{ slapparameter_dict.get("max_rx_sample_db", 0) }}
...@@ -4,9 +4,9 @@ parts = ...@@ -4,9 +4,9 @@ parts =
ltelogs ltelogs
lte-mme-config lte-mme-config
lte-mme-service lte-mme-service
tun-up-promise
monitor-base monitor-base
publish-connection-information publish-connection-information
check-interface-up.py
{% if slapparameter_dict.get("iperf3", None) %} {% if slapparameter_dict.get("iperf3", None) %}
iperf-service iperf-service
port-listening-promise port-listening-promise
...@@ -86,11 +86,15 @@ environment = AMARISOFT_PATH=/opt/amarisoft/.amarisoft ...@@ -86,11 +86,15 @@ environment = AMARISOFT_PATH=/opt/amarisoft/.amarisoft
[lte-mme-sh-wrapper] [lte-mme-sh-wrapper]
recipe = slapos.recipe.template recipe = slapos.recipe.template
output = ${directory:bin}/${:_buildout_section_name_} output = ${directory:bin}/${:_buildout_section_name_}
mme-log = ${directory:log}/mme-output.log
inline = inline =
#!/bin/sh #!/bin/sh
{% if not slapparameter_dict.get("testing", False) %} {% if not slapparameter_dict.get("testing", False) %}
rm -f ${directory:var}/lte_ue.db; rm -f ${directory:var}/lte_ue.db;
{{ mme }}/ltemme ${directory:etc}/mme.cfg >> ${directory:log}/mme-output.log 2>> ${directory:log}/mme-output.log (echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting MME software..." && echo) >> ${:mme-log};
tail -c 1M ${:mme-log} > ${:mme-log}.tmp;
mv ${:mme-log}.tmp ${:mme-log};
{{ mme }}/ltemme ${directory:etc}/mme.cfg >> ${:mme-log} 2>> ${:mme-log};
{% endif %} {% endif %}
### MME ### MME
...@@ -177,15 +181,16 @@ recipe = slapos.cookbook:publish.serialised ...@@ -177,15 +181,16 @@ recipe = slapos.cookbook:publish.serialised
epc-ipv6 = ${slap-configuration:ipv6-random} epc-ipv6 = ${slap-configuration:ipv6-random}
epc-ipv4 = {{ epc_ipv4 }} epc-ipv4 = {{ epc_ipv4 }}
# Add custom promise to check if /dev/sdr0 is busy [macro.promise]
[tun-up-promise] <= monitor-promise-base
recipe = slapos.cookbook:promise.plugin name = ${:_buildout_section_name_}
eggs = slapos.core
file = {{ interface_up_promise }} [check-interface-up.py]
output = ${directory:plugins}/check-tun-up.py <= macro.promise
promise = check_interface_up
config-testing = {{ slapparameter_dict.get("testing", False) }}
{% if not slapparameter_dict.get("testing", False) %} {% if not slapparameter_dict.get("testing", False) %}
config-ifname = ${slap-configuration:tun-name} config-ifname = ${slap-configuration:tun-name}
{% else %} {% else %}
config-ifname = config-ifname =
{% endif %} {% endif %}
config-testing = {{ slapparameter_dict.get("testing", False) }}
...@@ -21,6 +21,16 @@ ...@@ -21,6 +21,16 @@
"description": "Activate iperf3 UDP server", "description": "Activate iperf3 UDP server",
"type": "boolean" "type": "boolean"
}, },
"rrh": {
"title": "RRH",
"description": "RRH",
"type": "string",
"default": "SDR",
"enum": [
"SDR",
"Lopcomm ORAN"
]
},
"tx_gain": { "tx_gain": {
"title": "Tx gain", "title": "Tx gain",
"description": "Tx gain (in dB)", "description": "Tx gain (in dB)",
...@@ -142,20 +152,20 @@ ...@@ -142,20 +152,20 @@
"type": "number", "type": "number",
"default": 7 "default": 7
}, },
"promise_cpu_temperature_threshold": { "promise_cpu_max_spot_temp": {
"title": "CPU temperature promise threshold", "title": "Maximum CPU spot temperature",
"description": "Temperature threshold above which CPU temperature promise will fail", "description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number", "type": "number",
"default": 90 "default": 90
}, },
"promise_cpu_avg_temperature_threshold": { "promise_cpu_max_avg_temp": {
"title": "Average CPU temperature promise threshold", "title": "Maximum average CPU temperature",
"description": "If average temperature over specified duration reaches this threshold, promise will fail", "description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number", "type": "number",
"default": 80 "default": 80
}, },
"promise_cpu_avg_temperature_threshold_duration": { "promise_cpu_avg_temp_period": {
"title": "Average CPU temperature promise threshold duration", "title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold", "description": "Duration during which average temperature should not exceed specified threshold",
"type": "number", "type": "number",
"default": 600 "default": 600
......
...@@ -3,6 +3,16 @@ ...@@ -3,6 +3,16 @@
"$schema": "http://json-schema.org/draft-04/schema", "$schema": "http://json-schema.org/draft-04/schema",
"title": "Input Parameters", "title": "Input Parameters",
"properties": { "properties": {
"rrh": {
"title": "RRH",
"description": "RRH",
"type": "string",
"default": "SDR",
"enum": [
"SDR",
"Lopcomm ORAN"
]
},
"tx_gain": { "tx_gain": {
"title": "Tx gain", "title": "Tx gain",
"description": "Tx gain (in dB)", "description": "Tx gain (in dB)",
...@@ -124,20 +134,20 @@ ...@@ -124,20 +134,20 @@
"type": "number", "type": "number",
"default": 7 "default": 7
}, },
"promise_cpu_temperature_threshold": { "promise_cpu_max_spot_temp": {
"title": "CPU temperature promise threshold", "title": "Maximum CPU spot temperature",
"description": "Temperature threshold above which CPU temperature promise will fail", "description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number", "type": "number",
"default": 90 "default": 90
}, },
"promise_cpu_avg_temperature_threshold": { "promise_cpu_max_avg_temp": {
"title": "Average CPU temperature promise threshold", "title": "Maximum average CPU temperature",
"description": "If average temperature over specified duration reaches this threshold, promise will fail", "description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number", "type": "number",
"default": 80 "default": 80
}, },
"promise_cpu_avg_temperature_threshold_duration": { "promise_cpu_avg_temp_period": {
"title": "Average CPU temperature promise threshold duration", "title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold", "description": "Duration during which average temperature should not exceed specified threshold",
"type": "number", "type": "number",
"default": 600 "default": 600
......
...@@ -85,6 +85,12 @@ ...@@ -85,6 +85,12 @@
"type": "string", "type": "string",
"default": "0x12345" "default": "0x12345"
}, },
"gnb_id_bits": {
"title": "gNB ID bits",
"description": "Number of bits for the gNodeB global identifier. (range 22 to 32)",
"type": "number",
"default": 28
},
"pci": { "pci": {
"title": "Physical Cell ID", "title": "Physical Cell ID",
"description": "Physical Cell ID", "description": "Physical Cell ID",
...@@ -170,9 +176,9 @@ ...@@ -170,9 +176,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses", "description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean" "type": "boolean"
}, },
"enb_stats_fetch_period": { "gnb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)", "title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics", "description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number", "type": "number",
"default": 60 "default": 60
}, },
......
...@@ -67,6 +67,12 @@ ...@@ -67,6 +67,12 @@
"type": "string", "type": "string",
"default": "0x12345" "default": "0x12345"
}, },
"gnb_id_bits": {
"title": "gNB ID bits",
"description": "Number of bits for the gNodeB global identifier. (range 22 to 32)",
"type": "number",
"default": 28
},
"pci": { "pci": {
"title": "Physical Cell ID", "title": "Physical Cell ID",
"description": "Physical Cell ID", "description": "Physical Cell ID",
...@@ -152,9 +158,9 @@ ...@@ -152,9 +158,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses", "description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean" "type": "boolean"
}, },
"enb_stats_fetch_period": { "gnb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)", "title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics", "description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number", "type": "number",
"default": 60 "default": 60
}, },
......
...@@ -21,6 +21,16 @@ ...@@ -21,6 +21,16 @@
"description": "Activate iperf3 UDP server", "description": "Activate iperf3 UDP server",
"type": "boolean" "type": "boolean"
}, },
"rrh": {
"title": "RRH",
"description": "RRH",
"type": "string",
"default": "SDR",
"enum": [
"SDR",
"Lopcomm ORAN"
]
},
"tx_gain": { "tx_gain": {
"title": "Tx gain", "title": "Tx gain",
"description": "Tx gain (in dB)", "description": "Tx gain (in dB)",
...@@ -142,20 +152,20 @@ ...@@ -142,20 +152,20 @@
"type": "number", "type": "number",
"default": 7 "default": 7
}, },
"promise_cpu_temperature_threshold": { "promise_cpu_max_spot_temp": {
"title": "CPU temperature promise threshold", "title": "Maximum CPU spot temperature",
"description": "Temperature threshold above which CPU temperature promise will fail", "description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number", "type": "number",
"default": 90 "default": 90
}, },
"promise_cpu_avg_temperature_threshold": { "promise_cpu_max_avg_temp": {
"title": "Average CPU temperature promise threshold", "title": "Maximum average CPU temperature",
"description": "If average temperature over specified duration reaches this threshold, promise will fail", "description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number", "type": "number",
"default": 80 "default": 80
}, },
"promise_cpu_avg_temperature_threshold_duration": { "promise_cpu_avg_temp_period": {
"title": "Average CPU temperature promise threshold duration", "title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold", "description": "Duration during which average temperature should not exceed specified threshold",
"type": "number", "type": "number",
"default": 600 "default": 600
......
...@@ -3,6 +3,16 @@ ...@@ -3,6 +3,16 @@
"$schema": "http://json-schema.org/draft-04/schema", "$schema": "http://json-schema.org/draft-04/schema",
"title": "Input Parameters", "title": "Input Parameters",
"properties": { "properties": {
"rrh": {
"title": "RRH",
"description": "RRH",
"type": "string",
"default": "SDR",
"enum": [
"SDR",
"Lopcomm ORAN"
]
},
"tx_gain": { "tx_gain": {
"title": "Tx gain", "title": "Tx gain",
"description": "Tx gain (in dB)", "description": "Tx gain (in dB)",
...@@ -124,20 +134,20 @@ ...@@ -124,20 +134,20 @@
"type": "number", "type": "number",
"default": 7 "default": 7
}, },
"promise_cpu_temperature_threshold": { "promise_cpu_max_spot_temp": {
"title": "CPU temperature promise threshold", "title": "Maximum CPU spot temperature",
"description": "Temperature threshold above which CPU temperature promise will fail", "description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number", "type": "number",
"default": 90 "default": 90
}, },
"promise_cpu_avg_temperature_threshold": { "promise_cpu_max_avg_temp": {
"title": "Average CPU temperature promise threshold", "title": "Maximum average CPU temperature",
"description": "If average temperature over specified duration reaches this threshold, promise will fail", "description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number", "type": "number",
"default": 80 "default": 80
}, },
"promise_cpu_avg_temperature_threshold_duration": { "promise_cpu_avg_temp_period": {
"title": "Average CPU temperature promise threshold duration", "title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold", "description": "Duration during which average temperature should not exceed specified threshold",
"type": "number", "type": "number",
"default": 600 "default": 600
......
...@@ -85,6 +85,12 @@ ...@@ -85,6 +85,12 @@
"type": "string", "type": "string",
"default": "0x12345" "default": "0x12345"
}, },
"gnb_id_bits": {
"title": "gNB ID bits",
"description": "Number of bits for the gNodeB global identifier. (range 22 to 32)",
"type": "number",
"default": 28
},
"pci": { "pci": {
"title": "Physical Cell ID", "title": "Physical Cell ID",
"description": "Physical Cell ID", "description": "Physical Cell ID",
...@@ -170,9 +176,9 @@ ...@@ -170,9 +176,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses", "description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean" "type": "boolean"
}, },
"enb_stats_fetch_period": { "gnb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)", "title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics", "description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number", "type": "number",
"default": 60 "default": 60
}, },
......
...@@ -67,6 +67,12 @@ ...@@ -67,6 +67,12 @@
"type": "string", "type": "string",
"default": "0x12345" "default": "0x12345"
}, },
"gnb_id_bits": {
"title": "gNB ID bits",
"description": "Number of bits for the gNodeB global identifier. (range 22 to 32)",
"type": "number",
"default": 28
},
"pci": { "pci": {
"title": "Physical Cell ID", "title": "Physical Cell ID",
"description": "Physical Cell ID", "description": "Physical Cell ID",
...@@ -152,9 +158,9 @@ ...@@ -152,9 +158,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses", "description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean" "type": "boolean"
}, },
"enb_stats_fetch_period": { "gnb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)", "title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics", "description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number", "type": "number",
"default": 60 "default": 60
}, },
......
...@@ -21,6 +21,16 @@ ...@@ -21,6 +21,16 @@
"description": "Activate iperf3 UDP server", "description": "Activate iperf3 UDP server",
"type": "boolean" "type": "boolean"
}, },
"rrh": {
"title": "RRH",
"description": "RRH",
"type": "string",
"default": "SDR",
"enum": [
"SDR",
"Lopcomm ORAN"
]
},
"tx_gain": { "tx_gain": {
"title": "Tx gain", "title": "Tx gain",
"description": "Tx gain (in dB)", "description": "Tx gain (in dB)",
...@@ -142,20 +152,20 @@ ...@@ -142,20 +152,20 @@
"type": "number", "type": "number",
"default": 7 "default": 7
}, },
"promise_cpu_temperature_threshold": { "promise_cpu_max_spot_temp": {
"title": "CPU temperature promise threshold", "title": "Maximum CPU spot temperature",
"description": "Temperature threshold above which CPU temperature promise will fail", "description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number", "type": "number",
"default": 90 "default": 90
}, },
"promise_cpu_avg_temperature_threshold": { "promise_cpu_max_avg_temp": {
"title": "Average CPU temperature promise threshold", "title": "Maximum average CPU temperature",
"description": "If average temperature over specified duration reaches this threshold, promise will fail", "description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number", "type": "number",
"default": 80 "default": 80
}, },
"promise_cpu_avg_temperature_threshold_duration": { "promise_cpu_avg_temp_period": {
"title": "Average CPU temperature promise threshold duration", "title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold", "description": "Duration during which average temperature should not exceed specified threshold",
"type": "number", "type": "number",
"default": 600 "default": 600
......
...@@ -3,6 +3,16 @@ ...@@ -3,6 +3,16 @@
"$schema": "http://json-schema.org/draft-04/schema", "$schema": "http://json-schema.org/draft-04/schema",
"title": "Input Parameters", "title": "Input Parameters",
"properties": { "properties": {
"rrh": {
"title": "RRH",
"description": "RRH",
"type": "string",
"default": "SDR",
"enum": [
"SDR",
"Lopcomm ORAN"
]
},
"tx_gain": { "tx_gain": {
"title": "Tx gain", "title": "Tx gain",
"description": "Tx gain (in dB)", "description": "Tx gain (in dB)",
...@@ -124,20 +134,20 @@ ...@@ -124,20 +134,20 @@
"type": "number", "type": "number",
"default": 7 "default": 7
}, },
"promise_cpu_temperature_threshold": { "promise_cpu_max_spot_temp": {
"title": "CPU temperature promise threshold", "title": "Maximum CPU spot temperature",
"description": "Temperature threshold above which CPU temperature promise will fail", "description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number", "type": "number",
"default": 90 "default": 90
}, },
"promise_cpu_avg_temperature_threshold": { "promise_cpu_max_avg_temp": {
"title": "Average CPU temperature promise threshold", "title": "Maximum average CPU temperature",
"description": "If average temperature over specified duration reaches this threshold, promise will fail", "description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number", "type": "number",
"default": 80 "default": 80
}, },
"promise_cpu_avg_temperature_threshold_duration": { "promise_cpu_avg_temp_period": {
"title": "Average CPU temperature promise threshold duration", "title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold", "description": "Duration during which average temperature should not exceed specified threshold",
"type": "number", "type": "number",
"default": 600 "default": 600
......
...@@ -85,6 +85,12 @@ ...@@ -85,6 +85,12 @@
"type": "string", "type": "string",
"default": "0x12345" "default": "0x12345"
}, },
"gnb_id_bits": {
"title": "gNB ID bits",
"description": "Number of bits for the gNodeB global identifier. (range 22 to 32)",
"type": "number",
"default": 28
},
"pci": { "pci": {
"title": "Physical Cell ID", "title": "Physical Cell ID",
"description": "Physical Cell ID", "description": "Physical Cell ID",
...@@ -170,9 +176,9 @@ ...@@ -170,9 +176,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses", "description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean" "type": "boolean"
}, },
"enb_stats_fetch_period": { "gnb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)", "title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics", "description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number", "type": "number",
"default": 60 "default": 60
}, },
......
...@@ -67,6 +67,12 @@ ...@@ -67,6 +67,12 @@
"type": "string", "type": "string",
"default": "0x12345" "default": "0x12345"
}, },
"gnb_id_bits": {
"title": "gNB ID bits",
"description": "Number of bits for the gNodeB global identifier. (range 22 to 32)",
"type": "number",
"default": 28
},
"pci": { "pci": {
"title": "Physical Cell ID", "title": "Physical Cell ID",
"description": "Physical Cell ID", "description": "Physical Cell ID",
...@@ -152,9 +158,9 @@ ...@@ -152,9 +158,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses", "description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean" "type": "boolean"
}, },
"enb_stats_fetch_period": { "gnb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)", "title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics", "description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number", "type": "number",
"default": 60 "default": 60
}, },
......
...@@ -21,6 +21,16 @@ ...@@ -21,6 +21,16 @@
"description": "Activate iperf3 UDP server", "description": "Activate iperf3 UDP server",
"type": "boolean" "type": "boolean"
}, },
"rrh": {
"title": "RRH",
"description": "RRH",
"type": "string",
"default": "SDR",
"enum": [
"SDR",
"Lopcomm ORAN"
]
},
"tx_gain": { "tx_gain": {
"title": "Tx gain", "title": "Tx gain",
"description": "Tx gain (in dB)", "description": "Tx gain (in dB)",
...@@ -142,20 +152,20 @@ ...@@ -142,20 +152,20 @@
"type": "number", "type": "number",
"default": 7 "default": 7
}, },
"promise_cpu_temperature_threshold": { "promise_cpu_max_spot_temp": {
"title": "CPU temperature promise threshold", "title": "Maximum CPU spot temperature",
"description": "Temperature threshold above which CPU temperature promise will fail", "description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number", "type": "number",
"default": 90 "default": 90
}, },
"promise_cpu_avg_temperature_threshold": { "promise_cpu_max_avg_temp": {
"title": "Average CPU temperature promise threshold", "title": "Maximum average CPU temperature",
"description": "If average temperature over specified duration reaches this threshold, promise will fail", "description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number", "type": "number",
"default": 80 "default": 80
}, },
"promise_cpu_avg_temperature_threshold_duration": { "promise_cpu_avg_temp_period": {
"title": "Average CPU temperature promise threshold duration", "title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold", "description": "Duration during which average temperature should not exceed specified threshold",
"type": "number", "type": "number",
"default": 600 "default": 600
......
...@@ -3,6 +3,16 @@ ...@@ -3,6 +3,16 @@
"$schema": "http://json-schema.org/draft-04/schema", "$schema": "http://json-schema.org/draft-04/schema",
"title": "Input Parameters", "title": "Input Parameters",
"properties": { "properties": {
"rrh": {
"title": "RRH",
"description": "RRH",
"type": "string",
"default": "SDR",
"enum": [
"SDR",
"Lopcomm ORAN"
]
},
"tx_gain": { "tx_gain": {
"title": "Tx gain", "title": "Tx gain",
"description": "Tx gain (in dB)", "description": "Tx gain (in dB)",
...@@ -124,20 +134,20 @@ ...@@ -124,20 +134,20 @@
"type": "number", "type": "number",
"default": 7 "default": 7
}, },
"promise_cpu_temperature_threshold": { "promise_cpu_max_spot_temp": {
"title": "CPU temperature promise threshold", "title": "Maximum CPU spot temperature",
"description": "Temperature threshold above which CPU temperature promise will fail", "description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number", "type": "number",
"default": 90 "default": 90
}, },
"promise_cpu_avg_temperature_threshold": { "promise_cpu_max_avg_temp": {
"title": "Average CPU temperature promise threshold", "title": "Maximum average CPU temperature",
"description": "If average temperature over specified duration reaches this threshold, promise will fail", "description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number", "type": "number",
"default": 80 "default": 80
}, },
"promise_cpu_avg_temperature_threshold_duration": { "promise_cpu_avg_temp_period": {
"title": "Average CPU temperature promise threshold duration", "title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold", "description": "Duration during which average temperature should not exceed specified threshold",
"type": "number", "type": "number",
"default": 600 "default": 600
......
...@@ -85,6 +85,12 @@ ...@@ -85,6 +85,12 @@
"type": "string", "type": "string",
"default": "0x12345" "default": "0x12345"
}, },
"gnb_id_bits": {
"title": "gNB ID bits",
"description": "Number of bits for the gNodeB global identifier. (range 22 to 32)",
"type": "number",
"default": 28
},
"pci": { "pci": {
"title": "Physical Cell ID", "title": "Physical Cell ID",
"description": "Physical Cell ID", "description": "Physical Cell ID",
...@@ -170,9 +176,9 @@ ...@@ -170,9 +176,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses", "description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean" "type": "boolean"
}, },
"enb_stats_fetch_period": { "gnb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)", "title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics", "description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number", "type": "number",
"default": 60 "default": 60
}, },
......
...@@ -67,6 +67,12 @@ ...@@ -67,6 +67,12 @@
"type": "string", "type": "string",
"default": "0x12345" "default": "0x12345"
}, },
"gnb_id_bits": {
"title": "gNB ID bits",
"description": "Number of bits for the gNodeB global identifier. (range 22 to 32)",
"type": "number",
"default": 28
},
"pci": { "pci": {
"title": "Physical Cell ID", "title": "Physical Cell ID",
"description": "Physical Cell ID", "description": "Physical Cell ID",
...@@ -152,9 +158,9 @@ ...@@ -152,9 +158,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses", "description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean" "type": "boolean"
}, },
"enb_stats_fetch_period": { "gnb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)", "title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics", "description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number", "type": "number",
"default": 60 "default": 60
}, },
......
...@@ -4,8 +4,8 @@ parts = ...@@ -4,8 +4,8 @@ parts =
ltelogs ltelogs
lte-ue-lte-config lte-ue-lte-config
lte-ue-service lte-ue-service
sdr-busy-promise check-sdr-busy.py
cpu-temperature-promise check-cpu-temperature.py
monitor-base monitor-base
publish-connection-information publish-connection-information
...@@ -66,11 +66,15 @@ offline = false ...@@ -66,11 +66,15 @@ offline = false
[lte-ue-sh-wrapper] [lte-ue-sh-wrapper]
recipe = slapos.recipe.template recipe = slapos.recipe.template
output = ${directory:bin}/${:_buildout_section_name_} output = ${directory:bin}/${:_buildout_section_name_}
ue-log = ${directory:log}/ue-output.log
inline = inline =
#!/bin/sh #!/bin/sh
{% if not slapparameter_dict.get("testing", False) %} {% if not slapparameter_dict.get("testing", False) %}
sudo /opt/amarisoft/rm-tmp-lte | true; sudo /opt/amarisoft/rm-tmp-lte | true;
{{ ue }}/lteue ${directory:etc}/ue.cfg >> ${directory:log}/ue-output.log 2>> ${directory:log}/ue-output.log (echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting UE software..." && echo) >> ${:ue-log};
tail -c 1M ${:ue-log} > ${:ue-log}.tmp;
mv ${:ue-log}.tmp ${:ue-log};
{{ ue }}/lteue ${directory:etc}/ue.cfg >> ${:ue-log} 2>> ${:ue-log};
{% endif %} {% endif %}
### User Equipment (UE) ### User Equipment (UE)
...@@ -121,23 +125,22 @@ monitor-title = {{ slapparameter_dict['name'] | string }} ...@@ -121,23 +125,22 @@ monitor-title = {{ slapparameter_dict['name'] | string }}
password = {{ slapparameter_dict['monitor-password'] | string }} password = {{ slapparameter_dict['monitor-password'] | string }}
{% endif %} {% endif %}
# Add custom promise to check if /dev/sdr0 is busy [macro.promise]
[sdr-busy-promise] <= monitor-promise-base
recipe = slapos.cookbook:promise.plugin name = ${:_buildout_section_name_}
eggs = slapos.core
file = {{ sdr_busy_promise }} [check-cpu-temperature.py]
output = ${directory:plugins}/check-sdr-busy.py <= macro.promise
promise = check_cpu_temperature
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }} config-frequency = {{ slapparameter_dict.get("promise_cpu_temperature_frequency", 5) }}
config-max-spot-temp = {{ slapparameter_dict.get("promise_cpu_max_spot_temp", 90) }}
config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_max_avg_temp", 80) }}
config-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temp_duration", 600) }}
config-avg-flag-file = ${directory:var}/promise_cpu_avg_flag_file
[cpu-temperature-promise] [check-sdr-busy.py]
recipe = slapos.cookbook:promise.plugin <= macro.promise
eggs = promise = check_sdr_busy
slapos.core
python-dateutil
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }} config-sdr = {{ sdr }}
config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold", 80) }}
config-max-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold_duration", 600) }}
...@@ -4,8 +4,8 @@ parts = ...@@ -4,8 +4,8 @@ parts =
ltelogs ltelogs
lte-ue-nr-config lte-ue-nr-config
lte-ue-service lte-ue-service
sdr-busy-promise check-sdr-busy.py
cpu-temperature-promise check-cpu-temperature.py
monitor-base monitor-base
publish-connection-information publish-connection-information
...@@ -68,11 +68,15 @@ offline = false ...@@ -68,11 +68,15 @@ offline = false
[lte-ue-sh-wrapper] [lte-ue-sh-wrapper]
recipe = slapos.recipe.template recipe = slapos.recipe.template
output = ${directory:bin}/${:_buildout_section_name_} output = ${directory:bin}/${:_buildout_section_name_}
ue-log = ${directory:log}/ue-output.log
inline = inline =
#!/bin/sh #!/bin/sh
{% if not slapparameter_dict.get("testing", False) %} {% if not slapparameter_dict.get("testing", False) %}
sudo /opt/amarisoft/rm-tmp-lte | true; sudo /opt/amarisoft/rm-tmp-lte | true;
{{ ue }}/lteue ${directory:etc}/ue.cfg >> ${directory:log}/ue-output.log 2>> ${directory:log}/ue-output.log (echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting UE software..." && echo) >> ${:ue-log};
tail -c 1M ${:ue-log} > ${:ue-log}.tmp;
mv ${:ue-log}.tmp ${:ue-log};
{{ ue }}/lteue ${directory:etc}/ue.cfg >> ${:ue-log} 2>> ${:ue-log};
{% endif %} {% endif %}
### User Equipment (UE) ### User Equipment (UE)
...@@ -124,23 +128,22 @@ monitor-title = {{ slapparameter_dict['name'] | string }} ...@@ -124,23 +128,22 @@ monitor-title = {{ slapparameter_dict['name'] | string }}
password = {{ slapparameter_dict['monitor-password'] | string }} password = {{ slapparameter_dict['monitor-password'] | string }}
{% endif %} {% endif %}
# Add custom promise to check if /dev/sdr0 is busy [macro.promise]
[sdr-busy-promise] <= monitor-promise-base
recipe = slapos.cookbook:promise.plugin name = ${:_buildout_section_name_}
eggs = slapos.core
file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }}
[cpu-temperature-promise] [check-cpu-temperature.py]
recipe = slapos.cookbook:promise.plugin <= macro.promise
eggs = promise = check_cpu_temperature
slapos.core
python-dateutil
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }} config-frequency = {{ slapparameter_dict.get("promise_cpu_temperature_frequency", 5) }}
config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold", 80) }} config-max-spot-temp = {{ slapparameter_dict.get("promise_cpu_max_spot_temp", 90) }}
config-max-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temperature_threshold_duration", 600) }} config-max-avg-temp = {{ slapparameter_dict.get("promise_cpu_max_avg_temp", 80) }}
config-avg-temp-duration = {{ slapparameter_dict.get("promise_cpu_avg_temp_duration", 600) }}
config-avg-flag-file = ${directory:var}/promise_cpu_avg_flag_file
[check-sdr-busy.py]
<= macro.promise
promise = check_sdr_busy
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }}
...@@ -31,8 +31,11 @@ context = ...@@ -31,8 +31,11 @@ context =
[amarisoft] [amarisoft]
recipe = slapos.recipe.build recipe = slapos.recipe.build
init = init =
import os import os, re
lte_version = "2021-09-18" try:
lte_version = sorted(filter(lambda x: re.match(r"v[0-9]{4}-[0-9]{2}-[0-9]{2}", x), os.listdir('/opt/amarisoft')))[-1][1:]
except FileNotFoundError:
lte_version = 'LTEVERSION'
path = "/opt/amarisoft/v" + lte_version path = "/opt/amarisoft/v" + lte_version
options['lte-version'] = lte_version options['lte-version'] = lte_version
options['path'] = path options['path'] = path
...@@ -75,7 +78,6 @@ extensions = jinja2.ext.do ...@@ -75,7 +78,6 @@ extensions = jinja2.ext.do
extra-context = extra-context =
raw monitor_template ${monitor2-template:output} raw monitor_template ${monitor2-template:output}
key slave_instance_list slap-configuration:slave-instance-list key slave_instance_list slap-configuration:slave-instance-list
raw cpu_temperature_promise ${cpu-temperature-promise:target}
[dynamic-template-lte-gnb-epc] [dynamic-template-lte-gnb-epc]
< = jinja2-template-base < = jinja2-template-base
...@@ -85,7 +87,6 @@ extensions = jinja2.ext.do ...@@ -85,7 +87,6 @@ extensions = jinja2.ext.do
extra-context = extra-context =
raw monitor_template ${monitor2-template:output} raw monitor_template ${monitor2-template:output}
key slave_instance_list slap-configuration:slave-instance-list key slave_instance_list slap-configuration:slave-instance-list
raw cpu_temperature_promise ${cpu-temperature-promise:target}
[dynamic-template-lte-epc] [dynamic-template-lte-epc]
< = jinja2-template-base < = jinja2-template-base
...@@ -95,7 +96,6 @@ extensions = jinja2.ext.do ...@@ -95,7 +96,6 @@ extensions = jinja2.ext.do
extra-context = extra-context =
raw monitor_template ${monitor2-template:output} raw monitor_template ${monitor2-template:output}
key slave_instance_list slap-configuration:slave-instance-list key slave_instance_list slap-configuration:slave-instance-list
raw cpu_temperature_promise ${cpu-temperature-promise:target}
[dynamic-template-lte-enb] [dynamic-template-lte-enb]
< = jinja2-template-base < = jinja2-template-base
...@@ -110,12 +110,8 @@ extra-context = ...@@ -110,12 +110,8 @@ extra-context =
raw sib23 ${sib23.asn:target} raw sib23 ${sib23.asn:target}
raw ltelogs_template ${ltelogs.jinja2.sh:target} raw ltelogs_template ${ltelogs.jinja2.sh:target}
raw amarisoft_stats_template ${amarisoft-stats.jinja2.py:target} raw amarisoft_stats_template ${amarisoft-stats.jinja2.py:target}
raw sdr_busy_promise ${sdr-busy-promise:target} raw amarisoft_rf_info_template ${amarisoft-rf-info.jinja2.py:target}
raw cell_gain_saturated_promise ${cell-gain-saturated-promise:target} raw lopcomm_rrh_stats_template ${lopcomm-rrh-stats.jinja2.py:target}
raw rx_saturated_promise ${rx-saturated-promise:target}
raw baseband_latency_promise ${baseband-latency-promise:target}
raw amarisoft_stats_log_promise ${amarisoft-stats-log-promise:target}
raw cpu_temperature_promise ${cpu-temperature-promise:target}
raw openssl_location ${openssl:location} raw openssl_location ${openssl:location}
raw default_dl_earfcn ${default-params:default-dl-earfcn} raw default_dl_earfcn ${default-params:default-dl-earfcn}
raw default_lte_dl_freq ${default-params:default-lte-dl-freq} raw default_lte_dl_freq ${default-params:default-lte-dl-freq}
...@@ -141,12 +137,7 @@ extra-context = ...@@ -141,12 +137,7 @@ extra-context =
raw gnb_template ${gnb.jinja2.cfg:target} raw gnb_template ${gnb.jinja2.cfg:target}
raw ltelogs_template ${ltelogs.jinja2.sh:target} raw ltelogs_template ${ltelogs.jinja2.sh:target}
raw amarisoft_stats_template ${amarisoft-stats.jinja2.py:target} raw amarisoft_stats_template ${amarisoft-stats.jinja2.py:target}
raw sdr_busy_promise ${sdr-busy-promise:target} raw amarisoft_rf_info_template ${amarisoft-rf-info.jinja2.py:target}
raw cell_gain_saturated_promise ${cell-gain-saturated-promise:target}
raw rx_saturated_promise ${rx-saturated-promise:target}
raw baseband_latency_promise ${baseband-latency-promise:target}
raw amarisoft_stats_log_promise ${amarisoft-stats-log-promise:target}
raw cpu_temperature_promise ${cpu-temperature-promise:target}
raw openssl_location ${openssl:location} raw openssl_location ${openssl:location}
raw default_dl_nr_arfcn ${default-params:default-dl-nr-arfcn} raw default_dl_nr_arfcn ${default-params:default-dl-nr-arfcn}
raw default_nr_band ${default-params:default-nr-band} raw default_nr_band ${default-params:default-nr-band}
...@@ -169,7 +160,6 @@ filename = instance-lte-mme.cfg ...@@ -169,7 +160,6 @@ filename = instance-lte-mme.cfg
extensions = jinja2.ext.do extensions = jinja2.ext.do
extra-context = extra-context =
raw monitor_template ${monitor2-template:output} raw monitor_template ${monitor2-template:output}
raw interface_up_promise ${interface-up-promise:target}
key mme amarisoft:mme key mme amarisoft:mme
raw mme_template ${mme.jinja2.cfg:target} raw mme_template ${mme.jinja2.cfg:target}
raw ims_template ${ims.jinja2.cfg:target} raw ims_template ${ims.jinja2.cfg:target}
...@@ -186,13 +176,10 @@ filename = instance-lte-ue-lte.cfg ...@@ -186,13 +176,10 @@ filename = instance-lte-ue-lte.cfg
extensions = jinja2.ext.do extensions = jinja2.ext.do
extra-context = extra-context =
raw monitor_template ${monitor2-template:output} raw monitor_template ${monitor2-template:output}
raw interface_up_promise ${interface-up-promise:target}
key ue amarisoft:ue key ue amarisoft:ue
key sdr amarisoft:sdr key sdr amarisoft:sdr
raw ue_lte_template ${ue-lte.jinja2.cfg:target} raw ue_lte_template ${ue-lte.jinja2.cfg:target}
raw ltelogs_template ${ltelogs.jinja2.sh:target} raw ltelogs_template ${ltelogs.jinja2.sh:target}
raw sdr_busy_promise ${sdr-busy-promise:target}
raw cpu_temperature_promise ${cpu-temperature-promise:target}
raw openssl_location ${openssl:location} raw openssl_location ${openssl:location}
raw default_dl_earfcn ${default-params:default-dl-earfcn} raw default_dl_earfcn ${default-params:default-dl-earfcn}
raw default_lte_dl_freq ${default-params:default-lte-dl-freq} raw default_lte_dl_freq ${default-params:default-lte-dl-freq}
...@@ -211,13 +198,10 @@ filename = instance-lte-ue-nr.cfg ...@@ -211,13 +198,10 @@ filename = instance-lte-ue-nr.cfg
extensions = jinja2.ext.do extensions = jinja2.ext.do
extra-context = extra-context =
raw monitor_template ${monitor2-template:output} raw monitor_template ${monitor2-template:output}
raw interface_up_promise ${interface-up-promise:target}
key ue amarisoft:ue key ue amarisoft:ue
key sdr amarisoft:sdr key sdr amarisoft:sdr
raw ue_nr_template ${ue-nr.jinja2.cfg:target} raw ue_nr_template ${ue-nr.jinja2.cfg:target}
raw cpu_temperature_promise ${cpu-temperature-promise:target}
raw ltelogs_template ${ltelogs.jinja2.sh:target} raw ltelogs_template ${ltelogs.jinja2.sh:target}
raw sdr_busy_promise ${sdr-busy-promise:target}
raw openssl_location ${openssl:location} raw openssl_location ${openssl:location}
raw default_dl_nr_arfcn ${default-params:default-dl-nr-arfcn} raw default_dl_nr_arfcn ${default-params:default-dl-nr-arfcn}
raw default_nr_band ${default-params:default-nr-band} raw default_nr_band ${default-params:default-nr-band}
......
#!{{ 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 }}"
self.logger = logging.getLogger('logger')
self.json_logger = logging.getLogger('json_logger')
self.logger.setLevel(logging.DEBUG)
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)
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': 'huawei'
},
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)
self.json_logger.info('', extra={'data': data_dict})
def close(self):
# Close not compatible between ncclient and netconf server
#self.conn.close()
pass
if __name__ == '__main__':
nc = LopcommNetconfClient()
while True:
try:
nc.connect("192.168.0.210", 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()
import errno
import json
import os
from datetime import datetime
from dateutil import parser
from zope.interface import implementer
from slapos.grid.promise import interface
from slapos.grid.promise.generic import GenericPromise
# Get latest timestamp from JSON log
def get_latest_timestamp(log):
log_number = 0
while True:
try:
f = open("{}.{}".format(log, log_number) if log_number else log, "rb")
except OSError:
return 0
try:
f.seek(0, os.SEEK_END)
try:
while f.seek(-2, os.SEEK_CUR) and f.read(1) != b'\n':
pass
except OSError:
break
l = json.loads(f.readline().decode().replace("'", '"'))
return parser.parse(l['time'])
finally:
f.close()
log_number += 1
return 0
@implementer(interface.IPromise)
class RunPromise(GenericPromise):
def __init__(self, config):
super(RunPromise, self).__init__(config)
self.setPeriodicity(minute=1)
def sense(self):
amarisoft_stats_log = self.getConfig('amarisoft-stats-log')
stats_period = int(self.getConfig('stats-period'))
latest_timestamp = get_latest_timestamp(amarisoft_stats_log)
delta = (datetime.now() - latest_timestamp).total_seconds()
if delta > stats_period * 2:
self.logger.error("Latest entry from amarisoft statistics log too "\
"old (%s seconds old)" % (delta,))
else:
self.logger.info("Latest entry from amarisoft statistics is "\
"%s seconds old" % (delta,))
def test(self):
"""
Called after sense() if the instance is still converging.
Returns success or failure based on sense results.
In this case, fail if the previous sensor result is negative.
"""
return self._test(result_count=1, failure_amount=1)
def anomaly(self):
"""
Called after sense() if the instance has finished converging.
Returns success or failure based on sense results.
Failure signals the instance has diverged.
In this case, fail if two out of the last three results are negative.
"""
return self._anomaly(result_count=1, failure_amount=1)
import errno
import json
import logging
import os
from dateutil import parser
from zope.interface import implementer
from slapos.grid.promise import interface
from slapos.grid.promise.generic import GenericPromise
# Get all data in the last "interval" seconds from JSON log
def get_data_interval(log, interval):
log_number = 0
latest_timestamp = 0
data_list = []
while True:
try:
f = open("{}.{}".format(log, log_number) if log_number else log, "rb")
except OSError:
return data_list
try:
f.seek(0, os.SEEK_END)
while True:
try:
while f.seek(-2, os.SEEK_CUR) and f.read(1) != b'\n':
pass
except OSError:
break
pos = f.tell()
l = json.loads(f.readline().decode().replace("'", '"'))
timestamp = parser.parse(l['time'])
data_list.append(l['data'])
if not latest_timestamp:
latest_timestamp = timestamp
if (latest_timestamp - timestamp).total_seconds() > interval:
return data_list
f.seek(pos, os.SEEK_SET)
finally:
f.close()
log_number += 1
@implementer(interface.IPromise)
class RunPromise(GenericPromise):
def __init__(self, config):
self.__name = config.get('name', None)
self.__log_folder = config.get('log-folder', None)
super(RunPromise, self).__init__(config)
self.setPeriodicity(minute=1)
self.__title = os.path.splitext(self.__name)[0]
self.__log_file = os.path.join(self.__log_folder, '%s.json.log' % self.__title)
self.json_logger = logging.getLogger('json_logger')
self.json_logger.setLevel(logging.INFO)
handler = logging.FileHandler(self.__log_file)
formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
handler.setFormatter(formatter)
self.json_logger.addHandler(handler)
def sense(self):
testing = self.getConfig('testing') == "True"
if testing:
self.logger.info("skipping promise")
return
amarisoft_stats_log = self.getConfig('amarisoft-stats-log')
stats_period = int(self.getConfig('stats-period'))
min_txrx_delay = float(self.getConfig('min-txrx-delay', 5))
avg_txrx_delay = float(self.getConfig('avg-txrx-delay', 7))
data_list = get_data_interval(amarisoft_stats_log, stats_period * 2)
min_txrx_delay_list = []
avg_txrx_delay_list = []
min_unavailable = False
avg_unavailable = False
for data in data_list:
rf_list = data['rf']
if not min_txrx_delay_list:
min_txrx_delay_list = [99 for x in rf_list]
if not avg_txrx_delay_list:
avg_txrx_delay_list = [99 for x in rf_list]
for i, rxtx_delay_avg in enumerate(rf_list):
min_txrx_delay_list[i] = min(min_txrx_delay_list[i], float(rf_list['rxtx_delay_min']))
min_delay = min_txrx_delay_list[i]
if min_txrx_delay_list[i] >= min_txrx_delay:
min_unavailable = True
for i, rxtx_delay_avg in enumerate(rf_list):
avg_txrx_delay_list[i] = min(avg_txrx_delay_list[i], float(rf_list['rxtx_delay_avg']))
avg_delay = avg_txrx_delay_list[i]
if avg_txrx_delay_list[i] >= avg_txrx_delay:
avg_unavailable = True
self.json_logger.info("The minimum available time for radio front end processing (ms)",
extra={'data': min_txrx_delay_list})
if not min_txrx_delay_list or not avg_txrx_delay:
self.logger.error("No TX/RX diff data available")
elif min_unavailable:
self.logger.error("The minimum available time %s (ms) for radio front end processing is higher than a threshold %s (ms) depending on the radio front end." % (min_delay, min_txrx_delay))
elif avg_unavailable:
self.logger.error("The average available time %s (ms) for radio front end processing is higher than a threshold %s (ms) depending on the radio front end." % (avg_delay, avg_txrx_delay))
else:
self.logger.info("The minimum %s (ms) and average %s (ms) available time for radio front end processing OK" % (min_delay, avg_delay))
def test(self):
"""
Called after sense() if the instance is still converging.
Returns success or failure based on sense results.
In this case, fail if the previous sensor result is negative.
"""
return self._test(result_count=1, failure_amount=1)
def anomaly(self):
"""
Called after sense() if the instance has finished converging.
Returns success or failure based on sense results.
Failure signals the instance has diverged.
In this case, fail if two out of the last three results are negative.
"""
return self._anomaly(result_count=1, failure_amount=1)
import errno
import json
import logging
import os
from dateutil import parser
from zope.interface import implementer
from slapos.grid.promise import interface
from slapos.grid.promise.generic import GenericPromise
# Get latest data and data from "interval" seconds ago from JSON log
def get_data_interval(log, interval):
log_number = 0
latest_timestamp = 0
latest_data = {}
while True:
try:
f = open("{}.{}".format(log, log_number) if log_number else log, "rb")
except OSError:
return latest_data, {}
try:
f.seek(0, os.SEEK_END)
while True:
try:
while f.seek(-2, os.SEEK_CUR) and f.read(1) != b'\n':
pass
except OSError:
break
pos = f.tell()
l = json.loads(f.readline().decode().replace("'", '"'))
timestamp = parser.parse(l['time'])
if not latest_timestamp:
latest_timestamp = timestamp
latest_data = l['data']
if (latest_timestamp - timestamp).total_seconds() > interval:
return latest_data, l['data']
f.seek(pos, os.SEEK_SET)
finally:
f.close()
log_number += 1
@implementer(interface.IPromise)
class RunPromise(GenericPromise):
def __init__(self, config):
self.__name = config.get('name', None)
self.__log_folder = config.get('log-folder', None)
super(RunPromise, self).__init__(config)
self.setPeriodicity(minute=1)
self.__title = os.path.splitext(self.__name)[0]
self.__log_file = os.path.join(self.__log_folder, '%s.json.log' % self.__title)
self.json_logger = logging.getLogger('json_logger')
self.json_logger.setLevel(logging.INFO)
handler = logging.FileHandler(self.__log_file)
formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
handler.setFormatter(formatter)
self.json_logger.addHandler(handler)
def sense(self):
testing = self.getConfig('testing') == "True"
amarisoft_stats_log = self.getConfig('amarisoft-stats-log')
stats_period = int(self.getConfig('stats-period'))
latest_data, previous_data = get_data_interval(amarisoft_stats_log, stats_period * 2)
def get_saturation_events(data):
if data:
return sum([x['sat'] for x in data['samples']['rx']])
return 0
saturation_events = get_saturation_events(latest_data) - \
get_saturation_events(previous_data)
self.json_logger.info("Saturation events",
extra={'data': {'recent_saturation_events': saturation_events}})
if saturation_events:
self.logger.error("Reception saturated, please lower cell_gain")
else:
self.logger.info("No saturation events on reception")
def test(self):
"""
Called after sense() if the instance is still converging.
Returns success or failure based on sense results.
In this case, fail if the previous sensor result is negative.
"""
return self._test(result_count=1, failure_amount=1)
def anomaly(self):
"""
Called after sense() if the instance has finished converging.
Returns success or failure based on sense results.
Failure signals the instance has diverged.
In this case, fail if two out of the last three results are negative.
"""
return self._anomaly(result_count=1, failure_amount=1)
import socket
import errno
import logging
import json
import os
import psutil
from dateutil import parser
from zope.interface import implementer
from slapos.grid.promise import interface
from slapos.grid.promise.generic import GenericPromise
# Get all data in the last "interval" seconds from JSON log
def get_data_interval(log, interval):
log_number = 0
latest_timestamp = 0
data_list = []
while True:
try:
f = open("{}.{}".format(log, log_number) if log_number else log, "rb")
except OSError:
return data_list
try:
f.seek(0, os.SEEK_END)
while True:
try:
while f.seek(-2, os.SEEK_CUR) and f.read(1) != b'\n':
pass
except OSError:
break
pos = f.tell()
l = json.loads(f.readline().decode().replace("'", '"'))
timestamp = parser.parse(l['time'])
data_list.append(l['data'])
if not latest_timestamp:
latest_timestamp = timestamp
if (latest_timestamp - timestamp).total_seconds() > interval:
return data_list
f.seek(pos, os.SEEK_SET)
finally:
f.close()
log_number += 1
@implementer(interface.IPromise)
class RunPromise(GenericPromise):
def __init__(self, config):
self.__name = config.get('name', None)
self.__log_folder = config.get('log-folder', None)
super(RunPromise, self).__init__(config)
self.setPeriodicity(minute=2)
self.__title = os.path.splitext(self.__name)[0]
self.__log_file = os.path.join(self.__log_folder, '%s.json.log' % self.__title)
self.json_logger = logging.getLogger('json_logger')
self.json_logger.setLevel(logging.INFO)
handler = logging.FileHandler(self.__log_file)
formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
handler.setFormatter(formatter)
self.json_logger.addHandler(handler)
def sense(self):
max_temp = float(self.getConfig('max-temp', 90))
max_avg_temp = float(self.getConfig('max-avg-temp', 80))
max_avg_temp_duration = int(self.getConfig('max-avg-temp-duration', 300))
testing = self.getConfig('testing') == "True"
if testing:
from random import randint
cpu_temp = randint(40, 75)
else:
data = psutil.sensors_temperatures()
cpu_temp = data['coretemp'][0][1]
l = get_data_interval(self.__log_file, max_avg_temp_duration) or [{'cpu_temperature': cpu_temp}]
avg_temp = sum(map(lambda x: x['cpu_temperature'], l)) / len(l)
data = json.dumps({'cpu_temperature': cpu_temp, 'avg_cpu_temperature': avg_temp})
self.json_logger.info("Temperature data", extra={'data': data})
promise_success = True
if cpu_temp > max_temp:
self.logger.error("Temperature reached critical threshold: %s degrees celsius (threshold is %s degrees celsius)" % (cpu_temp, max_temp))
promise_success = False
if avg_temp > max_avg_temp:
self.logger.error("Average temperature over the last %s seconds reached threshold: %s degrees celsius (threshold is %s degrees celsius)" % (max_avg_temp_duration, avg_temp, max_avg_temp))
promise_success = False
if promise_success:
self.logger.info("Temperature OK")
def test(self):
"""
Called after sense() if the instance is still converging.
Returns success or failure based on sense results.
In this case, fail if the previous sensor result is negative.
"""
return self._test(result_count=1, failure_amount=1)
def anomaly(self):
"""
Called after sense() if the instance has finished converging.
Returns success or failure based on sense results.
Failure signals the instance has diverged.
In this case, fail if two out of the last three results are negative.
"""
return self._anomaly(result_count=3, failure_amount=2)
import socket
import errno
from zope.interface import implementer
from slapos.grid.promise import interface
from slapos.grid.promise.generic import GenericPromise
@implementer(interface.IPromise)
class RunPromise(GenericPromise):
def __init__(self, config):
super(RunPromise, self).__init__(config)
self.setPeriodicity(minute=2)
def sense(self):
ifname = self.getConfig('ifname')
testing = self.getConfig('testing') == "True"
if testing:
self.logger.info("skipping promise")
return
f = open('/sys/class/net/%s/operstate' % ifname, 'r')
if f.read() == 'up\n':
self.logger.info("%s is up", ifname)
else:
self.logger.error("%s is down", ifname)
f.close()
def test(self):
"""
Called after sense() if the instance is still converging.
Returns success or failure based on sense results.
In this case, fail if the previous sensor result is negative.
"""
return self._test(result_count=1, failure_amount=1)
def anomaly(self):
"""
Called after sense() if the instance has finished converging.
Returns success or failure based on sense results.
Failure signals the instance has diverged.
In this case, fail if two out of the last three results are negative.
"""
return self._anomaly(result_count=3, failure_amount=2)
import errno
import json
import logging
import os
from dateutil import parser
from zope.interface import implementer
from slapos.grid.promise import interface
from slapos.grid.promise.generic import GenericPromise
# Get all data in the last "interval" seconds from JSON log
def get_data_interval(log, interval):
log_number = 0
latest_timestamp = 0
data_list = []
while True:
try:
f = open("{}.{}".format(log, log_number) if log_number else log, "rb")
except OSError:
return data_list
try:
f.seek(0, os.SEEK_END)
while True:
try:
while f.seek(-2, os.SEEK_CUR) and f.read(1) != b'\n':
pass
except OSError:
break
pos = f.tell()
l = json.loads(f.readline().decode().replace("'", '"'))
timestamp = parser.parse(l['time'])
data_list.append(l['data'])
if not latest_timestamp:
latest_timestamp = timestamp
if (latest_timestamp - timestamp).total_seconds() > interval:
return data_list
f.seek(pos, os.SEEK_SET)
finally:
f.close()
log_number += 1
@implementer(interface.IPromise)
class RunPromise(GenericPromise):
def __init__(self, config):
self.__name = config.get('name', None)
self.__log_folder = config.get('log-folder', None)
super(RunPromise, self).__init__(config)
self.setPeriodicity(minute=1)
self.__title = os.path.splitext(self.__name)[0]
self.__log_file = os.path.join(self.__log_folder, '%s.json.log' % self.__title)
self.json_logger = logging.getLogger('json_logger')
self.json_logger.setLevel(logging.INFO)
handler = logging.FileHandler(self.__log_file)
formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
handler.setFormatter(formatter)
self.json_logger.addHandler(handler)
def sense(self):
testing = self.getConfig('testing') == "True"
amarisoft_stats_log = self.getConfig('amarisoft-stats-log')
stats_period = int(self.getConfig('stats-period'))
max_rx_sample_db = float(self.getConfig('max-rx-sample-db'))
data_list = get_data_interval(amarisoft_stats_log, stats_period * 2)
max_rx = []
saturated = False
for data in data_list:
rx_list = data['samples']['rx']
if not max_rx:
max_rx = [-99.9 for x in rx_list]
for i, rx in enumerate(rx_list):
max_rx[i] = max(max_rx[i], float(rx['max']))
if max_rx[i] >= max_rx_sample_db:
saturated = True
self.json_logger.info("RX maximum sample values (dB)",
extra={'data': max_rx})
if not max_rx:
self.logger.error("No RX samples data available")
elif saturated:
self.logger.error("RX antenna saturated, please lower rx_gain")
else:
self.logger.info("No saturation detected on RX antenna")
def test(self):
"""
Called after sense() if the instance is still converging.
Returns success or failure based on sense results.
In this case, fail if the previous sensor result is negative.
"""
return self._test(result_count=1, failure_amount=1)
def anomaly(self):
"""
Called after sense() if the instance has finished converging.
Returns success or failure based on sense results.
Failure signals the instance has diverged.
In this case, fail if two out of the last three results are negative.
"""
return self._anomaly(result_count=1, failure_amount=1)
import os
import errno
import subprocess
from zope.interface import implementer
from slapos.grid.promise import interface
from slapos.grid.promise.generic import GenericPromise
@implementer(interface.IPromise)
class RunPromise(GenericPromise):
def __init__(self, config):
super(RunPromise, self).__init__(config)
self.setPeriodicity(minute=1)
def sense(self):
testing = self.getConfig('testing') == "True"
sdr = self.getConfig('sdr')
if testing:
self.logger.info("skipping promise")
return
try:
out = subprocess.check_output([
sdr + '/sdr_util', '-c', '0', 'version'], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
if e.returncode == 1 and \
("DMA channel is already opened" in e.output.decode() or \
"Device or resource busy" in e.output.decode()):
self.logger.info("eNB is using /dev/sdr0")
return
self.logger.error("eNB is not using /dev/sdr0")
def test(self):
"""
Called after sense() if the instance is still converging.
Returns success or failure based on sense results.
In this case, fail if the previous sensor result is negative.
"""
return self._test(result_count=1, failure_amount=1)
def anomaly(self):
"""
Called after sense() if the instance has finished converging.
Returns success or failure based on sense results.
Failure signals the instance has diverged.
In this case, fail if two out of the last three results are negative.
"""
return self._anomaly(result_count=1, failure_amount=1)
#!/usr/bin/env python3 #!/usr/bin/env python3
from jinja2 import Template from jinja2 import Template
import argparse
import os import os
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--delete', action='store_true')
args = parser.parse_args()
if args.delete:
directory = os.path.dirname(os.path.realpath(__file__))
test_directory = os.path.join(directory, 'test')
for f in os.listdir(directory):
if 'tdd' in f:
os.remove(os.path.join(directory, f))
for f in os.listdir(test_directory):
if 'testTDD' in f:
os.remove(os.path.join(test_directory, f))
exit()
global_context = { global_context = {
'generated_file_message': "This file was generated using a jinja2 template and the render-templates script, don't modify directly." 'generated_file_message': "This file was generated using a jinja2 template and the render-templates script, don't modify directly."
} }
......
...@@ -7,6 +7,8 @@ extends = ...@@ -7,6 +7,8 @@ extends =
../../component/nghttp2/buildout.cfg ../../component/nghttp2/buildout.cfg
../../component/iperf3/buildout.cfg ../../component/iperf3/buildout.cfg
../../component/python3/buildout.cfg ../../component/python3/buildout.cfg
../../component/python-pynacl/buildout.cfg
../../component/bcrypt/buildout.cfg
parts += parts +=
template template
...@@ -27,7 +29,6 @@ parts += ...@@ -27,7 +29,6 @@ parts +=
# apache-php # apache-php
# logrotate # logrotate
[template] [template]
recipe = slapos.recipe.template recipe = slapos.recipe.template
url = ${:_profile_base_location_}/${:filename} url = ${:_profile_base_location_}/${:filename}
...@@ -40,6 +41,12 @@ url = ${:_profile_base_location_}/${:_update_hash_filename_} ...@@ -40,6 +41,12 @@ url = ${:_profile_base_location_}/${:_update_hash_filename_}
[amarisoft-stats.jinja2.py] [amarisoft-stats.jinja2.py]
<= download-base <= download-base
[amarisoft-rf-info.jinja2.py]
<= download-base
[lopcomm-rrh-stats.jinja2.py]
<= download-base
[template-lte-enb-epc] [template-lte-enb-epc]
<= download-base <= download-base
...@@ -64,21 +71,6 @@ url = ${:_profile_base_location_}/${:_update_hash_filename_} ...@@ -64,21 +71,6 @@ url = ${:_profile_base_location_}/${:_update_hash_filename_}
[template-lte-ue-nr] [template-lte-ue-nr]
<= download-base <= download-base
[sdr-busy-promise]
<= download-base
[cell-gain-saturated-promise]
<= download-base
[rx-saturated-promise]
<= download-base
[baseband-latency-promise]
<= download-base
[amarisoft-stats-log-promise]
<= download-base
[cpu-temperature-promise]
<= download-base
[interface-up-promise]
<= download-base
[copy-to-instance] [copy-to-instance]
recipe = slapos.recipe.build:download recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:_buildout_section_name_} url = ${:_profile_base_location_}/${:_buildout_section_name_}
...@@ -119,7 +111,13 @@ filename = ue-nr.jinja2.cfg ...@@ -119,7 +111,13 @@ filename = ue-nr.jinja2.cfg
recipe = zc.recipe.egg recipe = zc.recipe.egg
eggs = eggs =
websocket-client websocket-client
${python-pynacl:egg}
${bcrypt:egg}
xmltodict
ncclient
interpreter = pythonwitheggs interpreter = pythonwitheggs
[versions] [versions]
websocket-client = 1.4.2 websocket-client = 1.4.2
ncclient = 0.6.13
xmltodict = 0.13.0
...@@ -66,6 +66,7 @@ param_dict = { ...@@ -66,6 +66,7 @@ param_dict = {
'n_antenna_ul': 2, 'n_antenna_ul': 2,
'inactivity_timer': 17, 'inactivity_timer': 17,
'gnb_id': "0x17", 'gnb_id': "0x17",
'gnb_id_bits': 30,
'ssb_pos_bitmap': "10", 'ssb_pos_bitmap': "10",
'amf_list': { 'amf_list': {
'10.0.0.1': {'amf_addr': '10.0.0.1'}, '10.0.0.1': {'amf_addr': '10.0.0.1'},
...@@ -133,6 +134,7 @@ def test_gnb_conf1(self): ...@@ -133,6 +134,7 @@ def test_gnb_conf1(self):
self.assertEqual(conf['nr_cell_list'][0]['ssb_pos_bitmap'], gnb_param_dict1['ssb_pos_bitmap']) self.assertEqual(conf['nr_cell_list'][0]['ssb_pos_bitmap'], gnb_param_dict1['ssb_pos_bitmap'])
self.assertEqual(conf['nr_cell_default']['n_id_cell'], gnb_param_dict1['pci']) self.assertEqual(conf['nr_cell_default']['n_id_cell'], gnb_param_dict1['pci'])
self.assertEqual(conf['gnb_id'], int(gnb_param_dict1['gnb_id'], 16)) self.assertEqual(conf['gnb_id'], int(gnb_param_dict1['gnb_id'], 16))
self.assertEqual(conf['gnb_id_bits'], gnb_param_dict1['gnb_id_bits'])
for p in conf['nr_cell_default']['plmn_list']: for p in conf['nr_cell_default']['plmn_list']:
for n in "plmn ranac reserved tac".split(): for n in "plmn ranac reserved tac".split():
self.assertEqual(p[n], gnb_param_dict1['plmn_list'][p['plmn']][n]) self.assertEqual(p[n], gnb_param_dict1['plmn_list'][p['plmn']][n])
......
...@@ -66,6 +66,7 @@ param_dict = { ...@@ -66,6 +66,7 @@ param_dict = {
'n_antenna_ul': 2, 'n_antenna_ul': 2,
'inactivity_timer': 17, 'inactivity_timer': 17,
'gnb_id': "0x17", 'gnb_id': "0x17",
'gnb_id_bits': 30,
'ssb_pos_bitmap': "10", 'ssb_pos_bitmap': "10",
'amf_list': { 'amf_list': {
'10.0.0.1': {'amf_addr': '10.0.0.1'}, '10.0.0.1': {'amf_addr': '10.0.0.1'},
...@@ -133,6 +134,7 @@ def test_gnb_conf1(self): ...@@ -133,6 +134,7 @@ def test_gnb_conf1(self):
self.assertEqual(conf['nr_cell_list'][0]['ssb_pos_bitmap'], gnb_param_dict1['ssb_pos_bitmap']) self.assertEqual(conf['nr_cell_list'][0]['ssb_pos_bitmap'], gnb_param_dict1['ssb_pos_bitmap'])
self.assertEqual(conf['nr_cell_default']['n_id_cell'], gnb_param_dict1['pci']) self.assertEqual(conf['nr_cell_default']['n_id_cell'], gnb_param_dict1['pci'])
self.assertEqual(conf['gnb_id'], int(gnb_param_dict1['gnb_id'], 16)) self.assertEqual(conf['gnb_id'], int(gnb_param_dict1['gnb_id'], 16))
self.assertEqual(conf['gnb_id_bits'], gnb_param_dict1['gnb_id_bits'])
for p in conf['nr_cell_default']['plmn_list']: for p in conf['nr_cell_default']['plmn_list']:
for n in "plmn ranac reserved tac".split(): for n in "plmn ranac reserved tac".split():
self.assertEqual(p[n], gnb_param_dict1['plmn_list'][p['plmn']][n]) self.assertEqual(p[n], gnb_param_dict1['plmn_list'][p['plmn']][n])
......
...@@ -66,6 +66,7 @@ param_dict = { ...@@ -66,6 +66,7 @@ param_dict = {
'n_antenna_ul': 2, 'n_antenna_ul': 2,
'inactivity_timer': 17, 'inactivity_timer': 17,
'gnb_id': "0x17", 'gnb_id': "0x17",
'gnb_id_bits': 30,
'ssb_pos_bitmap': "10", 'ssb_pos_bitmap': "10",
'amf_list': { 'amf_list': {
'10.0.0.1': {'amf_addr': '10.0.0.1'}, '10.0.0.1': {'amf_addr': '10.0.0.1'},
...@@ -133,6 +134,7 @@ def test_gnb_conf1(self): ...@@ -133,6 +134,7 @@ def test_gnb_conf1(self):
self.assertEqual(conf['nr_cell_list'][0]['ssb_pos_bitmap'], gnb_param_dict1['ssb_pos_bitmap']) self.assertEqual(conf['nr_cell_list'][0]['ssb_pos_bitmap'], gnb_param_dict1['ssb_pos_bitmap'])
self.assertEqual(conf['nr_cell_default']['n_id_cell'], gnb_param_dict1['pci']) self.assertEqual(conf['nr_cell_default']['n_id_cell'], gnb_param_dict1['pci'])
self.assertEqual(conf['gnb_id'], int(gnb_param_dict1['gnb_id'], 16)) self.assertEqual(conf['gnb_id'], int(gnb_param_dict1['gnb_id'], 16))
self.assertEqual(conf['gnb_id_bits'], gnb_param_dict1['gnb_id_bits'])
for p in conf['nr_cell_default']['plmn_list']: for p in conf['nr_cell_default']['plmn_list']:
for n in "plmn ranac reserved tac".split(): for n in "plmn ranac reserved tac".split():
self.assertEqual(p[n], gnb_param_dict1['plmn_list'][p['plmn']][n]) self.assertEqual(p[n], gnb_param_dict1['plmn_list'][p['plmn']][n])
......
...@@ -66,6 +66,7 @@ param_dict = { ...@@ -66,6 +66,7 @@ param_dict = {
'n_antenna_ul': 2, 'n_antenna_ul': 2,
'inactivity_timer': 17, 'inactivity_timer': 17,
'gnb_id': "0x17", 'gnb_id': "0x17",
'gnb_id_bits': 30,
'ssb_pos_bitmap': "10", 'ssb_pos_bitmap': "10",
'amf_list': { 'amf_list': {
'10.0.0.1': {'amf_addr': '10.0.0.1'}, '10.0.0.1': {'amf_addr': '10.0.0.1'},
...@@ -133,6 +134,7 @@ def test_gnb_conf1(self): ...@@ -133,6 +134,7 @@ def test_gnb_conf1(self):
self.assertEqual(conf['nr_cell_list'][0]['ssb_pos_bitmap'], gnb_param_dict1['ssb_pos_bitmap']) self.assertEqual(conf['nr_cell_list'][0]['ssb_pos_bitmap'], gnb_param_dict1['ssb_pos_bitmap'])
self.assertEqual(conf['nr_cell_default']['n_id_cell'], gnb_param_dict1['pci']) self.assertEqual(conf['nr_cell_default']['n_id_cell'], gnb_param_dict1['pci'])
self.assertEqual(conf['gnb_id'], int(gnb_param_dict1['gnb_id'], 16)) self.assertEqual(conf['gnb_id'], int(gnb_param_dict1['gnb_id'], 16))
self.assertEqual(conf['gnb_id_bits'], gnb_param_dict1['gnb_id_bits'])
for p in conf['nr_cell_default']['plmn_list']: for p in conf['nr_cell_default']['plmn_list']:
for n in "plmn ranac reserved tac".split(): for n in "plmn ranac reserved tac".split():
self.assertEqual(p[n], gnb_param_dict1['plmn_list'][p['plmn']][n]) self.assertEqual(p[n], gnb_param_dict1['plmn_list'][p['plmn']][n])
......
...@@ -66,6 +66,7 @@ param_dict = { ...@@ -66,6 +66,7 @@ param_dict = {
'n_antenna_ul': 2, 'n_antenna_ul': 2,
'inactivity_timer': 17, 'inactivity_timer': 17,
'gnb_id': "0x17", 'gnb_id': "0x17",
'gnb_id_bits': 30,
'ssb_pos_bitmap': "10", 'ssb_pos_bitmap': "10",
'amf_list': { 'amf_list': {
'10.0.0.1': {'amf_addr': '10.0.0.1'}, '10.0.0.1': {'amf_addr': '10.0.0.1'},
...@@ -133,6 +134,7 @@ def test_gnb_conf1(self): ...@@ -133,6 +134,7 @@ def test_gnb_conf1(self):
self.assertEqual(conf['nr_cell_list'][0]['ssb_pos_bitmap'], gnb_param_dict1['ssb_pos_bitmap']) self.assertEqual(conf['nr_cell_list'][0]['ssb_pos_bitmap'], gnb_param_dict1['ssb_pos_bitmap'])
self.assertEqual(conf['nr_cell_default']['n_id_cell'], gnb_param_dict1['pci']) self.assertEqual(conf['nr_cell_default']['n_id_cell'], gnb_param_dict1['pci'])
self.assertEqual(conf['gnb_id'], int(gnb_param_dict1['gnb_id'], 16)) self.assertEqual(conf['gnb_id'], int(gnb_param_dict1['gnb_id'], 16))
self.assertEqual(conf['gnb_id_bits'], gnb_param_dict1['gnb_id_bits'])
for p in conf['nr_cell_default']['plmn_list']: for p in conf['nr_cell_default']['plmn_list']:
for n in "plmn ranac reserved tac".split(): for n in "plmn ranac reserved tac".split():
self.assertEqual(p[n], gnb_param_dict1['plmn_list'][p['plmn']][n]) self.assertEqual(p[n], gnb_param_dict1['plmn_list'][p['plmn']][n])
......
...@@ -302,7 +302,7 @@ slapos.rebootstrap = 4.5 ...@@ -302,7 +302,7 @@ slapos.rebootstrap = 4.5
slapos.recipe.build = 0.56 slapos.recipe.build = 0.56
slapos.recipe.cmmi = 0.19 slapos.recipe.cmmi = 0.19
slapos.recipe.template = 5.1 slapos.recipe.template = 5.1
slapos.toolbox = 0.129 slapos.toolbox = 0.130
smmap = 5.0.0 smmap = 5.0.0
sniffio = 1.3.0 sniffio = 1.3.0
sortedcontainers = 2.4.0 sortedcontainers = 2.4.0
......
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