]> git.proxmox.com Git - mirror_frr.git/blob - mgmtd/mgmt_vty.c
Merge pull request #13435 from mjstapp/fix_pim_cpp_notice
[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 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 write_mgmt_debug_helper(struct vty *vty, bool config)
392 {
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);
398
399 if (!(be || ds || fe || txn))
400 return 0;
401
402 vty_out(vty, "debug mgmt");
403 if (be)
404 vty_out(vty, " backend");
405 if (ds)
406 vty_out(vty, " datastore");
407 if (fe)
408 vty_out(vty, " frontend");
409 if (txn)
410 vty_out(vty, " transaction");
411
412 vty_out(vty, "\n");
413
414 return 0;
415 }
416
417 int config_write_mgmt_debug(struct vty *vty)
418 {
419 return write_mgmt_debug_helper(vty, true);
420 }
421
422 DEFPY_NOSH(show_debugging_mgmt, show_debugging_mgmt_cmd,
423 "show debugging [mgmt]", SHOW_STR DEBUG_STR "MGMT Information\n")
424 {
425 vty_out(vty, "MGMT debugging status:\n");
426
427 write_mgmt_debug_helper(vty, false);
428
429 cmd_show_lib_debugs(vty);
430
431 return CMD_SUCCESS;
432 }
433
434 DEFPY(debug_mgmt, debug_mgmt_cmd,
435 "[no$no] debug mgmt {backend$be|datastore$ds|frontend$fe|transaction$txn}",
436 NO_STR DEBUG_STR MGMTD_STR
437 "Backend debug\n"
438 "Datastore debug\n"
439 "Frontend debug\n"
440 "Transaction debug\n")
441 {
442 uint32_t mode = DEBUG_NODE2MODE(vty->node);
443
444 if (be)
445 DEBUG_MODE_SET(&mgmt_debug_be, mode, !no);
446 if (ds)
447 DEBUG_MODE_SET(&mgmt_debug_ds, mode, !no);
448 if (fe)
449 DEBUG_MODE_SET(&mgmt_debug_fe, mode, !no);
450 if (txn)
451 DEBUG_MODE_SET(&mgmt_debug_txn, mode, !no);
452
453 return CMD_SUCCESS;
454 }
455
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 */
460 static 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
483 void mgmt_vty_init(void)
484 {
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 */
491 #if HAVE_STATICD
492 extern void static_vty_init(void);
493 static_vty_init();
494 #endif
495
496 hook_register(frr_config_pre, mgmt_config_pre_hook);
497
498 install_node(&debug_node);
499
500 install_element(VIEW_NODE, &show_mgmt_be_adapter_cmd);
501 install_element(VIEW_NODE, &show_mgmt_be_xpath_reg_cmd);
502 install_element(VIEW_NODE, &show_mgmt_fe_adapter_cmd);
503 install_element(VIEW_NODE, &show_mgmt_txn_cmd);
504 install_element(VIEW_NODE, &show_mgmt_ds_cmd);
505 install_element(VIEW_NODE, &show_mgmt_get_config_cmd);
506 install_element(VIEW_NODE, &show_mgmt_get_data_cmd);
507 install_element(VIEW_NODE, &show_mgmt_dump_data_cmd);
508 install_element(VIEW_NODE, &show_mgmt_map_xpath_cmd);
509 install_element(VIEW_NODE, &show_mgmt_cmt_hist_cmd);
510
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);
514 install_element(CONFIG_NODE, &mgmt_load_config_cmd);
515 install_element(CONFIG_NODE, &mgmt_save_config_cmd);
516 install_element(CONFIG_NODE, &mgmt_rollback_cmd);
517
518 install_element(VIEW_NODE, &debug_mgmt_cmd);
519 install_element(CONFIG_NODE, &debug_mgmt_cmd);
520
521 /* Enable view */
522 install_element(ENABLE_NODE, &mgmt_performance_measurement_cmd);
523 install_element(ENABLE_NODE, &mgmt_reset_performance_stats_cmd);
524
525 install_element(ENABLE_NODE, &show_debugging_mgmt_cmd);
526
527 mgmt_fe_client_lib_vty_init();
528 /*
529 * TODO: Register and handlers for auto-completion here.
530 */
531 }