summaryrefslogtreecommitdiff
path: root/lib/northbound_cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/northbound_cli.c')
-rw-r--r--lib/northbound_cli.c163
1 files changed, 151 insertions, 12 deletions
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index 01f577fd5b..2cacc6b1dc 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -56,10 +56,30 @@ static void vty_show_libyang_errors(struct vty *vty, struct ly_ctx *ly_ctx)
ly_err_clean(ly_ctx, NULL);
}
-int nb_cli_cfg_change(struct vty *vty, char *xpath_base,
- struct cli_config_change changes[], size_t size)
+void nb_cli_enqueue_change(struct vty *vty, const char *xpath,
+ enum nb_operation operation, const char *value)
+{
+ struct vty_cfg_change *change;
+
+ if (vty->num_cfg_changes == VTY_MAXCFGCHANGES) {
+ /* Not expected to happen. */
+ vty_out(vty,
+ "%% Exceeded the maximum number of changes (%u) for a single command\n\n",
+ VTY_MAXCFGCHANGES);
+ return;
+ }
+
+ change = &vty->cfg_changes[vty->num_cfg_changes++];
+ change->xpath = xpath;
+ change->operation = operation;
+ change->value = value;
+}
+
+int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt, ...)
{
struct nb_config *candidate_transitory;
+ char xpath_base[XPATH_MAXLEN];
+ va_list ap;
bool error = false;
int ret;
@@ -72,9 +92,14 @@ int nb_cli_cfg_change(struct vty *vty, char *xpath_base,
*/
candidate_transitory = nb_config_dup(vty->candidate_config);
+ /* Parse the base XPath format string. */
+ va_start(ap, xpath_base_fmt);
+ vsnprintf(xpath_base, sizeof(xpath_base), xpath_base_fmt, ap);
+ va_end(ap);
+
/* Edit candidate configuration. */
- for (size_t i = 0; i < size; i++) {
- struct cli_config_change *change = &changes[i];
+ for (size_t i = 0; i < vty->num_cfg_changes; i++) {
+ struct vty_cfg_change *change = &vty->cfg_changes[i];
struct nb_node *nb_node;
char xpath[XPATH_MAXLEN];
struct yang_data *data;
@@ -82,19 +107,21 @@ int nb_cli_cfg_change(struct vty *vty, char *xpath_base,
/* Handle relative XPaths. */
memset(xpath, 0, sizeof(xpath));
if (vty->xpath_index > 0
- && ((xpath_base && xpath_base[0] == '.')
+ && ((xpath_base_fmt && xpath_base[0] == '.')
|| change->xpath[0] == '.'))
strlcpy(xpath, VTY_CURR_XPATH, sizeof(xpath));
- if (xpath_base) {
+ if (xpath_base_fmt) {
if (xpath_base[0] == '.')
- xpath_base++;
- strlcat(xpath, xpath_base, sizeof(xpath));
+ strlcat(xpath, xpath_base + 1, sizeof(xpath));
+ else
+ strlcat(xpath, xpath_base, sizeof(xpath));
}
if (change->xpath[0] == '.')
strlcat(xpath, change->xpath + 1, sizeof(xpath));
else
strlcpy(xpath, change->xpath, sizeof(xpath));
+ /* Find the northbound node associated to the data path. */
nb_node = nb_node_find(xpath);
if (!nb_node) {
flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
@@ -359,7 +386,7 @@ static int nb_cli_show_config_libyang(struct vty *vty, LYD_FORMAT format,
{
struct lyd_node *dnode;
char *strp;
- int options;
+ int options = 0;
dnode = yang_dnode_dup(config->dnode);
if (translator
@@ -371,11 +398,11 @@ static int nb_cli_show_config_libyang(struct vty *vty, LYD_FORMAT format,
return CMD_WARNING;
}
- options = LYP_FORMAT | LYP_WITHSIBLINGS;
+ SET_FLAG(options, LYP_FORMAT | LYP_WITHSIBLINGS);
if (with_defaults)
- options |= LYP_WD_ALL;
+ SET_FLAG(options, LYP_WD_ALL);
else
- options |= LYP_WD_TRIM;
+ SET_FLAG(options, LYP_WD_TRIM);
if (lyd_print_mem(&strp, dnode, format, options) == 0 && strp) {
vty_out(vty, "%s", strp);
@@ -1071,6 +1098,117 @@ DEFPY (show_config_transaction,
#endif /* HAVE_CONFIG_ROLLBACKS */
}
+static int nb_cli_oper_data_cb(const struct lys_node *snode,
+ struct yang_translator *translator,
+ struct yang_data *data, void *arg)
+{
+ struct lyd_node *dnode = arg;
+ struct ly_ctx *ly_ctx;
+
+ if (translator) {
+ int ret;
+
+ ret = yang_translate_xpath(translator,
+ YANG_TRANSLATE_FROM_NATIVE,
+ data->xpath, sizeof(data->xpath));
+ switch (ret) {
+ case YANG_TRANSLATE_SUCCESS:
+ break;
+ case YANG_TRANSLATE_NOTFOUND:
+ goto exit;
+ case YANG_TRANSLATE_FAILURE:
+ goto error;
+ }
+
+ ly_ctx = translator->ly_ctx;
+ } else
+ ly_ctx = ly_native_ctx;
+
+ ly_errno = 0;
+ dnode = lyd_new_path(dnode, ly_ctx, data->xpath, (void *)data->value, 0,
+ LYD_PATH_OPT_UPDATE);
+ if (!dnode && ly_errno) {
+ flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed",
+ __func__);
+ goto error;
+ }
+
+exit:
+ yang_data_free(data);
+ return NB_OK;
+
+error:
+ yang_data_free(data);
+ return NB_ERR;
+}
+
+DEFPY (show_yang_operational_data,
+ show_yang_operational_data_cmd,
+ "show yang operational-data XPATH$xpath\
+ [{\
+ format <json$json|xml$xml>\
+ |translate WORD$translator_family\
+ }]",
+ SHOW_STR
+ "YANG information\n"
+ "Show YANG operational data\n"
+ "XPath expression specifying the YANG data path\n"
+ "Set the output format\n"
+ "JavaScript Object Notation\n"
+ "Extensible Markup Language\n"
+ "Translate operational data\n"
+ "YANG module translator\n")
+{
+ LYD_FORMAT format;
+ struct yang_translator *translator = NULL;
+ struct ly_ctx *ly_ctx;
+ struct lyd_node *dnode;
+ char *strp;
+
+ if (xml)
+ format = LYD_XML;
+ else
+ format = LYD_JSON;
+
+ if (translator_family) {
+ translator = yang_translator_find(translator_family);
+ if (!translator) {
+ vty_out(vty, "%% Module translator \"%s\" not found\n",
+ translator_family);
+ return CMD_WARNING;
+ }
+
+ ly_ctx = translator->ly_ctx;
+ } else
+ ly_ctx = ly_native_ctx;
+
+ /* Obtain data. */
+ dnode = yang_dnode_new(ly_ctx, false);
+ if (nb_oper_data_iterate(xpath, translator, 0, nb_cli_oper_data_cb,
+ dnode)
+ != NB_OK) {
+ vty_out(vty, "%% Failed to fetch operational data.\n");
+ yang_dnode_free(dnode);
+ return CMD_WARNING;
+ }
+ lyd_validate(&dnode, LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB, ly_ctx);
+
+ /* Display the data. */
+ if (lyd_print_mem(&strp, dnode, format,
+ LYP_FORMAT | LYP_WITHSIBLINGS | LYP_WD_ALL)
+ != 0
+ || !strp) {
+ vty_out(vty, "%% Failed to display operational data.\n");
+ yang_dnode_free(dnode);
+ return CMD_WARNING;
+ }
+ vty_out(vty, "%s", strp);
+ free(strp);
+ yang_dnode_free(dnode);
+
+ return CMD_SUCCESS;
+}
+
DEFPY (show_yang_module,
show_yang_module_cmd,
"show yang module [module-translator WORD$translator_family]",
@@ -1410,6 +1548,7 @@ void nb_cli_init(void)
/* Other commands. */
install_element(CONFIG_NODE, &yang_module_translator_load_cmd);
install_element(CONFIG_NODE, &yang_module_translator_unload_cmd);
+ install_element(ENABLE_NODE, &show_yang_operational_data_cmd);
install_element(ENABLE_NODE, &show_yang_module_cmd);
install_element(ENABLE_NODE, &show_yang_module_detail_cmd);
install_element(ENABLE_NODE, &show_yang_module_translator_cmd);