# instance-enb implements eNB/gNB service.

{#- defaults for global eNB/gNB parameters.
    TODO automatically load enb defaults from JSON schema #}
{%- set enb_defaults = {
  'com_ws_port':  9001,
  'com_addr':     '127.0.1.2',
  'use_ipv4':     False,
  'gnb_id_bits':  28,
  'nssai':        {'1': {'sst': 1}},
} %}
{%- set gtp_addr_lo = '127.0.1.1' %}
{%- for k,v in enb_defaults|dictsort %}
{%-   do slapparameter_dict.setdefault(k, v) %}
{%- endfor %}


[buildout]
parts =
  directory
  enb-config
  enb-service
  xamari-xlog-service
{% if slapparameter_dict.get('xlog_fluentbit_forward_host') %}
  xlog-fluentbit-service
{% endif %}
  check-baseband-latency.py
  monitor-base
  publish-connection-information

extends = {{ monitor_template }}

eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true

{%- set icell_kind='enb'                                        %}
{%- import 'slaplte.jinja2'            as slaplte with context  %}
{%- import 'ru_libinstance.jinja2.cfg' as rulib   with context  %}
{%- set ipeer_dict = {}                                         %}
{%- set ipeercell_dict = {}                                     %}
{%- do slaplte.load_ipeer(ipeer_dict)                           %}
{%- do slaplte.load_ipeercell(ipeercell_dict)                   %}
{%- do slaplte.check_loaded_everything()                        %}

{{ rulib.buildout() }}

[myslap]
# NOTE we don't query slapos.cookbook:slapconfiguration the second time because
# slapparameter_dict is potentially modified with defaults.
parameter_dict = {{ dumps(slapparameter_dict) }}
configuration = {{ dumps(slap_configuration) }}


[monitor-httpd-conf-parameter]
httpd-include-file = {{ buildout_directory }}/etc/httpd-include-file.conf
port = ${monitor-instance-parameter:monitor-httpd-port}
url = https://[${monitor-instance-parameter:monitor-httpd-ipv6}]:${:port}

[monitor-instance-parameter]
monitor-httpd-port = ${monitor-address:port}

[monitor-address]
recipe = slapos.cookbook:free_port
minimum = 8035
maximum = 8055
ip = ${monitor-instance-parameter:monitor-httpd-ipv6}


[directory]
recipe = slapos.cookbook:mkdirectory
software = {{ buildout_directory }}
home = ${buildout:directory}
var = ${:home}/var
etc = ${:home}/etc
bin = ${:home}/bin
tmp = ${:home}/tmp
run = ${:var}/run
script = ${:etc}/run
service = ${:etc}/service
promise = ${:etc}/promise
log = ${:var}/log

{% if slapparameter_dict.get("enb_config_link", None) %}
[enb-config-dl]
recipe = slapos.recipe.build:download
url = {{ slapparameter_dict.get("enb_config_link") }}
version = {{ slapparameter_dict.get("enb_config_version") }}
offline = false
{% endif %}

[enb-sh-wrapper]
recipe = slapos.recipe.template
output = ${directory:bin}/${:_buildout_section_name_}
enb-log = ${directory:log}/enb-output.log
inline =
  #!/bin/sh
{% if not slapparameter_dict.get("testing", False) %}
  sudo -n /opt/amarisoft/rm-tmp-lte;
  sudo -n /opt/amarisoft/init-sdr;
  sudo -n /opt/amarisoft/init-enb;
  (echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting eNB software..." && echo) >> ${:enb-log};
  tail -c 1M ${:enb-log} > ${:enb-log}.tmp;
  mv ${:enb-log}.tmp ${:enb-log};
  {{ enb }}/lteenb ${directory:etc}/enb.cfg >> ${:enb-log} 2>> ${:enb-log};
{% endif %}

[enb-service]
recipe = slapos.cookbook:wrapper
command-line = ${enb-sh-wrapper:output}
wrapper-path = ${directory:service}/enb
mode = 0775
reserve-cpu = True
pidfile = ${directory:run}/enb.pid
hash-files =
  ${enb-config:output}
  ${enb-sh-wrapper:output}
environment =
  LD_LIBRARY_PATH={{ openssl_location }}/lib
  AMARISOFT_PATH=/opt/amarisoft/.amarisoft

[xamari-xlog-script]
recipe = slapos.recipe.template
output = ${directory:bin}/${:_buildout_section_name_}
period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
stats_logspec = stats[samples,rf]/${:period}s
{%- if slapparameter_dict.get("enb_drb_stats_enabled", True) %}
drb_stats_logspec = x.drb_stats/${:period}s
{%- else %}
drb_stats_logspec =
{%- endif %}
rotatespec = 100MB.9
logspec = ${:stats_logspec} ${:drb_stats_logspec}
{%- if slapparameter_dict.get("websocket_password", "") %}
websock = ws://[{{my_ipv6}}]:9001
{%- else %}
websock = ws://127.0.1.2:9001
{%- endif %}
xamari = {{ buildout_directory }}/bin/xamari
logfile = ${monitor-directory:public}/enb.xlog
inline =
  #!/bin/sh
  exec ${:xamari} xlog --rotate ${:rotatespec} ${:websock} ${:logfile} ${:logspec}

[xamari-xlog-service]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:service}/${:_buildout_section_name_}
command-line = ${xamari-xlog-script:output}
hash-files = ${:command-line}

{% if slapparameter_dict.get('xlog_fluentbit_forward_host') %}
[xlog-fluentbit-config]
recipe = slapos.recipe.template
output = ${directory:etc}/${:_buildout_section_name_}.cfg
logfile = ${xamari-xlog-script:logfile}
forward-host = {{ slapparameter_dict.get('xlog_fluentbit_forward_host', '') }}
forward-port = {{ slapparameter_dict.get('xlog_fluentbit_forward_port', '') }}
forward-shared-key = {{ slapparameter_dict.get('xlog_fluentbit_forward_shared_key', '') }}
forward-self-hostname = {{ comp_id['comp-id'] }}
inline =
  [SERVICE]
      flush           5
  [INPUT]
      name            tail
      path            ${:logfile}
      Read_from_Head  True
  [OUTPUT]
      name            forward
      match           *
      Host            ${:forward-host}
{%- if slapparameter_dict.get('xlog_fluentbit_forward_port') %}
      Port            ${:forward-port}
{%- endif %}
{%- if slapparameter_dict.get('xlog_fluentbit_forward_shared_key') %}
      Shared_Key      ${:forward-shared-key}
{%- endif %}
      Self_Hostname   ${:forward-self-hostname}
      tls             on
      tls.verify      off

[xlog-fluentbit-service]
recipe  = slapos.cookbook:wrapper
fluentbit =  {{ fluent_bit_location }}/bin/fluent-bit
fluentbit-config = ${xlog-fluentbit-config:output}
command-line = ${:fluentbit} -c ${:fluentbit-config}
wrapper-path = ${directory:service}/${:_buildout_section_name_}
hash-files = ${:fluentbit-config}
{% endif %}

[config-base]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
extra-context =
context =
  json ors false
  section directory directory
  key slap_configuration myslap:configuration
  key slapparameter_dict myslap:parameter_dict
  raw gtp_addr_v6 {{ my_ipv6 }}
  raw gtp_addr_v4 {{ lan_ipv4 }}
  raw gtp_addr_lo {{ gtp_addr_lo }}
  import  xbuildout xbuildout
  import  netaddr netaddr
  ${:extra-context}

[enb-config]
<= config-base
{% if slapparameter_dict.get("enb_config_link", None) %}
url = ${enb-config-dl:target}
{% else %}
url = {{ enb_template }}
{% endif %}
output = ${directory:etc}/enb.cfg
import-list =
    rawfile slaplte.jinja2 {{ slaplte_template }}
extra-context =
    import json_module json
    key iru_dict       :iru_dict
    key icell_dict     :icell_dict
    key ipeer_dict     :ipeer_dict
    key ipeercell_dict :ipeercell_dict
iru_dict       = {{ dumps(rulib.iru_dict) }}
icell_dict     = {{ dumps(rulib.icell_dict) }}
ipeer_dict     = {{ dumps(ipeer_dict) }}
ipeercell_dict = {{ dumps(ipeercell_dict) }}


[publish-connection-information]
<= monitor-publish
recipe = slapos.cookbook:publish.serialised
{%- if slapparameter_dict.get("websocket_password", "") %}
websocket_url = ws://[{{my_ipv6}}]:9001
{%- endif %}
enb-ipv6 = {{ my_ipv6 }}
enb-ipv4 = {{ lan_ipv4 }}
amarisoft-version = {{ lte_version }}
license-expiration = {{ lte_expiration }}
monitor-gadget-url = ${:monitor-base-url}/gadget/software.cfg.html
ru-list   = {{ dumps(rulib.iru_dict.keys()   | sort) }}
cell-list = {{ dumps(rulib.icell_dict.keys() | sort) }}
peer-list = {{ dumps(ipeer_dict.keys()       | sort) }}
peer-cell-list = {{ dumps(ipeercell_dict.keys() | sort) }}


[monitor-instance-parameter]
{% if slapparameter_dict.get("name", None) %}
monitor-title = {{ slapparameter_dict['name'] | string }}
{% endif %}
{% if slapparameter_dict.get("monitor-password", None) %}
password = {{ slapparameter_dict['monitor-password'] | string }}
{% endif %}

[macro.promise]
<= monitor-promise-base
name = ${:_buildout_section_name_}

[check-baseband-latency.py]
<= macro.promise
promise = check_baseband_latency
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${ru_amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
config-min-rxtx-delay = {{ slapparameter_dict.get("min_rxtx_delay", 0) }}
