summaryrefslogtreecommitdiff
path: root/mgmtd/mgmt_vty.c
diff options
context:
space:
mode:
authorChristian Hopps <chopps@labn.net>2023-03-08 17:22:09 -0500
committerChristian Hopps <chopps@labn.net>2023-03-21 22:08:32 -0400
commit1c84efe4fa8585df58a9b53459f94c47934f0786 (patch)
tree21609ad9048500a6b23c38ce373506d5d6aa6ac3 /mgmtd/mgmt_vty.c
parented851381b578fda5c313ea0cb6a2e9d3fb017cce (diff)
mgmtd: Bringup MGMTD daemon and datastore module support
Features added in this commit: 1. Bringup/shutdown new management daemon 'mgmtd' along with FRR. 2. Support for Startup, Candidate and Running DBs. 3. Lock/Unlock DS feature using pthread lock. 4. Load config from a JSON file onto candidate DS. 5. Save config to a JSON file from running/candidate DS. 6. Dump candidate or running DS contents on the terminal or a file in JSON/XML format. 7. Maintaining commit history (Full rollback support to be added in future commits). 8. Addition of debug commands. Co-authored-by: Yash Ranjan <ranjany@vmware.com> Co-authored-by: Abhinay Ramesh <rabhinay@vmware.com> Co-authored-by: Ujwal P <ujwalp@vmware.com> Signed-off-by: Pushpasis Sarkar <pushpasis@gmail.com>
Diffstat (limited to 'mgmtd/mgmt_vty.c')
-rw-r--r--mgmtd/mgmt_vty.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c
new file mode 100644
index 0000000000..3070b754fa
--- /dev/null
+++ b/mgmtd/mgmt_vty.c
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MGMTD VTY Interface
+ *
+ * Copyright (C) 2021 Vmware, Inc.
+ * Pushpasis Sarkar <spushpasis@vmware.com>
+ */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "json.h"
+#include "mgmtd/mgmt.h"
+#include "mgmtd/mgmt_ds.h"
+
+#ifndef VTYSH_EXTRACT_PL
+#include "mgmtd/mgmt_vty_clippy.c"
+#endif
+
+DEFPY(show_mgmt_ds,
+ show_mgmt_ds_cmd,
+ "show mgmt datastore [all|candidate|operational|running]$dsname",
+ SHOW_STR
+ MGMTD_STR
+ MGMTD_DS_STR
+ "All datastores (default)\n"
+ "Candidate datastore\n"
+ "Operational datastore\n"
+ "Running datastore\n")
+{
+ struct mgmt_ds_ctx *ds_ctx;
+
+ if (!dsname || dsname[0] == 'a') {
+ mgmt_ds_status_write(vty);
+ return CMD_SUCCESS;
+ }
+ ds_ctx = mgmt_ds_get_ctx_by_id(mm, mgmt_ds_name2id(dsname));
+ if (!ds_ctx) {
+ vty_out(vty, "ERROR: Could not access %s datastore!\n", dsname);
+ return CMD_ERR_NO_MATCH;
+ }
+ mgmt_ds_status_write_one(vty, ds_ctx);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(show_mgmt_dump_data,
+ show_mgmt_dump_data_cmd,
+ "show mgmt datastore-contents WORD$dsname [xpath WORD$path] [file WORD$filepath] <json|xml>$fmt",
+ SHOW_STR
+ MGMTD_STR
+ "Get Datastore contents from a specific datastore\n"
+ "<candidate | running | operational>\n"
+ "XPath expression specifying the YANG data path\n"
+ "XPath string\n"
+ "Dump the contents to a file\n"
+ "Full path of the file\n"
+ "json|xml\n")
+{
+ enum mgmt_datastore_id datastore = MGMTD_DS_CANDIDATE;
+ struct mgmt_ds_ctx *ds_ctx;
+ LYD_FORMAT format = fmt[0] == 'j' ? LYD_JSON : LYD_XML;
+ FILE *f = NULL;
+
+ datastore = mgmt_ds_name2id(dsname);
+
+ if (datastore == MGMTD_DS_NONE) {
+ vty_out(vty,
+ "DS Name %s does not matches any existing datastore\n",
+ dsname);
+ return CMD_SUCCESS;
+ }
+
+ ds_ctx = mgmt_ds_get_ctx_by_id(mm, datastore);
+ if (!ds_ctx) {
+ vty_out(vty, "ERROR: Could not access datastore!\n");
+ return CMD_ERR_NO_MATCH;
+ }
+
+ if (filepath) {
+ f = fopen(filepath, "w");
+ if (!f) {
+ vty_out(vty,
+ "Could not open file pointed by filepath %s\n",
+ filepath);
+ return CMD_SUCCESS;
+ }
+ }
+
+ mgmt_ds_dump_tree(vty, ds_ctx, path, f, format);
+
+ if (f)
+ fclose(f);
+ return CMD_SUCCESS;
+}
+
+DEFPY(mgmt_load_config,
+ mgmt_load_config_cmd,
+ "mgmt load-config file WORD$filepath <merge|replace>",
+ MGMTD_STR
+ "Load configuration onto Candidate Datastore\n"
+ "Read the configuration from a file\n"
+ "Full path of the file\n"
+ "Merge configuration with contents of Candidate Datastore\n"
+ "Replace the existing contents of Candidate datastore\n")
+{
+ bool merge = false;
+ int idx_merge = 4;
+ int ret;
+ struct mgmt_ds_ctx *ds_ctx;
+
+ if (access(filepath, F_OK) == -1) {
+ vty_out(vty, "ERROR: File %s : %s\n", filepath,
+ strerror(errno));
+ return CMD_ERR_NO_FILE;
+ }
+
+ ds_ctx = mgmt_ds_get_ctx_by_id(mm, MGMTD_DS_CANDIDATE);
+ if (!ds_ctx) {
+ vty_out(vty, "ERROR: Could not access Candidate datastore!\n");
+ return CMD_ERR_NO_MATCH;
+ }
+
+ if (strncmp(argv[idx_merge]->arg, "merge", sizeof("merge")) == 0)
+ merge = true;
+ else if (strncmp(argv[idx_merge]->arg, "replace", sizeof("replace"))
+ == 0)
+ merge = false;
+ else {
+ vty_out(vty, "Chosen option: %s not valid\n",
+ argv[idx_merge]->arg);
+ return CMD_SUCCESS;
+ }
+
+ ret = mgmt_ds_load_config_from_file(ds_ctx, filepath, merge);
+ if (ret != 0)
+ vty_out(vty, "Error with parsing the file with error code %d\n",
+ ret);
+ return CMD_SUCCESS;
+}
+
+DEFPY(mgmt_save_config,
+ mgmt_save_config_cmd,
+ "mgmt save-config datastore WORD$dsname file WORD$filepath",
+ MGMTD_STR
+ "Save configuration from datastore\n"
+ "Datastore keyword\n"
+ "<candidate|running>\n"
+ "Write the configuration to a file\n"
+ "Full path of the file\n")
+{
+ struct mgmt_ds_ctx *ds_ctx;
+ enum mgmt_datastore_id datastore;
+ FILE *f;
+
+ datastore = mgmt_ds_name2id(dsname);
+
+ if (datastore == MGMTD_DS_NONE) {
+ vty_out(vty,
+ "DS Name %s does not matches any existing datastore\n",
+ dsname);
+ return CMD_SUCCESS;
+ }
+
+ if (datastore != MGMTD_DS_CANDIDATE && datastore != MGMTD_DS_RUNNING) {
+ vty_out(vty, "DS Name %s is not a configuration datastore\n",
+ dsname);
+ return CMD_SUCCESS;
+ }
+
+ ds_ctx = mgmt_ds_get_ctx_by_id(mm, datastore);
+ if (!ds_ctx) {
+ vty_out(vty, "ERROR: Could not access the '%s' datastore!\n",
+ dsname);
+ return CMD_ERR_NO_MATCH;
+ }
+
+ if (!filepath) {
+ vty_out(vty, "ERROR: No file path mentioned!\n");
+ return CMD_ERR_NO_MATCH;
+ }
+
+ f = fopen(filepath, "w");
+ if (!f) {
+ vty_out(vty, "Could not open file pointed by filepath %s\n",
+ filepath);
+ return CMD_SUCCESS;
+ }
+
+ mgmt_ds_dump_tree(vty, ds_ctx, "/", f, LYD_JSON);
+
+ fclose(f);
+
+ return CMD_SUCCESS;
+}
+
+static int config_write_mgmt_debug(struct vty *vty)
+{
+ int n = mgmt_debug_be + mgmt_debug_fe + mgmt_debug_ds + mgmt_debug_txn;
+ if (!n)
+ return 0;
+ if (n == 4) {
+ vty_out(vty, "debug mgmt all\n");
+ return 0;
+ }
+
+ vty_out(vty, "debug mgmt");
+ if (mgmt_debug_be)
+ vty_out(vty, " backend");
+ if (mgmt_debug_ds)
+ vty_out(vty, " datastore");
+ if (mgmt_debug_fe)
+ vty_out(vty, " frontend");
+ if (mgmt_debug_txn)
+ vty_out(vty, " transaction");
+
+ vty_out(vty, "\n");
+
+ return 0;
+}
+static struct cmd_node debug_node = {
+ .name = "debug",
+ .node = DEBUG_NODE,
+ .prompt = "",
+ .config_write = config_write_mgmt_debug,
+};
+
+DEFPY(debug_mgmt,
+ debug_mgmt_cmd,
+ "[no$no] debug mgmt <all$all|{backend$be|datastore$ds|frontend$fe|transaction$txn}>",
+ NO_STR
+ DEBUG_STR
+ MGMTD_STR
+ "All debug\n"
+ "Back-end debug\n"
+ "Datastore debug\n"
+ "Front-end debug\n"
+ "Transaction debug\n")
+{
+ bool set = !no;
+ if (all)
+ be = fe = ds = txn = set ? all : NULL;
+
+ if (be)
+ mgmt_debug_be = set;
+ if (ds)
+ mgmt_debug_ds = set;
+ if (fe)
+ mgmt_debug_fe = set;
+ if (txn)
+ mgmt_debug_txn = set;
+
+ return CMD_SUCCESS;
+}
+
+void mgmt_vty_init(void)
+{
+ install_node(&debug_node);
+
+ install_element(VIEW_NODE, &show_mgmt_ds_cmd);
+ install_element(VIEW_NODE, &show_mgmt_dump_data_cmd);
+
+ install_element(CONFIG_NODE, &mgmt_load_config_cmd);
+ install_element(CONFIG_NODE, &mgmt_save_config_cmd);
+
+ install_element(VIEW_NODE, &debug_mgmt_cmd);
+ install_element(CONFIG_NODE, &debug_mgmt_cmd);
+
+ /*
+ * TODO: Register and handlers for auto-completion here (if any).
+ */
+}