Commit e0f418c8 authored by Joanne Hugé's avatar Joanne Hugé

software/ors-amarisoft: use promises from slapos.toolbox

parent a1984961
......@@ -16,7 +16,7 @@
[template]
filename = instance.cfg
md5sum = 270f738ca2ed4438868d97a0fb05269e
md5sum = d21dcca80b710df5ab459bd74edd0ac7
[amarisoft-stats.jinja2.py]
_update_hash_filename_ = amarisoft-stats.jinja2.py
......@@ -28,35 +28,35 @@ md5sum = 39e191080722ac13ebc56b1e6350eb8f
[template-lte-enb-epc]
_update_hash_filename_ = instance-enb-epc.jinja2.cfg
md5sum = 833667743c693b8d5f78a2527b275a9e
md5sum = bb4435f433e100fede09ff921d42c927
[template-lte-enb]
_update_hash_filename_ = instance-enb.jinja2.cfg
md5sum = acb7eccc4f44b7a1a1bcb8d1decb76a9
md5sum = 9ccb99150a220a40158bb079691c83b8
[template-lte-gnb-epc]
_update_hash_filename_ = instance-gnb-epc.jinja2.cfg
md5sum = 1f0b18cb6d70466d002b378bb931e7da
md5sum = 9a0e36188b23831bec3cb53b226baa66
[template-lte-epc]
_update_hash_filename_ = instance-epc.jinja2.cfg
md5sum = 99c05a34678adb5a70aa64ecf2ee4e35
md5sum = acc9176fd9abe1d04c60a08cdd520eee
[template-lte-gnb]
_update_hash_filename_ = instance-gnb.jinja2.cfg
md5sum = e067a332ab1d6375049b413d90b7fa08
md5sum = 1d161902801a6ac0c461dffdf78e98ac
[template-lte-mme]
_update_hash_filename_ = instance-mme.jinja2.cfg
md5sum = 9a26877e326bffd57e17320de0d12c6d
md5sum = 400accb9d5bc104b1b122a7b9bc3a261
[template-lte-ue-lte]
_update_hash_filename_ = instance-ue-lte.jinja2.cfg
md5sum = 691a6223e587b6abf1de279375217744
md5sum = 5c1f78588a0d7447807c10765552a6e7
[template-lte-ue-nr]
_update_hash_filename_ = instance-ue-nr.jinja2.cfg
md5sum = ebc9a8edd23b10c2618bd02d1de76007
md5sum = 5b032c3c9dbbd5b8552b0ebd8dcc9acf
[ue_db.jinja2.cfg]
filename = config/ue_db.jinja2.cfg
......@@ -93,31 +93,3 @@ md5sum = 31c166f0a1b6d664f92b8f318b233d9a
[ue-nr.jinja2.cfg]
filename = config/ue-nr.jinja2.cfg
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
......@@ -14,7 +14,7 @@ parts =
directory
lte-enb-request
lte-mme-request
cpu-temperature-promise
check-cpu-temperature.py
publish-connection-information
{% for part in part_list -%}
{{ ' %s' % part }}
......@@ -87,17 +87,19 @@ return = monitor-base-url
lte-mme-request = ${lte-mme-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
python-dateutil
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
[macro.promise]
<= monitor-promise-base
name = ${:_buildout_section_name_}
[check-cpu-temperature.py]
<= macro.promise
promise = check_cpu_temperature
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }}
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) }}
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
[publish-connection-information]
recipe = slapos.cookbook:publish.serialised
......
......@@ -154,20 +154,20 @@
"type": "number",
"default": 7
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"promise_cpu_max_spot_temp": {
"title": "Maximum CPU spot temperature",
"description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number",
"default": 90
},
"promise_cpu_avg_temperature_threshold": {
"title": "Average CPU temperature promise threshold",
"description": "If average temperature over specified duration reaches this threshold, promise will fail",
"promise_cpu_max_avg_temp": {
"title": "Maximum average CPU temperature",
"description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number",
"default": 80
},
"promise_cpu_avg_temperature_threshold_duration": {
"title": "Average CPU temperature promise threshold duration",
"promise_cpu_avg_temp_period": {
"title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold",
"type": "number",
"default": 600
......
......@@ -5,18 +5,16 @@ parts =
lte-enb-config
lte-enb-service
amarisoft-stats-service
sdr-busy-promise
cell-gain-saturated-promise
rx-saturated-promise
baseband-latency-promise
amarisoft-stats-log-promise
{% if slapparameter_dict.get('rrh', '') == "Lopcomm ORAN" %}
lopcomm-rrh-stats-service
vswr-promise
check-lopcomm-vswr.py
{% endif %}
{% if not slapparameter_dict.get("sub-instance", False) %}
cpu-temperature-promise
check-cpu-temperature.py
{% endif %}
check-sdr-busy.py
check-baseband-latency.py
check-amarisoft-stats-log.py
monitor-base
publish-connection-information
......@@ -99,7 +97,6 @@ inline =
{{ enb }}/lteenb ${directory:etc}/enb.cfg >> ${:enb-log} 2>> ${:enb-log};
{% endif %}
### eNodeB (enb)
[lte-enb-service]
recipe = slapos.cookbook:wrapper
init = ${ltelogs:output} ${directory:log}/enb.log; sleep 2
......@@ -195,78 +192,53 @@ monitor-title = {{ slapparameter_dict['name'] | string }}
password = {{ slapparameter_dict['monitor-password'] | string }}
{% endif %}
[sdr-busy-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py
[macro.promise]
<= monitor-promise-base
name = ${:_buildout_section_name_}
[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-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
[check-baseband-latency.py]
<= macro.promise
promise = check_baseband_latency
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-min-txrx-delay = {{ slapparameter_dict.get("min_txrx_delay", 5) }}
[rx-saturated-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ rx_saturated_promise }}
output = ${directory:plugins}/check-rx-saturated.py
[check-amarisoft-stats-log.py]
<= macro.promise
promise = check_amarisoft_stats_log
output = ${directory:plugins}/check-amarisoft-stats-log.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) }}
[baseband-latency-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ baseband_latency_promise }}
output = ${directory:plugins}/check-baseband-latency.py
[check-lopcomm-vswr.py]
<= macro.promise
promise = check_lopcomm_vswr
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-min-txrx-delay = {{ slapparameter_dict.get("min_txrx_delay", 5) }}
config-avg-txrx-delay = {{ slapparameter_dict.get("avg_txrx_delay", 7) }}
[vswr-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ vswr_promise }}
output = ${directory:plugins}/check-vswr.py
[check-rx-saturated.py]
<= macro.promise
promise = check_rx_saturated
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-lopcomm-stats-log = ${lopcomm-rrh-stats-template:json-log-output}
[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
python-dateutil
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", 90) }}
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) }}
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-
parts =
directory
lte-mme-request
{% if not slapparameter_dict.get("sub-instance", False) %}
cpu-temperature-promise
{% endif %}
check-cpu-temperature.py
publish-connection-information
{% for part in part_list -%}
{{ ' %s' % part }}
......@@ -76,17 +74,19 @@ config-slave-list = {{ dumps(slave_instance_list) }}
[monitor-base-url-dict]
lte-mme-request = ${lte-mme-request:connection-monitor-base-url}
[cpu-temperature-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
[macro.promise]
<= monitor-promise-base
name = ${:_buildout_section_name_}
[check-cpu-temperature.py]
<= macro.promise
promise = check_cpu_temperature
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }}
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) }}
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
[publish-connection-information]
recipe = slapos.cookbook:publish.serialised
......
......@@ -14,7 +14,7 @@ parts =
directory
lte-gnb-request
lte-mme-request
cpu-temperature-promise
check-cpu-temperature.py
publish-connection-information
{% for part in part_list -%}
{{ ' %s' % part }}
......@@ -87,17 +87,19 @@ return = monitor-base-url
lte-mme-request = ${lte-mme-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
python-dateutil
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
[macro.promise]
<= monitor-promise-base
name = ${:_buildout_section_name_}
[check-cpu-temperature.py]
<= macro.promise
promise = check_cpu_temperature
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }}
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) }}
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
[publish-connection-information]
recipe = slapos.cookbook:publish.serialised
......
......@@ -172,9 +172,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses",
"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",
"gnb_stats_fetch_period": {
"title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number",
"default": 60
},
......
......@@ -5,13 +5,16 @@ parts =
lte-gnb-config
lte-enb-service
amarisoft-stats-service
sdr-busy-promise
cell-gain-saturated-promise
rx-saturated-promise
amarisoft-stats-log-promise
{% if slapparameter_dict.get('rrh', '') == "Lopcomm ORAN" %}
lopcomm-rrh-stats-service
check-lopcomm-vswr.py
{% endif %}
{% if not slapparameter_dict.get("sub-instance", False) %}
cpu-temperature-promise
check-cpu-temperature.py
{% endif %}
check-sdr-busy.py
check-baseband-latency.py
check-amarisoft-stats-log.py
monitor-base
publish-connection-information
......@@ -93,6 +96,7 @@ inline =
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 %}
### eNodeB (enb)
......@@ -119,14 +123,13 @@ 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 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_stats_template }}
output = ${directory:bin}/amarisoft-stats.py
### eNodeB (enb)
[amarisoft-stats-service]
recipe = slapos.cookbook:wrapper
command-line = ${amarisoft-stats-template:output}
......@@ -167,68 +170,53 @@ monitor-title = {{ slapparameter_dict['name'] | string }}
password = {{ slapparameter_dict['monitor-password'] | string }}
{% endif %}
[sdr-busy-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }}
[macro.promise]
<= monitor-promise-base
name = ${:_buildout_section_name_}
[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
[check-cpu-temperature.py]
<= macro.promise
promise = check_cpu_temperature
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-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-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) }}
config-sdr = {{ sdr }}
[baseband-latency-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ baseband_latency_promise }}
output = ${directory:plugins}/check-baseband-latency.py
[check-baseband-latency.py]
<= macro.promise
promise = check_baseband_latency
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-stats-period = {{ slapparameter_dict.get("gnb_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) }}
[amarisoft-stats-log-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ amarisoft_stats_log_promise }}
[check-amarisoft-stats-log.py]
<= macro.promise
promise = check_amarisoft_stats_log
output = ${directory:plugins}/check-amarisoft-stats-log.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) }}
[cpu-temperature-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
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-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }}
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) }}
config-netconf-log = ${lopcomm-rrh-stats-template:json-log-output}
config-stats-period = {{ slapparameter_dict.get("gnb_stats_fetch_period", 60) }}
[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("gnb_stats_fetch_period", 60) }}
config-max-rx-sample-db = {{ slapparameter_dict.get("max_rx_sample_db", 0) }}
......@@ -4,9 +4,9 @@ parts =
ltelogs
lte-mme-config
lte-mme-service
tun-up-promise
monitor-base
publish-connection-information
check-interface-up.py
{% if slapparameter_dict.get("iperf3", None) %}
iperf-service
port-listening-promise
......@@ -181,15 +181,16 @@ recipe = slapos.cookbook:publish.serialised
epc-ipv6 = ${slap-configuration:ipv6-random}
epc-ipv4 = {{ epc_ipv4 }}
# Add custom promise to check if /dev/sdr0 is busy
[tun-up-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ interface_up_promise }}
output = ${directory:plugins}/check-tun-up.py
[macro.promise]
<= monitor-promise-base
name = ${:_buildout_section_name_}
[check-interface-up.py]
<= macro.promise
promise = check_interface_up
config-testing = {{ slapparameter_dict.get("testing", False) }}
{% if not slapparameter_dict.get("testing", False) %}
config-ifname = ${slap-configuration:tun-name}
{% else %}
config-ifname =
{% endif %}
config-testing = {{ slapparameter_dict.get("testing", False) }}
......@@ -152,20 +152,20 @@
"type": "number",
"default": 7
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"promise_cpu_max_spot_temp": {
"title": "Maximum CPU spot temperature",
"description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number",
"default": 90
},
"promise_cpu_avg_temperature_threshold": {
"title": "Average CPU temperature promise threshold",
"description": "If average temperature over specified duration reaches this threshold, promise will fail",
"promise_cpu_max_avg_temp": {
"title": "Maximum average CPU temperature",
"description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number",
"default": 80
},
"promise_cpu_avg_temperature_threshold_duration": {
"title": "Average CPU temperature promise threshold duration",
"promise_cpu_avg_temp_period": {
"title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold",
"type": "number",
"default": 600
......
......@@ -134,20 +134,20 @@
"type": "number",
"default": 7
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"promise_cpu_max_spot_temp": {
"title": "Maximum CPU spot temperature",
"description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number",
"default": 90
},
"promise_cpu_avg_temperature_threshold": {
"title": "Average CPU temperature promise threshold",
"description": "If average temperature over specified duration reaches this threshold, promise will fail",
"promise_cpu_max_avg_temp": {
"title": "Maximum average CPU temperature",
"description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number",
"default": 80
},
"promise_cpu_avg_temperature_threshold_duration": {
"title": "Average CPU temperature promise threshold duration",
"promise_cpu_avg_temp_period": {
"title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold",
"type": "number",
"default": 600
......
......@@ -170,9 +170,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses",
"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",
"gnb_stats_fetch_period": {
"title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number",
"default": 60
},
......
......@@ -152,9 +152,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses",
"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",
"gnb_stats_fetch_period": {
"title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number",
"default": 60
},
......
......@@ -152,20 +152,20 @@
"type": "number",
"default": 7
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"promise_cpu_max_spot_temp": {
"title": "Maximum CPU spot temperature",
"description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number",
"default": 90
},
"promise_cpu_avg_temperature_threshold": {
"title": "Average CPU temperature promise threshold",
"description": "If average temperature over specified duration reaches this threshold, promise will fail",
"promise_cpu_max_avg_temp": {
"title": "Maximum average CPU temperature",
"description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number",
"default": 80
},
"promise_cpu_avg_temperature_threshold_duration": {
"title": "Average CPU temperature promise threshold duration",
"promise_cpu_avg_temp_period": {
"title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold",
"type": "number",
"default": 600
......
......@@ -134,20 +134,20 @@
"type": "number",
"default": 7
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"promise_cpu_max_spot_temp": {
"title": "Maximum CPU spot temperature",
"description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number",
"default": 90
},
"promise_cpu_avg_temperature_threshold": {
"title": "Average CPU temperature promise threshold",
"description": "If average temperature over specified duration reaches this threshold, promise will fail",
"promise_cpu_max_avg_temp": {
"title": "Maximum average CPU temperature",
"description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number",
"default": 80
},
"promise_cpu_avg_temperature_threshold_duration": {
"title": "Average CPU temperature promise threshold duration",
"promise_cpu_avg_temp_period": {
"title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold",
"type": "number",
"default": 600
......
......@@ -170,9 +170,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses",
"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",
"gnb_stats_fetch_period": {
"title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number",
"default": 60
},
......
......@@ -152,9 +152,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses",
"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",
"gnb_stats_fetch_period": {
"title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number",
"default": 60
},
......
......@@ -152,20 +152,20 @@
"type": "number",
"default": 7
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"promise_cpu_max_spot_temp": {
"title": "Maximum CPU spot temperature",
"description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number",
"default": 90
},
"promise_cpu_avg_temperature_threshold": {
"title": "Average CPU temperature promise threshold",
"description": "If average temperature over specified duration reaches this threshold, promise will fail",
"promise_cpu_max_avg_temp": {
"title": "Maximum average CPU temperature",
"description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number",
"default": 80
},
"promise_cpu_avg_temperature_threshold_duration": {
"title": "Average CPU temperature promise threshold duration",
"promise_cpu_avg_temp_period": {
"title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold",
"type": "number",
"default": 600
......
......@@ -134,20 +134,20 @@
"type": "number",
"default": 7
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"promise_cpu_max_spot_temp": {
"title": "Maximum CPU spot temperature",
"description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number",
"default": 90
},
"promise_cpu_avg_temperature_threshold": {
"title": "Average CPU temperature promise threshold",
"description": "If average temperature over specified duration reaches this threshold, promise will fail",
"promise_cpu_max_avg_temp": {
"title": "Maximum average CPU temperature",
"description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number",
"default": 80
},
"promise_cpu_avg_temperature_threshold_duration": {
"title": "Average CPU temperature promise threshold duration",
"promise_cpu_avg_temp_period": {
"title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold",
"type": "number",
"default": 600
......
......@@ -170,9 +170,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses",
"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",
"gnb_stats_fetch_period": {
"title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number",
"default": 60
},
......
......@@ -152,9 +152,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses",
"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",
"gnb_stats_fetch_period": {
"title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number",
"default": 60
},
......
......@@ -152,20 +152,20 @@
"type": "number",
"default": 7
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"promise_cpu_max_spot_temp": {
"title": "Maximum CPU spot temperature",
"description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number",
"default": 90
},
"promise_cpu_avg_temperature_threshold": {
"title": "Average CPU temperature promise threshold",
"description": "If average temperature over specified duration reaches this threshold, promise will fail",
"promise_cpu_max_avg_temp": {
"title": "Maximum average CPU temperature",
"description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number",
"default": 80
},
"promise_cpu_avg_temperature_threshold_duration": {
"title": "Average CPU temperature promise threshold duration",
"promise_cpu_avg_temp_period": {
"title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold",
"type": "number",
"default": 600
......
......@@ -134,20 +134,20 @@
"type": "number",
"default": 7
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"promise_cpu_max_spot_temp": {
"title": "Maximum CPU spot temperature",
"description": "Maximum CPU spot temperature above which CPU temperature promise will fail",
"type": "number",
"default": 90
},
"promise_cpu_avg_temperature_threshold": {
"title": "Average CPU temperature promise threshold",
"description": "If average temperature over specified duration reaches this threshold, promise will fail",
"promise_cpu_max_avg_temp": {
"title": "Maximum average CPU temperature",
"description": "If average temperature over specified period reaches this threshold, promise will fail",
"type": "number",
"default": 80
},
"promise_cpu_avg_temperature_threshold_duration": {
"title": "Average CPU temperature promise threshold duration",
"promise_cpu_avg_temp_period": {
"title": "Period of Average CPU temperature checks",
"description": "Duration during which average temperature should not exceed specified threshold",
"type": "number",
"default": 600
......
......@@ -170,9 +170,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses",
"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",
"gnb_stats_fetch_period": {
"title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number",
"default": 60
},
......
......@@ -152,9 +152,9 @@
"description": "Set to true to use IPv4 for AMF / MME addresses",
"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",
"gnb_stats_fetch_period": {
"title": "gNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get gNB statistics",
"type": "number",
"default": 60
},
......
......@@ -4,8 +4,8 @@ parts =
ltelogs
lte-ue-lte-config
lte-ue-service
sdr-busy-promise
cpu-temperature-promise
check-sdr-busy.py
check-cpu-temperature.py
monitor-base
publish-connection-information
......@@ -125,23 +125,22 @@ monitor-title = {{ slapparameter_dict['name'] | string }}
password = {{ slapparameter_dict['monitor-password'] | string }}
{% endif %}
# Add custom promise to check if /dev/sdr0 is busy
[sdr-busy-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py
[macro.promise]
<= monitor-promise-base
name = ${:_buildout_section_name_}
[check-cpu-temperature.py]
<= macro.promise
promise = check_cpu_temperature
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]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
[check-sdr-busy.py]
<= macro.promise
promise = check_sdr_busy
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }}
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) }}
config-sdr = {{ sdr }}
......@@ -4,8 +4,8 @@ parts =
ltelogs
lte-ue-nr-config
lte-ue-service
sdr-busy-promise
cpu-temperature-promise
check-sdr-busy.py
check-cpu-temperature.py
monitor-base
publish-connection-information
......@@ -128,23 +128,22 @@ monitor-title = {{ slapparameter_dict['name'] | string }}
password = {{ slapparameter_dict['monitor-password'] | string }}
{% endif %}
# Add custom promise to check if /dev/sdr0 is busy
[sdr-busy-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }}
[macro.promise]
<= monitor-promise-base
name = ${:_buildout_section_name_}
[cpu-temperature-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
[check-cpu-temperature.py]
<= macro.promise
promise = check_cpu_temperature
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 90) }}
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) }}
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-sdr = {{ sdr }}
......@@ -32,7 +32,10 @@ context =
recipe = slapos.recipe.build
init =
import os, re
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:]
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
options['lte-version'] = lte_version
options['path'] = path
......@@ -75,7 +78,6 @@ extensions = jinja2.ext.do
extra-context =
raw monitor_template ${monitor2-template:output}
key slave_instance_list slap-configuration:slave-instance-list
raw cpu_temperature_promise ${cpu-temperature-promise:target}
[dynamic-template-lte-gnb-epc]
< = jinja2-template-base
......@@ -85,7 +87,6 @@ extensions = jinja2.ext.do
extra-context =
raw monitor_template ${monitor2-template:output}
key slave_instance_list slap-configuration:slave-instance-list
raw cpu_temperature_promise ${cpu-temperature-promise:target}
[dynamic-template-lte-epc]
< = jinja2-template-base
......@@ -95,7 +96,6 @@ extensions = jinja2.ext.do
extra-context =
raw monitor_template ${monitor2-template:output}
key slave_instance_list slap-configuration:slave-instance-list
raw cpu_temperature_promise ${cpu-temperature-promise:target}
[dynamic-template-lte-enb]
< = jinja2-template-base
......@@ -111,13 +111,6 @@ extra-context =
raw ltelogs_template ${ltelogs.jinja2.sh:target}
raw amarisoft_stats_template ${amarisoft-stats.jinja2.py:target}
raw lopcomm_rrh_stats_template ${lopcomm-rrh-stats.jinja2.py: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 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 vswr_promise ${vswr-promise:target}
raw openssl_location ${openssl:location}
raw default_dl_earfcn ${default-params:default-dl-earfcn}
raw default_lte_dl_freq ${default-params:default-lte-dl-freq}
......@@ -143,12 +136,6 @@ extra-context =
raw gnb_template ${gnb.jinja2.cfg: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 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 default_dl_nr_arfcn ${default-params:default-dl-nr-arfcn}
raw default_nr_band ${default-params:default-nr-band}
......@@ -171,7 +158,6 @@ filename = instance-lte-mme.cfg
extensions = jinja2.ext.do
extra-context =
raw monitor_template ${monitor2-template:output}
raw interface_up_promise ${interface-up-promise:target}
key mme amarisoft:mme
raw mme_template ${mme.jinja2.cfg:target}
raw ims_template ${ims.jinja2.cfg:target}
......@@ -188,13 +174,10 @@ filename = instance-lte-ue-lte.cfg
extensions = jinja2.ext.do
extra-context =
raw monitor_template ${monitor2-template:output}
raw interface_up_promise ${interface-up-promise:target}
key ue amarisoft:ue
key sdr amarisoft:sdr
raw ue_lte_template ${ue-lte.jinja2.cfg: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 default_dl_earfcn ${default-params:default-dl-earfcn}
raw default_lte_dl_freq ${default-params:default-lte-dl-freq}
......@@ -213,13 +196,10 @@ filename = instance-lte-ue-nr.cfg
extensions = jinja2.ext.do
extra-context =
raw monitor_template ${monitor2-template:output}
raw interface_up_promise ${interface-up-promise:target}
key ue amarisoft:ue
key sdr amarisoft:sdr
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 sdr_busy_promise ${sdr-busy-promise:target}
raw openssl_location ${openssl:location}
raw default_dl_nr_arfcn ${default-params:default-dl-nr-arfcn}
raw default_nr_band ${default-params:default-nr-band}
......
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)
......@@ -9,6 +9,7 @@ extends =
../../component/python3/buildout.cfg
parts +=
# slapos.toolbox-dev
template
slapos-cookbook
ltelogs.jinja2.sh
......@@ -27,6 +28,18 @@ parts +=
# apache-php
# logrotate
# [slapos.toolbox-repository]
# recipe = slapos.recipe.build:gitclone
# repository = https://lab.nexedi.com/nexedi/slapos.toolbox.git
# branch = ors
# git-executable = ${git:location}/bin/git
# develop = true
# [slapos.toolbox-dev]
# recipe = zc.recipe.egg:develop
# egg = slapos.toolbox
# setup = ${slapos.toolbox-repository:location}
# depends = ${slapos-toolbox-dependencies:eggs}
[template]
recipe = slapos.recipe.template
......@@ -67,23 +80,6 @@ url = ${:_profile_base_location_}/${:_update_hash_filename_}
[template-lte-ue-nr]
<= 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
[vswr-promise]
<= download-base
[copy-to-instance]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:_buildout_section_name_}
......@@ -146,3 +142,4 @@ interpreter = pythonwitheggs
websocket-client = 1.4.2
ncclient = 0.6.13
xmltodict = 0.13.0
# slapos.toolbox =
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