<p>pespin <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bsc/+/24253">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  pespin: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">ctrl: Introduce CTRL SET cmd to apply VTY cfg file<br><br>Depends: libosmocore.git Change-Id I720ac04386261628c0798a1bfcaa91e2490a86c3<br>Related: SYS#5369<br>Change-Id: I4c6c13418e5f7b4681b0e2a5cc8bb3bc6d8d17c3<br>---<br>M TODO-RELEASE<br>M src/osmo-bsc/bsc_ctrl_commands.c<br>M tests/Makefile.am<br>A tests/ctrl/osmo-bsc-apply-config-file-invalid.cfg<br>A tests/ctrl/osmo-bsc-apply-config-file.cfg<br>M tests/ctrl_test_runner.py<br>6 files changed, 149 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/TODO-RELEASE b/TODO-RELEASE</span><br><span>index d13cea4..e64aebb 100644</span><br><span>--- a/TODO-RELEASE</span><br><span>+++ b/TODO-RELEASE</span><br><span>@@ -11,3 +11,4 @@</span><br><span> libosmogsm    >1.5.1            enum entry GSM0808_FE_IE_LAST_USED_EUTRAN_PLMN_ID</span><br><span> libosmogsm    >1.5.1            introduced struct needed gsm0808_old_bss_to_new_bss_info->last_eutran_plmn_id</span><br><span> libosmo-mgcp-client >1.8.0  need osmo_mgcpc_ep_ci_get_remote_rtp_info()</span><br><span style="color: hsl(120, 100%, 40%);">+libosmovty >1.5.1               needs vty_read_config_filep()</span><br><span>diff --git a/src/osmo-bsc/bsc_ctrl_commands.c b/src/osmo-bsc/bsc_ctrl_commands.c</span><br><span>index 96aeba2..9038404 100644</span><br><span>--- a/src/osmo-bsc/bsc_ctrl_commands.c</span><br><span>+++ b/src/osmo-bsc/bsc_ctrl_commands.c</span><br><span>@@ -22,6 +22,9 @@</span><br><span> #include <time.h></span><br><span> </span><br><span> #include <osmocom/ctrl/control_cmd.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/vty/command.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #include <osmocom/gsm/gsm48.h></span><br><span> #include <osmocom/bsc/ipaccess.h></span><br><span> #include <osmocom/bsc/gsm_data.h></span><br><span>@@ -32,6 +35,53 @@</span><br><span> #include <osmocom/bsc/bsc_msc_data.h></span><br><span> #include <osmocom/bsc/bts.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int verify_net_apply_config_file(struct ctrl_cmd *cmd, const char *value, void *_data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        FILE *cfile;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!cmd->value || cmd->value[0] == '\0')</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  cfile = fopen(cmd->value, "r");</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!cfile)</span><br><span style="color: hsl(120, 100%, 40%);">+           return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  fclose(cfile);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static int set_net_apply_config_file(struct ctrl_cmd *cmd, void *_data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       FILE *cfile;</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned cmd_ret = CTRL_CMD_ERROR;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  LOGP(DCTRL, LOGL_NOTICE, "Applying VTY snippet from %s...\n", cmd->value);</span><br><span style="color: hsl(120, 100%, 40%);">+       cfile = fopen(cmd->value, "r");</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!cfile) {</span><br><span style="color: hsl(120, 100%, 40%);">+         LOGP(DCTRL, LOGL_NOTICE, "Applying VTY snippet from %s: fopen() failed: %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   cmd->value, errno);</span><br><span style="color: hsl(120, 100%, 40%);">+           cmd->reply = "NoFile";</span><br><span style="color: hsl(120, 100%, 40%);">+           goto close_ret;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = vty_read_config_filep(cfile, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+      LOGP(DCTRL, LOGL_NOTICE, "Applying VTY snippet from %s returned %d\n", cmd->value, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+             cmd->reply = talloc_asprintf(cmd, "ParseError=%d", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!cmd->reply)</span><br><span style="color: hsl(120, 100%, 40%);">+                   cmd->reply = "OOM";</span><br><span style="color: hsl(120, 100%, 40%);">+              goto close_ret;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   cmd->reply = "OK";</span><br><span style="color: hsl(120, 100%, 40%);">+       cmd_ret = CTRL_CMD_REPLY;</span><br><span style="color: hsl(120, 100%, 40%);">+close_ret:</span><br><span style="color: hsl(120, 100%, 40%);">+ fclose(cfile);</span><br><span style="color: hsl(120, 100%, 40%);">+        return cmd_ret;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+CTRL_CMD_DEFINE_WO(net_apply_config_file, "apply-config-file");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> CTRL_CMD_DEFINE(net_mcc, "mcc");</span><br><span> static int get_net_mcc(struct ctrl_cmd *cmd, void *_data)</span><br><span> {</span><br><span>@@ -477,6 +527,7 @@</span><br><span> int bsc_base_ctrl_cmds_install(void)</span><br><span> {</span><br><span>   int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_apply_config_file);</span><br><span>      rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mnc);</span><br><span>    rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mcc);</span><br><span>    rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_apply_config);</span><br><span>diff --git a/tests/Makefile.am b/tests/Makefile.am</span><br><span>index 6bc7839..5e23be0 100644</span><br><span>--- a/tests/Makefile.am</span><br><span>+++ b/tests/Makefile.am</span><br><span>@@ -42,6 +42,8 @@</span><br><span>      timer.vty \</span><br><span>  power_ctrl.vty \</span><br><span>     ctrl/osmo-bsc-neigh-test.cfg \</span><br><span style="color: hsl(120, 100%, 40%);">+        ctrl/osmo-bsc-apply-config-file.cfg \</span><br><span style="color: hsl(120, 100%, 40%);">+ ctrl/osmo-bsc-apply-config-file-invalid.cfg \</span><br><span>        $(NULL)</span><br><span> </span><br><span> TESTSUITE = $(srcdir)/testsuite</span><br><span>diff --git a/tests/ctrl/osmo-bsc-apply-config-file-invalid.cfg b/tests/ctrl/osmo-bsc-apply-config-file-invalid.cfg</span><br><span>new file mode 100644</span><br><span>index 0000000..b819f7d</span><br><span>--- /dev/null</span><br><span>+++ b/tests/ctrl/osmo-bsc-apply-config-file-invalid.cfg</span><br><span>@@ -0,0 +1,2 @@</span><br><span style="color: hsl(120, 100%, 40%);">+network</span><br><span style="color: hsl(120, 100%, 40%);">+ btssss-invalid-cmd</span><br><span>diff --git a/tests/ctrl/osmo-bsc-apply-config-file.cfg b/tests/ctrl/osmo-bsc-apply-config-file.cfg</span><br><span>new file mode 100644</span><br><span>index 0000000..1a069ce</span><br><span>--- /dev/null</span><br><span>+++ b/tests/ctrl/osmo-bsc-apply-config-file.cfg</span><br><span>@@ -0,0 +1,55 @@</span><br><span style="color: hsl(120, 100%, 40%);">+network</span><br><span style="color: hsl(120, 100%, 40%);">+ bts 1</span><br><span style="color: hsl(120, 100%, 40%);">+  type osmo-bts</span><br><span style="color: hsl(120, 100%, 40%);">+  band DCS1800</span><br><span style="color: hsl(120, 100%, 40%);">+  cell_identity 123</span><br><span style="color: hsl(120, 100%, 40%);">+  location_area_code 1</span><br><span style="color: hsl(120, 100%, 40%);">+  base_station_id_code 55</span><br><span style="color: hsl(120, 100%, 40%);">+  ms max power 15</span><br><span style="color: hsl(120, 100%, 40%);">+  cell reselection hysteresis 4</span><br><span style="color: hsl(120, 100%, 40%);">+  rxlev access min 0</span><br><span style="color: hsl(120, 100%, 40%);">+  radio-link-timeout 32</span><br><span style="color: hsl(120, 100%, 40%);">+  channel allocator ascending</span><br><span style="color: hsl(120, 100%, 40%);">+  rach tx integer 9</span><br><span style="color: hsl(120, 100%, 40%);">+  rach max transmission 7</span><br><span style="color: hsl(120, 100%, 40%);">+  channel-description attach 1</span><br><span style="color: hsl(120, 100%, 40%);">+  channel-description bs-pa-mfrms 5</span><br><span style="color: hsl(120, 100%, 40%);">+  channel-description bs-ag-blks-res 1</span><br><span style="color: hsl(120, 100%, 40%);">+  early-classmark-sending forbidden</span><br><span style="color: hsl(120, 100%, 40%);">+  ipa unit-id 55 0</span><br><span style="color: hsl(120, 100%, 40%);">+  oml ipa stream-id 255 line 0</span><br><span style="color: hsl(120, 100%, 40%);">+  codec-support fr</span><br><span style="color: hsl(120, 100%, 40%);">+  gprs mode gprs</span><br><span style="color: hsl(120, 100%, 40%);">+  gprs routing area 6</span><br><span style="color: hsl(120, 100%, 40%);">+  neighbor bts 0</span><br><span style="color: hsl(120, 100%, 40%);">+  trx 0</span><br><span style="color: hsl(120, 100%, 40%);">+   rf_locked 0</span><br><span style="color: hsl(120, 100%, 40%);">+   arfcn 880</span><br><span style="color: hsl(120, 100%, 40%);">+   nominal power 23</span><br><span style="color: hsl(120, 100%, 40%);">+   ! to use full TRX power, set max_power_red 0</span><br><span style="color: hsl(120, 100%, 40%);">+   max_power_red 20</span><br><span style="color: hsl(120, 100%, 40%);">+   rsl e1 tei 0</span><br><span style="color: hsl(120, 100%, 40%);">+   timeslot 0</span><br><span style="color: hsl(120, 100%, 40%);">+    phys_chan_config CCCH+SDCCH4</span><br><span style="color: hsl(120, 100%, 40%);">+    hopping enabled 0</span><br><span style="color: hsl(120, 100%, 40%);">+   timeslot 1</span><br><span style="color: hsl(120, 100%, 40%);">+    phys_chan_config TCH/F</span><br><span style="color: hsl(120, 100%, 40%);">+    hopping enabled 0</span><br><span style="color: hsl(120, 100%, 40%);">+   timeslot 2</span><br><span style="color: hsl(120, 100%, 40%);">+    phys_chan_config TCH/F</span><br><span style="color: hsl(120, 100%, 40%);">+    hopping enabled 0</span><br><span style="color: hsl(120, 100%, 40%);">+   timeslot 3</span><br><span style="color: hsl(120, 100%, 40%);">+    phys_chan_config TCH/F</span><br><span style="color: hsl(120, 100%, 40%);">+    hopping enabled 0</span><br><span style="color: hsl(120, 100%, 40%);">+   timeslot 4</span><br><span style="color: hsl(120, 100%, 40%);">+    phys_chan_config TCH/F</span><br><span style="color: hsl(120, 100%, 40%);">+    hopping enabled 0</span><br><span style="color: hsl(120, 100%, 40%);">+   timeslot 5</span><br><span style="color: hsl(120, 100%, 40%);">+    phys_chan_config TCH/F</span><br><span style="color: hsl(120, 100%, 40%);">+    hopping enabled 0</span><br><span style="color: hsl(120, 100%, 40%);">+   timeslot 6</span><br><span style="color: hsl(120, 100%, 40%);">+    phys_chan_config TCH/F</span><br><span style="color: hsl(120, 100%, 40%);">+    hopping enabled 0</span><br><span style="color: hsl(120, 100%, 40%);">+   timeslot 7</span><br><span style="color: hsl(120, 100%, 40%);">+    phys_chan_config TCH/F</span><br><span style="color: hsl(120, 100%, 40%);">+    hopping enabled 0</span><br><span>diff --git a/tests/ctrl_test_runner.py b/tests/ctrl_test_runner.py</span><br><span>index 501b917..64f93fc 100755</span><br><span>--- a/tests/ctrl_test_runner.py</span><br><span>+++ b/tests/ctrl_test_runner.py</span><br><span>@@ -488,6 +488,44 @@</span><br><span>         self.assertEqual(r['var'], 'mcc')</span><br><span>         self.assertEqual(r['value'], '002')</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def testApplyConfigFile(self):</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        vty_file = os.path.join(confpath, 'tests/ctrl/osmo-bsc-apply-config-file.cfg')</span><br><span style="color: hsl(120, 100%, 40%);">+        vty_file_invalid = os.path.join(confpath, 'tests/ctrl/osmo-bsc-apply-config-file-invalid.cfg')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        # Test some invalid input</span><br><span style="color: hsl(120, 100%, 40%);">+        r = self.do_set('apply-config-file', 'wrong-file-name-nonexistent')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['mtype'], 'ERROR')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        # Test some existing file with invalid content</span><br><span style="color: hsl(120, 100%, 40%);">+        r = self.do_set('apply-config-file', vty_file_invalid)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['mtype'], 'ERROR')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        #bts1 shouldn't exist yet, let's check:</span><br><span style="color: hsl(120, 100%, 40%);">+        r = self.do_get('bts.1.location-area-code')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['mtype'], 'ERROR')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['error'], 'Error while resolving object')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        r = self.do_set('apply-config-file', vty_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        print('respose: ' + str(r))</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['mtype'], 'SET_REPLY')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['var'], 'apply-config-file')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['value'], 'OK')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        # BTS1 should exist now:</span><br><span style="color: hsl(120, 100%, 40%);">+        r = self.do_get('bts.1.location-area-code')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['mtype'], 'GET_REPLY')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['var'], 'bts.1.location-area-code')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['value'], '1')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        # Set it again</span><br><span style="color: hsl(120, 100%, 40%);">+        r = self.do_set('apply-config-file', vty_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['mtype'], 'SET_REPLY')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['var'], 'apply-config-file')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(r['value'], 'OK')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> class TestCtrlBSCNeighbor(TestCtrlBase):</span><br><span> </span><br><span>     def tearDown(self):</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bsc/+/24253">change 24253</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-bsc/+/24253"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bsc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I4c6c13418e5f7b4681b0e2a5cc8bb3bc6d8d17c3 </div>
<div style="display:none"> Gerrit-Change-Number: 24253 </div>
<div style="display:none"> Gerrit-PatchSet: 6 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: daniel <dwillmann@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>