software/ors-amarisoft: Merge instance-gnb.jinja2.cfg into instance-enb.jinja2.cfg

In MultiRU one enb will be driving multiple, possible of different kind,
TDD/FDD and LTE/NR cells all at the same time, because that standard
functionality of a base station and because original Amarisoft software
supports that out of the box.

However we currently have enb and gnb services separate and duplicating most of
each other code.

-> Merge instance-enb.jinja2.cfg and instance-gnb.jinja2.cfg as a preparatory step for MultiRU.

- instance-enb.jinja2.cfg pulls gnb specific bits from instance-gnb.jinja2.cfg
- instance-gnb.jinja2.cfg goes away effectively switching gnb to use
  ru/libinstance.jinja2.cfg like enb already does
- For parameters that were duplicated as enb_<X> and gnb_<X>  generic software
  now accepts only enb_<X> with ORS mode wrapper providing backward
  compatibility for gnb_* parameters. For example if gnb_config_link is given
  for a gnb instance, it will be translated to enb_config_link to underlying
  generic enb so that gnb_config_link works correctly.

  For ORS we care to provide 100% backward compatibility because there are many ORS'es deployed.
  For generic software we are free to clean things up as needed, because there
  is not much generic deployments at this time.

/cc @jhuge, @lu.xu, @tomo, @xavier_thompson, @Daetalus
/proposed-for-review-on !1522
/reviewed-by TrustMe

--------

Appendix. Diff between instance-enb.jinja2.cfg and instance-gnb.jinja2.cfg before this patch

```
$ git diff --no-index instance-enb.jinja2.cfg instance-gnb.jinja2.cfg
```

```diff
diff --git a/instance-enb.jinja2.cfg b/instance-gnb.jinja2.cfg
index 6d4ce7e94..6ee62b3ff 100644
--- a/instance-enb.jinja2.cfg
+++ b/instance-gnb.jinja2.cfg
@@ -1,19 +1,25 @@
 {#- defaults for eNB radio parameters.
     NOTE they are installed temporary and will go away after switch to generic multiRU. #}
 {%- do RF.setdefault('tx_gain',     slapparameter_dict.get('tx_gain',     0)) %}
 {%- do RF.setdefault('rx_gain',     slapparameter_dict.get('rx_gain',     0)) %}
-{%- do RF.setdefault('dl_earfcn',   slapparameter_dict.get('dl_earfcn',   0)) %}
+{%- do RF.setdefault('dl_nr_arfcn', slapparameter_dict.get('dl_nr_arfcn', 0)) %}
+{%- do RF.setdefault('nr_band',     slapparameter_dict.get('nr_band',     0)) %}

 [buildout]
 parts =
   directory
-  enb-config
+  gnb-config
   enb-service
   xamari-xlog-service
 {% if slapparameter_dict.get('xlog_fluentbit_forward_host') %}
   xlog-fluentbit-service
 {% endif %}
+  amarisoft-stats-service
+  amarisoft-rf-info-service
+  check-sdr-busy.py
   check-baseband-latency.py
+  check-amarisoft-stats-log.py
+  check-rx-saturated.py
   monitor-base
   publish-connection-information

@@ -23,11 +29,6 @@ eggs-directory = {{ eggs_directory }}
 develop-eggs-directory = {{ develop_eggs_directory }}
 offline = true

-{%- import 'slaplte.jinja2'            as slaplte with context  %}
-{%- import 'ru_libinstance.jinja2.cfg' as rulib   with context  %}
-{{ rulib.buildout() }}
-
-
 [monitor-httpd-conf-parameter]
 httpd-include-file = {{ buildout_directory }}/etc/httpd-include-file.conf
 port = ${monitor-instance-parameter:monitor-httpd-port}
@@ -52,10 +53,11 @@ cert = {{ slap_connection['cert-file'] }}

 configuration.com_ws_port = 9001
 configuration.com_addr = 127.0.1.2
-configuration.mme_addr = 127.0.1.100
+configuration.amf_addr = 127.0.1.100
 configuration.gtp_addr = 127.0.1.1
-configuration.default_lte_bandwidth = {{ default_lte_bandwidth }}
-configuration.default_lte_inactivity_timer = {{ default_lte_inactivity_timer }}
+configuration.default_nr_bandwidth = {{ default_nr_bandwidth }}
+configuration.default_nr_inactivity_timer = {{ default_nr_inactivity_timer }}
+configuration.default_nr_ssb_pos_bitmap = {{ default_nr_ssb_pos_bitmap }}
 configuration.default_n_antenna_dl = {{ default_n_antenna_dl }}
 configuration.default_n_antenna_ul = {{ default_n_antenna_ul }}

@@ -63,6 +65,7 @@ configuration.default_n_antenna_ul = {{ default_n_antenna_ul }}
 recipe = slapos.cookbook:mkdirectory
 software = {{ buildout_directory }}
 home = ${buildout:directory}
+etc = ${:home}/etc
 var = ${:home}/var
 etc = ${:home}/etc
 bin = ${:home}/bin
@@ -73,30 +76,32 @@ service = ${:etc}/service
 promise = ${:etc}/promise
 log = ${:var}/log

-{% if slapparameter_dict.get("enb_config_link", None) %}
-[enb-config-dl]
+{% if slapparameter_dict.get("gnb_config_link", None) %}
+[gnb-config-dl]
 recipe = slapos.recipe.build:download
-url = {{ slapparameter_dict.get("enb_config_link") }}
-version = {{ slapparameter_dict.get("enb_config_version") }}
+url = {{ slapparameter_dict.get("gnb_config_link") }}
+version = {{ slapparameter_dict.get("gnb_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
+gnb-log = ${directory:log}/gnb-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};
+  (echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting gNB software..." && echo) >> ${:gnb-log};
+  tail -c 1M ${:gnb-log} > ${:gnb-log}.tmp;
+  mv ${:gnb-log}.tmp ${:gnb-log};
+  {{ enb }}/lteenb ${directory:etc}/gnb.cfg >> ${:gnb-log} 2>> ${:gnb-log};
+
 {% endif %}

+### eNodeB (enb)
 [enb-service]
 recipe = slapos.cookbook:wrapper
 command-line = ${enb-sh-wrapper:output}
@@ -105,7 +110,7 @@ mode = 0775
 reserve-cpu = True
 pidfile = ${directory:run}/enb.pid
 hash-files =
-  ${enb-config:output}
+  ${gnb-config:output}
   ${enb-sh-wrapper:output}
 environment =
   LD_LIBRARY_PATH={{ openssl_location }}/lib
@@ -114,22 +119,23 @@ environment =
 [xamari-xlog-script]
 recipe = slapos.recipe.template
 output = ${directory:bin}/${:_buildout_section_name_}
-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
+period = {{ slapparameter_dict.get("gnb_stats_fetch_period", 60) }}
 stats_logspec = stats[samples,rf]/${:period}s
-{%- if slapparameter_dict.get("enb_drb_stats_enabled", True) %}
+{%- if slapparameter_dict.get("gnb_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", "") %}
+logspec = ${:stats_logspec} ${:drb_stats_logspec}
+{% if slapparameter_dict.get("websocket_password", "") %}
 websock = ws://[${slap-configuration:ipv6-random}]:9001
-{%- else %}
+{% else %}
 websock = ws://127.0.1.2:9001
-{%- endif %}
+{% endif %}
 xamari = {{ buildout_directory }}/bin/xamari
-logfile = ${monitor-directory:public}/enb.xlog
+logfile = ${monitor-directory:public}/gnb.xlog
 inline =
   #!/bin/sh
   exec ${:xamari} xlog --rotate ${:rotatespec} ${:websock} ${:logfile} ${:logspec}
@@ -177,6 +183,52 @@ wrapper-path = ${directory:service}/${:_buildout_section_name_}
 hash-files = ${:fluentbit-config}
 {% endif %}

+[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("gnb_stats_fetch_period", 60) }}
+  raw testing {{ slapparameter_dict.get("testing", False) }}
+  raw python_path {{ buildout_directory}}/bin/pythonwitheggs
+mode = 0775
+url = {{ ru_amarisoft_stats_template }}
+output = ${directory:bin}/amarisoft-stats.py
+
+[amarisoft-rf-info-template]
+recipe = slapos.recipe.template:jinja2
+extensions = jinja2.ext.do
+log-output = ${directory:var}/log/amarisoft-rf-info.json.log
+context =
+  section directory directory
+  key slapparameter_dict slap-configuration:configuration
+  key log_file :log-output
+  raw stats_period {{ slapparameter_dict.get("gnb_stats_fetch_period", 60) }}
+  raw testing {{ slapparameter_dict.get("testing", False) }}
+  raw python_path {{ buildout_directory}}/bin/pythonwitheggs
+mode = 0775
+url = {{ ru_amarisoft_rf_info_template }}
+output = ${directory:bin}/amarisoft-rf-info.py
+
+[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}
+
+[amarisoft-rf-info-service]
+recipe = slapos.cookbook:wrapper
+command-line = ${amarisoft-rf-info-template:output}
+wrapper-path = ${directory:service}/amarisoft-rf-info
+mode = 0775
+hash-files =
+  ${amarisoft-rf-info-template:output}
+
 [config-base]
 recipe = slapos.recipe.template:jinja2
 extensions = jinja2.ext.do
@@ -190,53 +242,47 @@ context =
   raw gtp_addr_v4 {{ lan_ipv4 }}
   raw tx_gain {{ RF.tx_gain }}
   raw rx_gain {{ RF.rx_gain }}
-  raw earfcn  {{ RF.dl_earfcn }}
+  raw nr_arfcn {{ RF.dl_nr_arfcn }}
+  raw nr_band {{ RF.nr_band }}
   raw software_name {{ software_name }}
   raw rf_mode {{ rf_mode }}
   raw trx {{ trx }}
   raw bbu {{ bbu }}
   raw ru_type {{ ru }}
-  json do_lte true
-  json do_nr  false
+  json do_lte false
+  json do_nr  true
   import  netaddr netaddr
   ${:extra-context}

-[sib-config]
-<= config-base
-url = {{ sib23_template }}
-output = ${directory:etc}/sib23.cfg
-
 [drb-config]
 <= config-base
-url = {{ drb_lte_template }}
+url = {{ drb_nr_template }}
 output = ${directory:etc}/drb.cfg

-[enb-config]
+[gnb-config]
 <= config-base
-{% if slapparameter_dict.get("enb_config_link", None) %}
-url = ${enb-config-dl:target}
+{% if slapparameter_dict.get("gnb_config_link", None) %}
+url = ${gnb-config-dl:target}
 {% else %}
 url = {{ enb_template }}
 {% endif %}
-output = ${directory:etc}/enb.cfg
+output = ${directory:etc}/gnb.cfg
 extra-context =
     import json_module json
-    json cell_list {{ rulib.cell_list | tojson }}
-    key sib23_file sib-config:output
     key drb_file   drb-config:output
 import-list =
     rawfile slaplte.jinja2 {{ slaplte_template }}

-
 [publish-connection-information]
 <= monitor-publish
 recipe = slapos.cookbook:publish.serialised
 {%- if slapparameter_dict.get("websocket_password", "") %}
 websocket_url = ws://[${slap-configuration:ipv6-random}]:9001
 {%- endif %}
-enb-ipv6 = ${slap-configuration:ipv6-random}
-enb-ipv4 = {{ lan_ipv4 }}
-current-earfcn  = {{ RF.dl_earfcn }}
+gnb-ipv6 = ${slap-configuration:ipv6-random}
+gnb-ipv4 = {{ lan_ipv4 }}
+current-nr-arfcn = {{ RF.dl_nr_arfcn }}
+current-nr-band = {{ RF.nr_band }}
 amarisoft-version = {{ lte_version }}
 license-expiration = {{ lte_expiration }}
 monitor-gadget-url = ${:monitor-base-url}/gadget/software.cfg.html
@@ -253,10 +299,35 @@ password = {{ slapparameter_dict['monitor-password'] | string }}
 <= monitor-promise-base
 name = ${:_buildout_section_name_}

+[check-sdr-busy.py]
+<= macro.promise
+promise = check_sdr_busy
+config-testing = {{ slapparameter_dict.get("testing", False) }}
+config-sdr = {{ sdr }}
+config-sdr_dev  = 0
+config-dma_chan = 0
+
 [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-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
+config-stats-period = {{ slapparameter_dict.get("gnb_stats_fetch_period", 60) }}
 config-min-rxtx-delay = {{ slapparameter_dict.get("min_rxtx_delay", 0) }}
+
+[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("gnb_stats_fetch_period", 60) }}
+
+[check-rx-saturated.py]
+<= macro.promise
+promise = check_rx_saturated
+config-testing = {{ slapparameter_dict.get("testing", False) }}
+config-rf-rx-chan-list = {{ list(range(0, int(slapparameter_dict.get('n_antenna_ul', default_n_antenna_ul)))) }}
+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 jobs for master in 0 seconds
Status Job ID Name Coverage
  External
passed Cloudooo.UnitTest-Master

00:16:10

passed SlapOS.Eggs.UnitTest-Master.Python2

00:19:45

passed SlapOS.Eggs.UnitTest-Master.Python3

00:19:10

failed SlapOS.Eggs.UnitTest-Master.Python3Next

00:15:00