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