From 25ff634b5eb06bc1411125dd01efae246e976c4a Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Mon, 17 May 2021 18:59:58 +0200 Subject: [PATCH] ctrl: Introduce CTRL SET cmd to apply VTY cfg file Depends: libosmocore.git Change-Id I720ac04386261628c0798a1bfcaa91e2490a86c3 Related: SYS#5369 Change-Id: I4c6c13418e5f7b4681b0e2a5cc8bb3bc6d8d17c3 --- TODO-RELEASE | 1 + src/osmo-bsc/bsc_ctrl_commands.c | 51 +++++++++++++++++ tests/Makefile.am | 2 + .../osmo-bsc-apply-config-file-invalid.cfg | 2 + tests/ctrl/osmo-bsc-apply-config-file.cfg | 55 +++++++++++++++++++ tests/ctrl_test_runner.py | 38 +++++++++++++ 6 files changed, 149 insertions(+) create mode 100644 tests/ctrl/osmo-bsc-apply-config-file-invalid.cfg create mode 100644 tests/ctrl/osmo-bsc-apply-config-file.cfg diff --git a/TODO-RELEASE b/TODO-RELEASE index d13cea4d5..e64aebbac 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -11,3 +11,4 @@ libosmocore >1.5.1 needs osmo_bts_features_name(), osmo_bts_features_desc() libosmogsm >1.5.1 enum entry GSM0808_FE_IE_LAST_USED_EUTRAN_PLMN_ID libosmogsm >1.5.1 introduced struct needed gsm0808_old_bss_to_new_bss_info->last_eutran_plmn_id libosmo-mgcp-client >1.8.0 need osmo_mgcpc_ep_ci_get_remote_rtp_info() +libosmovty >1.5.1 needs vty_read_config_filep() diff --git a/src/osmo-bsc/bsc_ctrl_commands.c b/src/osmo-bsc/bsc_ctrl_commands.c index 96aeba2c7..903840439 100644 --- a/src/osmo-bsc/bsc_ctrl_commands.c +++ b/src/osmo-bsc/bsc_ctrl_commands.c @@ -22,6 +22,9 @@ #include #include + +#include + #include #include #include @@ -32,6 +35,53 @@ #include #include +static int verify_net_apply_config_file(struct ctrl_cmd *cmd, const char *value, void *_data) +{ + FILE *cfile; + + if (!cmd->value || cmd->value[0] == '\0') + return -1; + + cfile = fopen(cmd->value, "r"); + if (!cfile) + return -1; + + fclose(cfile); + + return 0; +} +static int set_net_apply_config_file(struct ctrl_cmd *cmd, void *_data) +{ + int rc; + FILE *cfile; + unsigned cmd_ret = CTRL_CMD_ERROR; + + LOGP(DCTRL, LOGL_NOTICE, "Applying VTY snippet from %s...\n", cmd->value); + cfile = fopen(cmd->value, "r"); + if (!cfile) { + LOGP(DCTRL, LOGL_NOTICE, "Applying VTY snippet from %s: fopen() failed: %d\n", + cmd->value, errno); + cmd->reply = "NoFile"; + goto close_ret; + } + + rc = vty_read_config_filep(cfile, NULL); + LOGP(DCTRL, LOGL_NOTICE, "Applying VTY snippet from %s returned %d\n", cmd->value, rc); + if (rc) { + cmd->reply = talloc_asprintf(cmd, "ParseError=%d", rc); + if (!cmd->reply) + cmd->reply = "OOM"; + goto close_ret; + } + + cmd->reply = "OK"; + cmd_ret = CTRL_CMD_REPLY; +close_ret: + fclose(cfile); + return cmd_ret; +} +CTRL_CMD_DEFINE_WO(net_apply_config_file, "apply-config-file"); + CTRL_CMD_DEFINE(net_mcc, "mcc"); static int get_net_mcc(struct ctrl_cmd *cmd, void *_data) { @@ -477,6 +527,7 @@ CTRL_CMD_DEFINE(trx_max_power, "max-power-reduction"); int bsc_base_ctrl_cmds_install(void) { int rc = 0; + rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_apply_config_file); rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mnc); rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mcc); rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_apply_config); diff --git a/tests/Makefile.am b/tests/Makefile.am index 6bc78392e..5e23be0a4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -42,6 +42,8 @@ EXTRA_DIST = \ timer.vty \ power_ctrl.vty \ ctrl/osmo-bsc-neigh-test.cfg \ + ctrl/osmo-bsc-apply-config-file.cfg \ + ctrl/osmo-bsc-apply-config-file-invalid.cfg \ $(NULL) TESTSUITE = $(srcdir)/testsuite diff --git a/tests/ctrl/osmo-bsc-apply-config-file-invalid.cfg b/tests/ctrl/osmo-bsc-apply-config-file-invalid.cfg new file mode 100644 index 000000000..b819f7dc2 --- /dev/null +++ b/tests/ctrl/osmo-bsc-apply-config-file-invalid.cfg @@ -0,0 +1,2 @@ +network + btssss-invalid-cmd diff --git a/tests/ctrl/osmo-bsc-apply-config-file.cfg b/tests/ctrl/osmo-bsc-apply-config-file.cfg new file mode 100644 index 000000000..1a069ce75 --- /dev/null +++ b/tests/ctrl/osmo-bsc-apply-config-file.cfg @@ -0,0 +1,55 @@ +network + bts 1 + type osmo-bts + band DCS1800 + cell_identity 123 + location_area_code 1 + base_station_id_code 55 + ms max power 15 + cell reselection hysteresis 4 + rxlev access min 0 + radio-link-timeout 32 + channel allocator ascending + rach tx integer 9 + rach max transmission 7 + channel-description attach 1 + channel-description bs-pa-mfrms 5 + channel-description bs-ag-blks-res 1 + early-classmark-sending forbidden + ipa unit-id 55 0 + oml ipa stream-id 255 line 0 + codec-support fr + gprs mode gprs + gprs routing area 6 + neighbor bts 0 + trx 0 + rf_locked 0 + arfcn 880 + nominal power 23 + ! to use full TRX power, set max_power_red 0 + max_power_red 20 + rsl e1 tei 0 + timeslot 0 + phys_chan_config CCCH+SDCCH4 + hopping enabled 0 + timeslot 1 + phys_chan_config TCH/F + hopping enabled 0 + timeslot 2 + phys_chan_config TCH/F + hopping enabled 0 + timeslot 3 + phys_chan_config TCH/F + hopping enabled 0 + timeslot 4 + phys_chan_config TCH/F + hopping enabled 0 + timeslot 5 + phys_chan_config TCH/F + hopping enabled 0 + timeslot 6 + phys_chan_config TCH/F + hopping enabled 0 + timeslot 7 + phys_chan_config TCH/F + hopping enabled 0 diff --git a/tests/ctrl_test_runner.py b/tests/ctrl_test_runner.py index 501b917b5..64f93fc1d 100755 --- a/tests/ctrl_test_runner.py +++ b/tests/ctrl_test_runner.py @@ -488,6 +488,44 @@ class TestCtrlBSC(TestCtrlBase): self.assertEqual(r['var'], 'mcc') self.assertEqual(r['value'], '002') + + def testApplyConfigFile(self): + + vty_file = os.path.join(confpath, 'tests/ctrl/osmo-bsc-apply-config-file.cfg') + vty_file_invalid = os.path.join(confpath, 'tests/ctrl/osmo-bsc-apply-config-file-invalid.cfg') + + # Test some invalid input + r = self.do_set('apply-config-file', 'wrong-file-name-nonexistent') + self.assertEqual(r['mtype'], 'ERROR') + + # Test some existing file with invalid content + r = self.do_set('apply-config-file', vty_file_invalid) + self.assertEqual(r['mtype'], 'ERROR') + + #bts1 shouldn't exist yet, let's check: + r = self.do_get('bts.1.location-area-code') + self.assertEqual(r['mtype'], 'ERROR') + self.assertEqual(r['error'], 'Error while resolving object') + + r = self.do_set('apply-config-file', vty_file) + print('respose: ' + str(r)) + self.assertEqual(r['mtype'], 'SET_REPLY') + self.assertEqual(r['var'], 'apply-config-file') + self.assertEqual(r['value'], 'OK') + + # BTS1 should exist now: + r = self.do_get('bts.1.location-area-code') + self.assertEqual(r['mtype'], 'GET_REPLY') + self.assertEqual(r['var'], 'bts.1.location-area-code') + self.assertEqual(r['value'], '1') + + # Set it again + r = self.do_set('apply-config-file', vty_file) + self.assertEqual(r['mtype'], 'SET_REPLY') + self.assertEqual(r['var'], 'apply-config-file') + self.assertEqual(r['value'], 'OK') + + class TestCtrlBSCNeighbor(TestCtrlBase): def tearDown(self):