]> git.proxmox.com Git - mirror_frr.git/blame - mgmtd/mgmt_vty.c
Merge pull request #13369 from samanvithab/bgpd_fix
[mirror_frr.git] / mgmtd / mgmt_vty.c
CommitLineData
1c84efe4
CH
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * MGMTD VTY Interface
4 *
5 * Copyright (C) 2021 Vmware, Inc.
6 * Pushpasis Sarkar <spushpasis@vmware.com>
7 */
8
9#include <zebra.h>
10
11#include "command.h"
12#include "json.h"
8033bf39
CH
13#include "northbound_cli.h"
14
1c84efe4 15#include "mgmtd/mgmt.h"
7d65b7b7
CH
16#include "mgmtd/mgmt_be_server.h"
17#include "mgmtd/mgmt_be_adapter.h"
ef43a632
CH
18#include "mgmtd/mgmt_fe_server.h"
19#include "mgmtd/mgmt_fe_adapter.h"
1c84efe4 20#include "mgmtd/mgmt_ds.h"
74335ceb 21#include "mgmtd/mgmt_history.h"
1c84efe4 22
1c84efe4 23#include "mgmtd/mgmt_vty_clippy.c"
ef43a632 24
7d65b7b7
CH
25DEFPY(show_mgmt_be_adapter,
26 show_mgmt_be_adapter_cmd,
27 "show mgmt backend-adapter all",
28 SHOW_STR
29 MGMTD_STR
30 MGMTD_BE_ADAPTER_STR
31 "Display all Backend Adapters\n")
32{
33 mgmt_be_adapter_status_write(vty);
34
35 return CMD_SUCCESS;
36}
37
38DEFPY(show_mgmt_be_xpath_reg,
39 show_mgmt_be_xpath_reg_cmd,
40 "show mgmt backend-yang-xpath-registry",
41 SHOW_STR
42 MGMTD_STR
43 "Backend Adapter YANG Xpath Registry\n")
44{
45 mgmt_be_xpath_register_write(vty);
46
47 return CMD_SUCCESS;
48}
49
ef43a632
CH
50DEFPY(show_mgmt_fe_adapter, show_mgmt_fe_adapter_cmd,
51 "show mgmt frontend-adapter all [detail$detail]",
52 SHOW_STR
53 MGMTD_STR
54 MGMTD_FE_ADAPTER_STR
55 "Display all Frontend Adapters\n"
56 "Display more details\n")
57{
58 mgmt_fe_adapter_status_write(vty, !!detail);
59
60 return CMD_SUCCESS;
61}
1c84efe4 62
74335ceb
YR
63DEFPY_HIDDEN(mgmt_performance_measurement,
64 mgmt_performance_measurement_cmd,
65 "[no] mgmt performance-measurement",
66 NO_STR
67 MGMTD_STR
68 "Enable performance measurement\n")
69{
70 if (no)
71 mgmt_fe_adapter_perf_measurement(vty, false);
72 else
73 mgmt_fe_adapter_perf_measurement(vty, true);
74
75 return CMD_SUCCESS;
76}
77
78DEFPY(mgmt_reset_performance_stats,
79 mgmt_reset_performance_stats_cmd,
80 "mgmt reset-statistics",
81 MGMTD_STR
82 "Reset the Performance measurement statistics\n")
83{
84 mgmt_fe_adapter_reset_perf_stats(vty);
85
86 return CMD_SUCCESS;
87}
88
89DEFPY(show_mgmt_txn,
90 show_mgmt_txn_cmd,
91 "show mgmt transaction all",
92 SHOW_STR
93 MGMTD_STR
94 MGMTD_TXN_STR
95 "Display all Transactions\n")
96{
97 mgmt_txn_status_write(vty);
98
99 return CMD_SUCCESS;
100}
101
1c84efe4
CH
102DEFPY(show_mgmt_ds,
103 show_mgmt_ds_cmd,
104 "show mgmt datastore [all|candidate|operational|running]$dsname",
105 SHOW_STR
106 MGMTD_STR
107 MGMTD_DS_STR
108 "All datastores (default)\n"
109 "Candidate datastore\n"
110 "Operational datastore\n"
111 "Running datastore\n")
112{
113 struct mgmt_ds_ctx *ds_ctx;
114
115 if (!dsname || dsname[0] == 'a') {
116 mgmt_ds_status_write(vty);
117 return CMD_SUCCESS;
118 }
119 ds_ctx = mgmt_ds_get_ctx_by_id(mm, mgmt_ds_name2id(dsname));
120 if (!ds_ctx) {
121 vty_out(vty, "ERROR: Could not access %s datastore!\n", dsname);
122 return CMD_ERR_NO_MATCH;
123 }
124 mgmt_ds_status_write_one(vty, ds_ctx);
125
126 return CMD_SUCCESS;
127}
128
ef43a632
CH
129DEFPY(mgmt_commit,
130 mgmt_commit_cmd,
131 "mgmt commit <check|apply|abort>$type",
132 MGMTD_STR
133 "Commit action\n"
134 "Validate the set of config commands\n"
135 "Validate and apply the set of config commands\n"
136 "Abort and drop the set of config commands recently added\n")
137{
138 bool validate_only = type[0] == 'c';
139 bool abort = type[1] == 'b';
140
141 if (vty_mgmt_send_commit_config(vty, validate_only, abort) != 0)
142 return CMD_WARNING_CONFIG_FAILED;
143 return CMD_SUCCESS;
144}
145
146DEFPY(mgmt_set_config_data, mgmt_set_config_data_cmd,
147 "mgmt set-config WORD$path VALUE",
148 MGMTD_STR
149 "Set configuration data\n"
150 "XPath expression specifying the YANG data path\n"
151 "Value of the data to set\n")
152{
153 strlcpy(vty->cfg_changes[0].xpath, path,
154 sizeof(vty->cfg_changes[0].xpath));
155 vty->cfg_changes[0].value = value;
156 vty->cfg_changes[0].operation = NB_OP_CREATE;
157 vty->num_cfg_changes = 1;
158
159 vty->no_implicit_commit = true;
160 vty_mgmt_send_config_data(vty);
161 vty->no_implicit_commit = false;
162 return CMD_SUCCESS;
163}
164
165DEFPY(mgmt_delete_config_data, mgmt_delete_config_data_cmd,
166 "mgmt delete-config WORD$path",
167 MGMTD_STR
168 "Delete configuration data\n"
169 "XPath expression specifying the YANG data path\n")
170{
171
172 strlcpy(vty->cfg_changes[0].xpath, path,
173 sizeof(vty->cfg_changes[0].xpath));
174 vty->cfg_changes[0].value = NULL;
175 vty->cfg_changes[0].operation = NB_OP_DESTROY;
176 vty->num_cfg_changes = 1;
177
178 vty->no_implicit_commit = true;
179 vty_mgmt_send_config_data(vty);
180 vty->no_implicit_commit = false;
181 return CMD_SUCCESS;
182}
183
184DEFPY(show_mgmt_get_config, show_mgmt_get_config_cmd,
185 "show mgmt get-config [candidate|operational|running]$dsname WORD$path",
186 SHOW_STR MGMTD_STR
187 "Get configuration data from a specific configuration datastore\n"
188 "Candidate datastore (default)\n"
189 "Operational datastore\n"
190 "Running datastore\n"
191 "XPath expression specifying the YANG data path\n")
192{
193 const char *xpath_list[VTY_MAXCFGCHANGES] = {0};
194 Mgmtd__DatastoreId datastore = MGMTD_DS_CANDIDATE;
195
196 if (dsname)
197 datastore = mgmt_ds_name2id(dsname);
198
199 xpath_list[0] = path;
200 vty_mgmt_send_get_config(vty, datastore, xpath_list, 1);
201 return CMD_SUCCESS;
202}
203
204DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd,
205 "show mgmt get-data [candidate|operational|running]$dsname WORD$path",
206 SHOW_STR MGMTD_STR
207 "Get data from a specific datastore\n"
208 "Candidate datastore\n"
209 "Operational datastore (default)\n"
210 "Running datastore\n"
211 "XPath expression specifying the YANG data path\n")
212{
213 const char *xpath_list[VTY_MAXCFGCHANGES] = {0};
214 Mgmtd__DatastoreId datastore = MGMTD_DS_OPERATIONAL;
215
216 if (dsname)
217 datastore = mgmt_ds_name2id(dsname);
218
219 xpath_list[0] = path;
220 vty_mgmt_send_get_data(vty, datastore, xpath_list, 1);
221 return CMD_SUCCESS;
222}
223
1c84efe4
CH
224DEFPY(show_mgmt_dump_data,
225 show_mgmt_dump_data_cmd,
ef43a632 226 "show mgmt datastore-contents [candidate|operational|running]$dsname [xpath WORD$path] [file WORD$filepath] <json|xml>$fmt",
1c84efe4
CH
227 SHOW_STR
228 MGMTD_STR
229 "Get Datastore contents from a specific datastore\n"
ef43a632
CH
230 "Candidate datastore (default)\n"
231 "Operational datastore\n"
232 "Running datastore\n"
1c84efe4
CH
233 "XPath expression specifying the YANG data path\n"
234 "XPath string\n"
235 "Dump the contents to a file\n"
236 "Full path of the file\n"
ef43a632
CH
237 "json output\n"
238 "xml output\n")
1c84efe4 239{
1c84efe4 240 struct mgmt_ds_ctx *ds_ctx;
ef43a632 241 Mgmtd__DatastoreId datastore = MGMTD_DS_CANDIDATE;
1c84efe4
CH
242 LYD_FORMAT format = fmt[0] == 'j' ? LYD_JSON : LYD_XML;
243 FILE *f = NULL;
244
ef43a632
CH
245 if (datastore)
246 datastore = mgmt_ds_name2id(dsname);
1c84efe4
CH
247
248 ds_ctx = mgmt_ds_get_ctx_by_id(mm, datastore);
249 if (!ds_ctx) {
250 vty_out(vty, "ERROR: Could not access datastore!\n");
251 return CMD_ERR_NO_MATCH;
252 }
253
254 if (filepath) {
255 f = fopen(filepath, "w");
256 if (!f) {
257 vty_out(vty,
258 "Could not open file pointed by filepath %s\n",
259 filepath);
260 return CMD_SUCCESS;
261 }
262 }
263
264 mgmt_ds_dump_tree(vty, ds_ctx, path, f, format);
265
266 if (f)
267 fclose(f);
268 return CMD_SUCCESS;
269}
270
7d65b7b7
CH
271DEFPY(show_mgmt_map_xpath,
272 show_mgmt_map_xpath_cmd,
273 "show mgmt yang-xpath-subscription WORD$path",
274 SHOW_STR
275 MGMTD_STR
276 "Get YANG Backend Subscription\n"
277 "XPath expression specifying the YANG data path\n")
278{
279 mgmt_be_xpath_subscr_info_write(vty, path);
280 return CMD_SUCCESS;
281}
282
1c84efe4
CH
283DEFPY(mgmt_load_config,
284 mgmt_load_config_cmd,
ef43a632 285 "mgmt load-config WORD$filepath <merge|replace>$type",
1c84efe4
CH
286 MGMTD_STR
287 "Load configuration onto Candidate Datastore\n"
1c84efe4
CH
288 "Full path of the file\n"
289 "Merge configuration with contents of Candidate Datastore\n"
290 "Replace the existing contents of Candidate datastore\n")
291{
ef43a632 292 bool merge = type[0] == 'm' ? true : false;
1c84efe4 293 struct mgmt_ds_ctx *ds_ctx;
ef43a632 294 int ret;
1c84efe4
CH
295
296 if (access(filepath, F_OK) == -1) {
297 vty_out(vty, "ERROR: File %s : %s\n", filepath,
298 strerror(errno));
299 return CMD_ERR_NO_FILE;
300 }
301
302 ds_ctx = mgmt_ds_get_ctx_by_id(mm, MGMTD_DS_CANDIDATE);
303 if (!ds_ctx) {
304 vty_out(vty, "ERROR: Could not access Candidate datastore!\n");
305 return CMD_ERR_NO_MATCH;
306 }
307
1c84efe4
CH
308 ret = mgmt_ds_load_config_from_file(ds_ctx, filepath, merge);
309 if (ret != 0)
310 vty_out(vty, "Error with parsing the file with error code %d\n",
311 ret);
312 return CMD_SUCCESS;
313}
314
315DEFPY(mgmt_save_config,
316 mgmt_save_config_cmd,
ef43a632 317 "mgmt save-config <candidate|running>$dsname WORD$filepath",
1c84efe4
CH
318 MGMTD_STR
319 "Save configuration from datastore\n"
ef43a632
CH
320 "Candidate datastore\n"
321 "Running datastore\n"
1c84efe4
CH
322 "Full path of the file\n")
323{
ef43a632 324 Mgmtd__DatastoreId datastore = mgmt_ds_name2id(dsname);
1c84efe4 325 struct mgmt_ds_ctx *ds_ctx;
1c84efe4
CH
326 FILE *f;
327
1c84efe4
CH
328 ds_ctx = mgmt_ds_get_ctx_by_id(mm, datastore);
329 if (!ds_ctx) {
330 vty_out(vty, "ERROR: Could not access the '%s' datastore!\n",
331 dsname);
332 return CMD_ERR_NO_MATCH;
333 }
334
335 if (!filepath) {
336 vty_out(vty, "ERROR: No file path mentioned!\n");
337 return CMD_ERR_NO_MATCH;
338 }
339
340 f = fopen(filepath, "w");
341 if (!f) {
342 vty_out(vty, "Could not open file pointed by filepath %s\n",
343 filepath);
344 return CMD_SUCCESS;
345 }
346
347 mgmt_ds_dump_tree(vty, ds_ctx, "/", f, LYD_JSON);
348
349 fclose(f);
350
351 return CMD_SUCCESS;
352}
353
74335ceb
YR
354DEFPY(show_mgmt_cmt_hist,
355 show_mgmt_cmt_hist_cmd,
356 "show mgmt commit-history",
357 SHOW_STR
358 MGMTD_STR
359 "Show commit history\n")
360{
361 show_mgmt_cmt_history(vty);
362 return CMD_SUCCESS;
363}
364
365DEFPY(mgmt_rollback,
366 mgmt_rollback_cmd,
367 "mgmt rollback <commit-id WORD$commit | last [(1-10)]$last>",
368 MGMTD_STR
369 "Rollback commits\n"
370 "Rollback to commit ID\n"
371 "Commit-ID\n"
372 "Rollbak n commits\n"
373 "Number of commits\n")
374{
375 if (commit)
376 mgmt_history_rollback_by_id(vty, commit);
377 else
378 mgmt_history_rollback_n(vty, last);
379
380 return CMD_SUCCESS;
381}
382
cfa0facb 383int config_write_mgmt_debug(struct vty *vty);
74335ceb
YR
384static struct cmd_node debug_node = {
385 .name = "debug",
386 .node = DEBUG_NODE,
387 .prompt = "",
388 .config_write = config_write_mgmt_debug,
389};
390
cfa0facb 391static int write_mgmt_debug_helper(struct vty *vty, bool config)
1c84efe4 392{
cfa0facb
CH
393 uint32_t mode = config ? DEBUG_MODE_CONF : DEBUG_MODE_ALL;
394 bool be = DEBUG_MODE_CHECK(&mgmt_debug_be, mode);
395 bool ds = DEBUG_MODE_CHECK(&mgmt_debug_ds, mode);
396 bool fe = DEBUG_MODE_CHECK(&mgmt_debug_fe, mode);
397 bool txn = DEBUG_MODE_CHECK(&mgmt_debug_txn, mode);
83b78f43 398
cfa0facb 399 if (!(be || ds || fe || txn))
1c84efe4 400 return 0;
689e1d44 401
1c84efe4 402 vty_out(vty, "debug mgmt");
cfa0facb 403 if (be)
1c84efe4 404 vty_out(vty, " backend");
cfa0facb 405 if (ds)
1c84efe4 406 vty_out(vty, " datastore");
cfa0facb 407 if (fe)
1c84efe4 408 vty_out(vty, " frontend");
cfa0facb 409 if (txn)
1c84efe4
CH
410 vty_out(vty, " transaction");
411
412 vty_out(vty, "\n");
413
414 return 0;
415}
1c84efe4 416
cfa0facb 417int config_write_mgmt_debug(struct vty *vty)
689e1d44 418{
cfa0facb 419 return write_mgmt_debug_helper(vty, true);
689e1d44
MN
420}
421
cfa0facb 422DEFPY_NOSH(show_debugging_mgmt, show_debugging_mgmt_cmd,
689e1d44
MN
423 "show debugging [mgmt]", SHOW_STR DEBUG_STR "MGMT Information\n")
424{
425 vty_out(vty, "MGMT debugging status:\n");
426
cfa0facb 427 write_mgmt_debug_helper(vty, false);
689e1d44
MN
428
429 cmd_show_lib_debugs(vty);
430
431 return CMD_SUCCESS;
432}
433
434DEFPY(debug_mgmt, debug_mgmt_cmd,
cfa0facb 435 "[no$no] debug mgmt {backend$be|datastore$ds|frontend$fe|transaction$txn}",
689e1d44 436 NO_STR DEBUG_STR MGMTD_STR
cfa0facb 437 "Backend debug\n"
1c84efe4 438 "Datastore debug\n"
cfa0facb 439 "Frontend debug\n"
1c84efe4
CH
440 "Transaction debug\n")
441{
cfa0facb 442 uint32_t mode = DEBUG_NODE2MODE(vty->node);
1c84efe4
CH
443
444 if (be)
cfa0facb 445 DEBUG_MODE_SET(&mgmt_debug_be, mode, !no);
1c84efe4 446 if (ds)
cfa0facb 447 DEBUG_MODE_SET(&mgmt_debug_ds, mode, !no);
1c84efe4 448 if (fe)
cfa0facb 449 DEBUG_MODE_SET(&mgmt_debug_fe, mode, !no);
1c84efe4 450 if (txn)
cfa0facb 451 DEBUG_MODE_SET(&mgmt_debug_txn, mode, !no);
1c84efe4
CH
452
453 return CMD_SUCCESS;
454}
455
8033bf39
CH
456/*
457 * Analog of `frr_config_read_in()`, instead of our config file though we loop
458 * over all daemons that have transitioned to mgmtd, loading their configs
459 */
460static int mgmt_config_pre_hook(struct event_loop *loop)
461{
462 FILE *confp;
463 char *p;
464
465 for (uint i = 0; i < mgmt_daemons_count; i++) {
466 p = asprintfrr(MTYPE_TMP, "%s/%s.conf", frr_sysconfdir,
467 mgmt_daemons[i]);
468 confp = fopen(p, "r");
469 if (confp == NULL) {
470 if (errno != ENOENT)
471 zlog_err("%s: couldn't read config file %s: %s",
472 __func__, p, safe_strerror(errno));
473 } else {
474 zlog_info("mgmtd: reading daemon config from %s", p);
475 vty_read_file(vty_shared_candidate_config, confp);
476 fclose(confp);
477 }
478 XFREE(MTYPE_TMP, p);
479 }
480 return 0;
481}
482
1c84efe4
CH
483void mgmt_vty_init(void)
484{
7d65b7b7
CH
485 /*
486 * Initialize command handling from VTYSH connection.
487 * Call command initialization routines defined by
488 * backend components that are moved to new MGMTD infra
489 * here one by one.
490 */
7d65b7b7
CH
491#if HAVE_STATICD
492 extern void static_vty_init(void);
493 static_vty_init();
7d65b7b7
CH
494#endif
495
8033bf39
CH
496 hook_register(frr_config_pre, mgmt_config_pre_hook);
497
1c84efe4
CH
498 install_node(&debug_node);
499
7d65b7b7
CH
500 install_element(VIEW_NODE, &show_mgmt_be_adapter_cmd);
501 install_element(VIEW_NODE, &show_mgmt_be_xpath_reg_cmd);
ef43a632 502 install_element(VIEW_NODE, &show_mgmt_fe_adapter_cmd);
74335ceb 503 install_element(VIEW_NODE, &show_mgmt_txn_cmd);
1c84efe4 504 install_element(VIEW_NODE, &show_mgmt_ds_cmd);
ef43a632
CH
505 install_element(VIEW_NODE, &show_mgmt_get_config_cmd);
506 install_element(VIEW_NODE, &show_mgmt_get_data_cmd);
1c84efe4 507 install_element(VIEW_NODE, &show_mgmt_dump_data_cmd);
7d65b7b7 508 install_element(VIEW_NODE, &show_mgmt_map_xpath_cmd);
74335ceb 509 install_element(VIEW_NODE, &show_mgmt_cmt_hist_cmd);
1c84efe4 510
ef43a632
CH
511 install_element(CONFIG_NODE, &mgmt_commit_cmd);
512 install_element(CONFIG_NODE, &mgmt_set_config_data_cmd);
513 install_element(CONFIG_NODE, &mgmt_delete_config_data_cmd);
1c84efe4
CH
514 install_element(CONFIG_NODE, &mgmt_load_config_cmd);
515 install_element(CONFIG_NODE, &mgmt_save_config_cmd);
74335ceb 516 install_element(CONFIG_NODE, &mgmt_rollback_cmd);
1c84efe4
CH
517
518 install_element(VIEW_NODE, &debug_mgmt_cmd);
519 install_element(CONFIG_NODE, &debug_mgmt_cmd);
520
74335ceb
YR
521 /* Enable view */
522 install_element(ENABLE_NODE, &mgmt_performance_measurement_cmd);
523 install_element(ENABLE_NODE, &mgmt_reset_performance_stats_cmd);
524
689e1d44
MN
525 install_element(ENABLE_NODE, &show_debugging_mgmt_cmd);
526
cfa0facb 527 mgmt_fe_client_lib_vty_init();
1c84efe4 528 /*
74335ceb 529 * TODO: Register and handlers for auto-completion here.
1c84efe4
CH
530 */
531}