<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>