]> git.proxmox.com Git - mirror_frr.git/blob - mgmtd/mgmt_vty.c
lib: convert if_rmap config output to northbound
[mirror_frr.git] / mgmtd / mgmt_vty.c
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"
13 #include "northbound_cli.h"
14
15 #include "mgmtd/mgmt.h"
16 #include "mgmtd/mgmt_be_server.h"
17 #include "mgmtd/mgmt_be_adapter.h"
18 #include "mgmtd/mgmt_fe_server.h"
19 #include "mgmtd/mgmt_fe_adapter.h"
20 #include "mgmtd/mgmt_ds.h"
21 #include "mgmtd/mgmt_history.h"
22
23 #include "mgmtd/mgmt_vty_clippy.c"
24
25 DEFPY(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
38 DEFPY(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
50 DEFPY(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 }
62
63 DEFPY_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
78 DEFPY(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
89 DEFPY(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
102 DEFPY(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
129 DEFPY(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
146 DEFPY(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
165 DEFPY(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
184 DEFPY(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
204 DEFPY(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
224 DEFPY(show_mgmt_dump_data,
225 show_mgmt_dump_data_cmd,
226 "show mgmt datastore-contents [candidate|operational|running]$dsname [xpath WORD$path] [file WORD$filepath] <json|xml>$fmt",
227 SHOW_STR
228 MGMTD_STR
229 "Get Datastore contents from a specific datastore\n"
230 "Candidate datastore (default)\n"
231 "Operational datastore\n"
232 "Running datastore\n"
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"
237 "json output\n"
238 "xml output\n")
239 {
240 struct mgmt_ds_ctx *ds_ctx;
241 Mgmtd__DatastoreId datastore = MGMTD_DS_CANDIDATE;
242 LYD_FORMAT format = fmt[0] == 'j' ? LYD_JSON : LYD_XML;
243 FILE *f = NULL;
244
245 if (datastore)
246 datastore = mgmt_ds_name2id(dsname);
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
271 DEFPY(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
283 DEFPY(mgmt_load_config,
284 mgmt_load_config_cmd,
285 "mgmt load-config WORD$filepath <merge|replace>$type",
286 MGMTD_STR
287 "Load configuration onto Candidate Datastore\n"
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 {
292 bool merge = type[0] == 'm' ? true : false;
293 struct mgmt_ds_ctx *ds_ctx;
294 int ret;
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
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
315 DEFPY(mgmt_save_config,
316 mgmt_save_config_cmd,
317 "mgmt save-config <candidate|running>$dsname WORD$filepath",
318 MGMTD_STR
319 "Save configuration from datastore\n"
320 "Candidate datastore\n"
321 "Running datastore\n"
322 "Full path of the file\n")
323 {
324 Mgmtd__DatastoreId datastore = mgmt_ds_name2id(dsname);
325 struct mgmt_ds_ctx *ds_ctx;
326 FILE *f;
327
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
354 DEFPY(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
365 DEFPY(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
383 static int config_write_mgmt_debug(struct vty *vty);
384 static struct cmd_node debug_node = {
385 .name = "debug",
386 .node = DEBUG_NODE,
387 .prompt = "",
388 .config_write = config_write_mgmt_debug,
389 };
390
391 static int config_write_mgmt_debug_helper(struct vty *vty, bool config)
392 {
393 int n = mgmt_debug_be + mgmt_debug_fe + mgmt_debug_ds + mgmt_debug_txn;
394
395 if (!n)
396 return 0;
397
398 if (config && mgmt_debug_be && mgmt_debug_fe && mgmt_debug_ds &&
399 mgmt_debug_txn) {
400 vty_out(vty, "debug mgmt all\n");
401 return 0;
402 }
403
404 vty_out(vty, "debug mgmt");
405 if (mgmt_debug_be)
406 vty_out(vty, " backend");
407 if (mgmt_debug_ds)
408 vty_out(vty, " datastore");
409 if (mgmt_debug_fe)
410 vty_out(vty, " frontend");
411 if (mgmt_debug_txn)
412 vty_out(vty, " transaction");
413
414 vty_out(vty, "\n");
415
416 return 0;
417 }
418
419 static int config_write_mgmt_debug(struct vty *vty)
420 {
421 return config_write_mgmt_debug_helper(vty, true);
422 }
423
424 DEFUN_NOSH(show_debugging_mgmt, show_debugging_mgmt_cmd,
425 "show debugging [mgmt]", SHOW_STR DEBUG_STR "MGMT Information\n")
426 {
427 vty_out(vty, "MGMT debugging status:\n");
428
429 config_write_mgmt_debug_helper(vty, false);
430
431 cmd_show_lib_debugs(vty);
432
433 return CMD_SUCCESS;
434 }
435
436 DEFPY(debug_mgmt, debug_mgmt_cmd,
437 "[no$no] debug mgmt <all$all|{backend$be|datastore$ds|frontend$fe|transaction$txn}>",
438 NO_STR DEBUG_STR MGMTD_STR
439 "All debug\n"
440 "Back-end debug\n"
441 "Datastore debug\n"
442 "Front-end debug\n"
443 "Transaction debug\n")
444 {
445 bool set = !no;
446
447 if (all)
448 be = fe = ds = txn = set ? all : NULL;
449
450 if (be)
451 mgmt_debug_be = set;
452 if (ds)
453 mgmt_debug_ds = set;
454 if (fe)
455 mgmt_debug_fe = set;
456 if (txn)
457 mgmt_debug_txn = set;
458
459 return CMD_SUCCESS;
460 }
461
462 /*
463 * Analog of `frr_config_read_in()`, instead of our config file though we loop
464 * over all daemons that have transitioned to mgmtd, loading their configs
465 */
466 static int mgmt_config_pre_hook(struct event_loop *loop)
467 {
468 FILE *confp;
469 char *p;
470
471 for (uint i = 0; i < mgmt_daemons_count; i++) {
472 p = asprintfrr(MTYPE_TMP, "%s/%s.conf", frr_sysconfdir,
473 mgmt_daemons[i]);
474 confp = fopen(p, "r");
475 if (confp == NULL) {
476 if (errno != ENOENT)
477 zlog_err("%s: couldn't read config file %s: %s",
478 __func__, p, safe_strerror(errno));
479 } else {
480 zlog_info("mgmtd: reading daemon config from %s", p);
481 vty_read_file(vty_shared_candidate_config, confp);
482 fclose(confp);
483 }
484 XFREE(MTYPE_TMP, p);
485 }
486 return 0;
487 }
488
489 void mgmt_vty_init(void)
490 {
491 /*
492 * Initialize command handling from VTYSH connection.
493 * Call command initialization routines defined by
494 * backend components that are moved to new MGMTD infra
495 * here one by one.
496 */
497 #if HAVE_STATICD
498 extern void static_vty_init(void);
499 static_vty_init();
500 #endif
501
502 hook_register(frr_config_pre, mgmt_config_pre_hook);
503
504 install_node(&debug_node);
505
506 install_element(VIEW_NODE, &show_mgmt_be_adapter_cmd);
507 install_element(VIEW_NODE, &show_mgmt_be_xpath_reg_cmd);
508 install_element(VIEW_NODE, &show_mgmt_fe_adapter_cmd);
509 install_element(VIEW_NODE, &show_mgmt_txn_cmd);
510 install_element(VIEW_NODE, &show_mgmt_ds_cmd);
511 install_element(VIEW_NODE, &show_mgmt_get_config_cmd);
512 install_element(VIEW_NODE, &show_mgmt_get_data_cmd);
513 install_element(VIEW_NODE, &show_mgmt_dump_data_cmd);
514 install_element(VIEW_NODE, &show_mgmt_map_xpath_cmd);
515 install_element(VIEW_NODE, &show_mgmt_cmt_hist_cmd);
516
517 install_element(CONFIG_NODE, &mgmt_commit_cmd);
518 install_element(CONFIG_NODE, &mgmt_set_config_data_cmd);
519 install_element(CONFIG_NODE, &mgmt_delete_config_data_cmd);
520 install_element(CONFIG_NODE, &mgmt_load_config_cmd);
521 install_element(CONFIG_NODE, &mgmt_save_config_cmd);
522 install_element(CONFIG_NODE, &mgmt_rollback_cmd);
523
524 install_element(VIEW_NODE, &debug_mgmt_cmd);
525 install_element(CONFIG_NODE, &debug_mgmt_cmd);
526
527 /* Enable view */
528 install_element(ENABLE_NODE, &mgmt_performance_measurement_cmd);
529 install_element(ENABLE_NODE, &mgmt_reset_performance_stats_cmd);
530
531 install_element(ENABLE_NODE, &show_debugging_mgmt_cmd);
532
533 /*
534 * TODO: Register and handlers for auto-completion here.
535 */
536 }