Commit 4968d55c authored by Joanne Hugé's avatar Joanne Hugé

ors-amarisoft: get eNB stats and add promises

parent 5c411cb7
#!{{ 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 }}:
from random import randint
r = {
'message': 'stats',
'samples': {'rx': [
{'sat': 0, 'max': randint(-500,-100) / 10.0},
{'sat': 0, 'max': randint(-500,-100) / 10.0},
]}
}
else:
self.send({
"message": "stats",
"samples": True,
"rf": True
})
r = self.recv('stats')
self.logger.info('Samples stats', extra={'data': r})
if __name__ == '__main__':
ws = enbWebSocket()
try:
while True:
ws.stats()
time.sleep({{ stats_period }})
finally:
ws.close()
...@@ -16,27 +16,31 @@ ...@@ -16,27 +16,31 @@
[template] [template]
filename = instance.cfg filename = instance.cfg
md5sum = 6e5c63c35b13f8920ea13e24c27d7b50 md5sum = 8a6e6e065e3eeffc3d5d4d8bb68f4a43
[amarisoft-stats.jinja2.py]
_update_hash_filename_ = amarisoft-stats.jinja2.py
md5sum = 6e0a052bd0ca08cc0c7b4880d3deffcc
[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 = 42959a0525d2e06e61310836656d5de6 md5sum = f15c81f0f4c2aa59bc794d855e7d01c0
[template-lte-enb] [template-lte-enb]
_update_hash_filename_ = instance-enb.jinja2.cfg _update_hash_filename_ = instance-enb.jinja2.cfg
md5sum = 04dbc8396cb112e86d5d1564df033b82 md5sum = 68362f58fccc534757b6bb566d285fa6
[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 = 2b589e23486661c52f379c4d9b35e7a9 md5sum = dd98a2d0cb4fadc869638166bde6d9c8
[template-lte-epc] [template-lte-epc]
_update_hash_filename_ = instance-epc.jinja2.cfg _update_hash_filename_ = instance-epc.jinja2.cfg
md5sum = 9ffc54bf10757403c4b1809d1102ea52 md5sum = 48755eb0b2eb87f80130d42026ea8f7b
[template-lte-gnb] [template-lte-gnb]
_update_hash_filename_ = instance-gnb.jinja2.cfg _update_hash_filename_ = instance-gnb.jinja2.cfg
md5sum = 01f4de736594a0810a66f847753fadf1 md5sum = 45ff1f5f4e98867449dcff7caae678f8
[template-lte-mme] [template-lte-mme]
_update_hash_filename_ = instance-mme.jinja2.cfg _update_hash_filename_ = instance-mme.jinja2.cfg
...@@ -44,11 +48,11 @@ md5sum = 728f4d3ae248710c23e4b73eea4d628e ...@@ -44,11 +48,11 @@ md5sum = 728f4d3ae248710c23e4b73eea4d628e
[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 = 4517baee6700afbf78de3b2d7dd4ba22 md5sum = 38ef57bc93f53338187bd9c39fe4f0c5
[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 = 45e7ade19a579d6750d2733a0659dc1a md5sum = eaaf8fb3806a941f188eecdb90d38bda
[ue_db.jinja2.cfg] [ue_db.jinja2.cfg]
filename = config/ue_db.jinja2.cfg filename = config/ue_db.jinja2.cfg
...@@ -56,7 +60,7 @@ md5sum = dcaac06553a3222b14c0013a13f4a149 ...@@ -56,7 +60,7 @@ md5sum = dcaac06553a3222b14c0013a13f4a149
[enb.jinja2.cfg] [enb.jinja2.cfg]
filename = config/enb.jinja2.cfg filename = config/enb.jinja2.cfg
md5sum = 9fd6abb1e69fe59af0dafbb336f24f8d md5sum = 1c9909f691b5bb00d3fc30d41613e26a
[sib23.asn] [sib23.asn]
filename = config/sib23.asn filename = config/sib23.asn
...@@ -64,7 +68,7 @@ md5sum = b377dac7f1fcf94fb9ce9ebed617f36a ...@@ -64,7 +68,7 @@ md5sum = b377dac7f1fcf94fb9ce9ebed617f36a
[gnb.jinja2.cfg] [gnb.jinja2.cfg]
filename = config/gnb.jinja2.cfg filename = config/gnb.jinja2.cfg
md5sum = 407c20d11c5417636b985fe4886bf135 md5sum = 16698f0b4ea3e6cf40e9f070af2439e5
[ltelogs.jinja2.sh] [ltelogs.jinja2.sh]
filename = ltelogs.jinja2.sh filename = ltelogs.jinja2.sh
...@@ -88,8 +92,24 @@ md5sum = b3078deab008d7e81ddd88ac02b8b698 ...@@ -88,8 +92,24 @@ md5sum = b3078deab008d7e81ddd88ac02b8b698
[sdr-busy-promise] [sdr-busy-promise]
_update_hash_filename_ = promise/check_sdr_busy.py _update_hash_filename_ = promise/check_sdr_busy.py
md5sum = 2e25144d1d952ed5bebb194360b60afb 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
[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 = 8e8f836554d81e2979e39dfb50e05b88
[interface-up-promise] [interface-up-promise]
_update_hash_filename_ = promise/check_interface_up.py _update_hash_filename_ = promise/check_interface_up.py
md5sum = 7797aeaf02e055226249f2c08209775a md5sum = 44ae5693f62b7a4dbc98f700f68d8600
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,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']) }},
com_addr: "127.0.1.2:9001",
mme_list: [ mme_list: [
{% if slapparameter_dict.get('mme_list', '') %} {% if slapparameter_dict.get('mme_list', '') %}
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
tx_gain: {{ slapparameter_dict.get('tx_gain', slap_configuration['configuration.default_nr_tx_gain']) }}, tx_gain: {{ slapparameter_dict.get('tx_gain', slap_configuration['configuration.default_nr_tx_gain']) }},
rx_gain: {{ slapparameter_dict.get('rx_gain', slap_configuration['configuration.default_nr_rx_gain']) }}, rx_gain: {{ slapparameter_dict.get('rx_gain', slap_configuration['configuration.default_nr_rx_gain']) }},
{% endif %} {% endif %}
com_addr: "127.0.1.2:9001",
amf_list: [ amf_list: [
{% if slapparameter_dict.get('amf_list', '') %} {% if slapparameter_dict.get('amf_list', '') %}
......
...@@ -14,6 +14,7 @@ parts = ...@@ -14,6 +14,7 @@ parts =
directory directory
lte-enb-request lte-enb-request
lte-mme-request lte-mme-request
cpu-temperature-promise
publish-connection-information publish-connection-information
{% for part in part_list -%} {% for part in part_list -%}
{{ ' %s' % part }} {{ ' %s' % part }}
...@@ -59,6 +60,7 @@ cert-file = {{ slap_connection['cert-file'] }} ...@@ -59,6 +60,7 @@ cert-file = {{ slap_connection['cert-file'] }}
sla-computer_guid = {{ slap_connection['computer-id'] }} sla-computer_guid = {{ slap_connection['computer-id'] }}
config-monitor-password = ${monitor-htpasswd:passwd} config-monitor-password = ${monitor-htpasswd:passwd}
config-sub-instance = true
[lte-mme-request] [lte-mme-request]
<= request-common-base <= request-common-base
...@@ -85,6 +87,14 @@ return = monitor-base-url ...@@ -85,6 +87,14 @@ 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]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 80) }}
[publish-connection-information] [publish-connection-information]
recipe = slapos.cookbook:publish.serialised recipe = slapos.cookbook:publish.serialised
<= monitor-publish <= monitor-publish
......
...@@ -119,6 +119,24 @@ ...@@ -119,6 +119,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -4,7 +4,14 @@ parts = ...@@ -4,7 +4,14 @@ parts =
ltelogs ltelogs
lte-enb-config lte-enb-config
lte-enb-service lte-enb-service
amarisoft-stats-service
sdr-busy-promise sdr-busy-promise
cell-gain-saturated-promise
rx-saturated-promise
amarisoft-stats-log-promise
{% if not slapparameter_dict.get("sub-instance", False) %}
cpu-temperature-promise
{% endif %}
monitor-base monitor-base
publish-connection-information publish-connection-information
...@@ -97,6 +104,30 @@ environment = ...@@ -97,6 +104,30 @@ environment =
LD_LIBRARY_PATH={{ openssl_location }}/lib LD_LIBRARY_PATH={{ openssl_location }}/lib
AMARISOFT_PATH=/opt/amarisoft/.amarisoft AMARISOFT_PATH=/opt/amarisoft/.amarisoft
[amarisoft-stats-template]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
log-output = ${directory:var}/log/amarisoft-stats.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_stats_template }}
output = ${directory:bin}/amarisoft-stats.py
### eNodeB (enb)
[amarisoft-stats-service]
recipe = slapos.cookbook:wrapper
command-line = ${amarisoft-stats-template:output}
wrapper-path = ${directory:service}/amarisoft-stats
mode = 0775
hash-files =
${amarisoft-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
...@@ -130,7 +161,6 @@ monitor-title = {{ slapparameter_dict['name'] | string }} ...@@ -130,7 +161,6 @@ 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
[sdr-busy-promise] [sdr-busy-promise]
recipe = slapos.cookbook:promise.plugin recipe = slapos.cookbook:promise.plugin
eggs = slapos.core eggs = slapos.core
...@@ -138,3 +168,44 @@ file = {{ sdr_busy_promise }} ...@@ -138,3 +168,44 @@ file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py output = ${directory:plugins}/check-sdr-busy.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }} config-sdr = {{ sdr }}
[cell-gain-saturated-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
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-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[rx-saturated-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ rx_saturated_promise }}
output = ${directory:plugins}/check-rx-saturated.py
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) }}
[amarisoft-stats-log-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
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) }}
[cpu-temperature-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-maxtemp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 80) }}
...@@ -26,6 +26,12 @@ ...@@ -26,6 +26,12 @@
"title": "Use IPv4", "title": "Use IPv4",
"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"
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -13,6 +13,9 @@ info = Your SIM card has been attached to service ${slap-configuration:instance- ...@@ -13,6 +13,9 @@ 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) %}
cpu-temperature-promise
{% endif %}
publish-connection-information publish-connection-information
{% for part in part_list -%} {% for part in part_list -%}
{{ ' %s' % part }} {{ ' %s' % part }}
...@@ -73,6 +76,14 @@ config-slave-list = {{ dumps(slave_instance_list) }} ...@@ -73,6 +76,14 @@ 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]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 80) }}
[publish-connection-information] [publish-connection-information]
recipe = slapos.cookbook:publish.serialised recipe = slapos.cookbook:publish.serialised
<= monitor-publish <= monitor-publish
......
...@@ -14,6 +14,7 @@ parts = ...@@ -14,6 +14,7 @@ parts =
directory directory
lte-gnb-request lte-gnb-request
lte-mme-request lte-mme-request
cpu-temperature-promise
publish-connection-information publish-connection-information
{% for part in part_list -%} {% for part in part_list -%}
{{ ' %s' % part }} {{ ' %s' % part }}
...@@ -59,6 +60,7 @@ cert-file = {{ slap_connection['cert-file'] }} ...@@ -59,6 +60,7 @@ cert-file = {{ slap_connection['cert-file'] }}
sla-computer_guid = {{ slap_connection['computer-id'] }} sla-computer_guid = {{ slap_connection['computer-id'] }}
config-monitor-password = ${monitor-htpasswd:passwd} config-monitor-password = ${monitor-htpasswd:passwd}
config-sub-instance = true
[lte-mme-request] [lte-mme-request]
<= request-common-base <= request-common-base
...@@ -85,6 +87,14 @@ return = monitor-base-url ...@@ -85,6 +87,14 @@ 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]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 80) }}
[publish-connection-information] [publish-connection-information]
recipe = slapos.cookbook:publish.serialised recipe = slapos.cookbook:publish.serialised
<= monitor-publish <= monitor-publish
......
...@@ -171,6 +171,24 @@ ...@@ -171,6 +171,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -4,7 +4,14 @@ parts = ...@@ -4,7 +4,14 @@ parts =
ltelogs ltelogs
lte-gnb-config lte-gnb-config
lte-enb-service lte-enb-service
amarisoft-stats-service
sdr-busy-promise sdr-busy-promise
cell-gain-saturated-promise
rx-saturated-promise
amarisoft-stats-log-promise
{% if not slapparameter_dict.get("sub-instance", False) %}
cpu-temperature-promise
{% endif %}
monitor-base monitor-base
publish-connection-information publish-connection-information
...@@ -98,6 +105,30 @@ environment = ...@@ -98,6 +105,30 @@ environment =
LD_LIBRARY_PATH={{ openssl_location }}/lib LD_LIBRARY_PATH={{ openssl_location }}/lib
AMARISOFT_PATH=/opt/amarisoft/.amarisoft AMARISOFT_PATH=/opt/amarisoft/.amarisoft
[amarisoft-stats-template]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
log-output = ${directory:var}/log/amarisoft-stats.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_stats_template }}
output = ${directory:bin}/amarisoft-stats.py
### eNodeB (enb)
[amarisoft-stats-service]
recipe = slapos.cookbook:wrapper
command-line = ${amarisoft-stats-template:output}
wrapper-path = ${directory:service}/amarisoft-stats
mode = 0775
hash-files =
${amarisoft-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
...@@ -130,7 +161,6 @@ monitor-title = {{ slapparameter_dict['name'] | string }} ...@@ -130,7 +161,6 @@ 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
[sdr-busy-promise] [sdr-busy-promise]
recipe = slapos.cookbook:promise.plugin recipe = slapos.cookbook:promise.plugin
eggs = slapos.core eggs = slapos.core
...@@ -138,3 +168,44 @@ file = {{ sdr_busy_promise }} ...@@ -138,3 +168,44 @@ file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py output = ${directory:plugins}/check-sdr-busy.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }} config-sdr = {{ sdr }}
[cell-gain-saturated-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
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-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[rx-saturated-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ rx_saturated_promise }}
output = ${directory:plugins}/check-rx-saturated.py
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) }}
[amarisoft-stats-log-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
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) }}
[cpu-temperature-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 80) }}
...@@ -117,6 +117,24 @@ ...@@ -117,6 +117,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -99,6 +99,24 @@ ...@@ -99,6 +99,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -169,6 +169,24 @@ ...@@ -169,6 +169,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -151,6 +151,24 @@ ...@@ -151,6 +151,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -117,6 +117,24 @@ ...@@ -117,6 +117,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -99,6 +99,24 @@ ...@@ -99,6 +99,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -169,6 +169,24 @@ ...@@ -169,6 +169,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -151,6 +151,24 @@ ...@@ -151,6 +151,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -117,6 +117,24 @@ ...@@ -117,6 +117,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -99,6 +99,24 @@ ...@@ -99,6 +99,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -169,6 +169,24 @@ ...@@ -169,6 +169,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -151,6 +151,24 @@ ...@@ -151,6 +151,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -117,6 +117,24 @@ ...@@ -117,6 +117,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -99,6 +99,24 @@ ...@@ -99,6 +99,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -169,6 +169,24 @@ ...@@ -169,6 +169,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -151,6 +151,24 @@ ...@@ -151,6 +151,24 @@
"title": "Use IPv4", "title": "Use IPv4",
"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": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
} }
} }
} }
...@@ -5,6 +5,7 @@ parts = ...@@ -5,6 +5,7 @@ parts =
lte-ue-lte-config lte-ue-lte-config
lte-ue-service lte-ue-service
sdr-busy-promise sdr-busy-promise
cpu-temperature-promise
monitor-base monitor-base
publish-connection-information publish-connection-information
...@@ -128,3 +129,11 @@ file = {{ sdr_busy_promise }} ...@@ -128,3 +129,11 @@ file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py output = ${directory:plugins}/check-sdr-busy.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }} config-sdr = {{ sdr }}
[cpu-temperature-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-maxtemp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 80) }}
...@@ -5,6 +5,7 @@ parts = ...@@ -5,6 +5,7 @@ parts =
lte-ue-nr-config lte-ue-nr-config
lte-ue-service lte-ue-service
sdr-busy-promise sdr-busy-promise
cpu-temperature-promise
monitor-base monitor-base
publish-connection-information publish-connection-information
...@@ -131,3 +132,11 @@ file = {{ sdr_busy_promise }} ...@@ -131,3 +132,11 @@ file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py output = ${directory:plugins}/check-sdr-busy.py
config-testing = {{ slapparameter_dict.get("testing", False) }} config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }} config-sdr = {{ sdr }}
[cpu-temperature-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-maxtemp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 80) }}
...@@ -75,6 +75,7 @@ extensions = jinja2.ext.do ...@@ -75,6 +75,7 @@ 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
...@@ -84,6 +85,7 @@ extensions = jinja2.ext.do ...@@ -84,6 +85,7 @@ 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
...@@ -93,6 +95,7 @@ extensions = jinja2.ext.do ...@@ -93,6 +95,7 @@ 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
...@@ -106,7 +109,12 @@ extra-context = ...@@ -106,7 +109,12 @@ extra-context =
raw enb_template ${enb.jinja2.cfg:target} raw enb_template ${enb.jinja2.cfg:target}
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 sdr_busy_promise ${sdr-busy-promise:target} raw sdr_busy_promise ${sdr-busy-promise:target}
raw cell_gain_saturated_promise ${cell-gain-saturated-promise:target}
raw rx_saturated_promise ${rx-saturated-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}
...@@ -129,7 +137,12 @@ extra-context = ...@@ -129,7 +137,12 @@ extra-context =
key sdr amarisoft:sdr key sdr amarisoft:sdr
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 sdr_busy_promise ${sdr-busy-promise:target} raw sdr_busy_promise ${sdr-busy-promise:target}
raw cell_gain_saturated_promise ${cell-gain-saturated-promise:target}
raw rx_saturated_promise ${rx-saturated-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}
...@@ -141,6 +154,7 @@ extra-context = ...@@ -141,6 +154,7 @@ extra-context =
raw default_nr_inactivity_timer ${default-params:default-nr-inactivity-timer} raw default_nr_inactivity_timer ${default-params:default-nr-inactivity-timer}
raw min_frequency ${default-params:min-frequency} raw min_frequency ${default-params:min-frequency}
raw max_frequency ${default-params:max-frequency} raw max_frequency ${default-params:max-frequency}
raw python_path ${python3:location}
[dynamic-template-lte-mme] [dynamic-template-lte-mme]
< = jinja2-template-base < = jinja2-template-base
...@@ -172,6 +186,7 @@ extra-context = ...@@ -172,6 +186,7 @@ extra-context =
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 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}
...@@ -194,6 +209,7 @@ extra-context = ...@@ -194,6 +209,7 @@ extra-context =
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 sdr_busy_promise ${sdr-busy-promise:target}
raw openssl_location ${openssl:location} raw openssl_location ${openssl:location}
......
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 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 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):
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 = int(self.getConfig('max-temp', 80))
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]
data = json.dumps({'cpu_temperature': cpu_temp})
if cpu_temp > max_temp:
self.logger.error("Temperature too high (%s > %s)" % (cpu_temp, max_temp))
self.json_logger.info("Temperature too high (%s > %s)" % (cpu_temp, max_temp), extra={'data': data})
else:
self.logger.info("Temperature OK")
self.json_logger.info("Temperature OK", extra={'data': data})
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)
...@@ -5,28 +5,17 @@ from zope.interface import implementer ...@@ -5,28 +5,17 @@ from zope.interface import implementer
from slapos.grid.promise import interface from slapos.grid.promise import interface
from slapos.grid.promise.generic import GenericPromise from slapos.grid.promise.generic import GenericPromise
@implementer(interface.IPromise) @implementer(interface.IPromise)
class RunPromise(GenericPromise): class RunPromise(GenericPromise):
def __init__(self, config): def __init__(self, config):
"""
Called when initialising the promise before testing.
Sets the configuration and the periodicity.
"""
super(RunPromise, self).__init__(config) super(RunPromise, self).__init__(config)
self.setPeriodicity(minute=2) self.setPeriodicity(minute=2)
def sense(self): def sense(self):
"""
Called every time the promise is tested.
Signals a positive or negative result.
In this case, check whether the file exists.
"""
ifname = self.getConfig('ifname') ifname = self.getConfig('ifname')
testing = self.getConfig('testing') == "True" testing = self.getConfig('testing') == "True"
......
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)
...@@ -6,28 +6,17 @@ from zope.interface import implementer ...@@ -6,28 +6,17 @@ from zope.interface import implementer
from slapos.grid.promise import interface from slapos.grid.promise import interface
from slapos.grid.promise.generic import GenericPromise from slapos.grid.promise.generic import GenericPromise
@implementer(interface.IPromise) @implementer(interface.IPromise)
class RunPromise(GenericPromise): class RunPromise(GenericPromise):
def __init__(self, config): def __init__(self, config):
"""
Called when initialising the promise before testing.
Sets the configuration and the periodicity.
"""
super(RunPromise, self).__init__(config) super(RunPromise, self).__init__(config)
self.setPeriodicity(minute=1) self.setPeriodicity(minute=1)
def sense(self): def sense(self):
"""
Called every time the promise is tested.
Signals a positive or negative result.
In this case, check whether the file exists.
"""
testing = self.getConfig('testing') == "True" testing = self.getConfig('testing') == "True"
sdr = self.getConfig('sdr') sdr = self.getConfig('sdr')
......
...@@ -6,6 +6,7 @@ extends = ...@@ -6,6 +6,7 @@ extends =
../../component/logrotate/buildout.cfg ../../component/logrotate/buildout.cfg
../../component/nghttp2/buildout.cfg ../../component/nghttp2/buildout.cfg
../../component/iperf3/buildout.cfg ../../component/iperf3/buildout.cfg
../../component/python3/buildout.cfg
parts += parts +=
template template
...@@ -21,6 +22,7 @@ parts += ...@@ -21,6 +22,7 @@ parts +=
ue-nr.jinja2.cfg ue-nr.jinja2.cfg
sib23.asn sib23.asn
iperf3 iperf3
eggs
# unimplemented parts - the http monitor and better log handling using logrotate # unimplemented parts - the http monitor and better log handling using logrotate
# apache-php # apache-php
# logrotate # logrotate
...@@ -35,6 +37,9 @@ output = ${buildout:directory}/template.cfg ...@@ -35,6 +37,9 @@ output = ${buildout:directory}/template.cfg
recipe = slapos.recipe.build:download recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:_update_hash_filename_} url = ${:_profile_base_location_}/${:_update_hash_filename_}
[amarisoft-stats.jinja2.py]
<= download-base
[template-lte-enb-epc] [template-lte-enb-epc]
<= download-base <= download-base
...@@ -61,7 +66,14 @@ url = ${:_profile_base_location_}/${:_update_hash_filename_} ...@@ -61,7 +66,14 @@ url = ${:_profile_base_location_}/${:_update_hash_filename_}
[sdr-busy-promise] [sdr-busy-promise]
<= download-base <= download-base
[cell-gain-saturated-promise]
<= download-base
[rx-saturated-promise]
<= download-base
[amarisoft-stats-log-promise]
<= download-base
[cpu-temperature-promise]
<= download-base
[interface-up-promise] [interface-up-promise]
<= download-base <= download-base
...@@ -100,3 +112,13 @@ filename = ue-lte.jinja2.cfg ...@@ -100,3 +112,13 @@ filename = ue-lte.jinja2.cfg
[ue-nr.jinja2.cfg] [ue-nr.jinja2.cfg]
<= copy-config-to-instance <= copy-config-to-instance
filename = ue-nr.jinja2.cfg filename = ue-nr.jinja2.cfg
[eggs]
recipe = zc.recipe.egg
eggs =
websocket-client
python-dateutil
interpreter = pythonwitheggs
[versions]
websocket-client = 1.4.2
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