From f0bd103e7977ca98a7c4b35d8422405287f23919 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Sun, 6 Oct 2024 09:18:24 +0200 Subject: [PATCH] Added new DOMAIN level in YANG spec structure --- apps/backend/backend_client.c | 29 ++++--- apps/backend/backend_main.c | 4 +- apps/cli/cli_generate.c | 33 ++++++-- apps/cli/cli_generate.h | 4 +- apps/cli/cli_main.c | 2 +- apps/netconf/netconf_main.c | 2 +- apps/restconf/restconf_main_fcgi.c | 2 +- apps/restconf/restconf_main_native.c | 2 +- apps/snmp/snmp_main.c | 2 +- lib/clixon/clixon_yang.h | 9 +- lib/src/clixon_data.c | 24 ++++-- lib/src/clixon_datastore_read.c | 2 +- lib/src/clixon_options.c | 2 +- lib/src/clixon_yang.c | 119 +++++++++++++++++++++++---- lib/src/clixon_yang_schema_mount.c | 27 ++++-- test/test_autocli_grouping.sh | 4 +- test/test_nacm_mount.sh | 2 +- 17 files changed, 201 insertions(+), 68 deletions(-) diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c index eb7152b7..f253d463 100644 --- a/apps/backend/backend_client.c +++ b/apps/backend/backend_client.c @@ -1419,20 +1419,22 @@ from_client_stats(clixon_handle h, { int retval = -1; uint64_t nr; - yang_stmt *ym; char *str; int modules = 0; - yang_stmt *yspec; + yang_stmt *yspec0; yang_stmt *ymounts; yang_stmt *ydomain; + yang_stmt *yspec; + yang_stmt *ymodule; cxobj *xt = NULL; - char *name; + char *domain; int inext; int inext2; + int inext3; if ((str = xml_find_body(xe, "modules")) != NULL) modules = strcmp(str, "true") == 0; - yspec = clicon_dbspec_yang(h); + yspec0 = clicon_dbspec_yang(h); cprintf(cbret, "", NETCONF_BASE_NAMESPACE); cprintf(cbret, "", CLIXON_LIB_NS); nr=0; @@ -1447,7 +1449,7 @@ from_client_stats(clixon_handle h, goto done; if (clixon_stats_datastore_get(h, "candidate", cbret) < 0) goto done; - if (if_feature(yspec, "ietf-netconf", "startup")) + if (if_feature(yspec0, "ietf-netconf", "startup")) if (clixon_stats_datastore_get(h, "startup", cbret) < 0) goto done; cprintf(cbret, ""); @@ -1458,19 +1460,22 @@ from_client_stats(clixon_handle h, cprintf(cbret, "", CLIXON_LIB_NS); inext = 0; while ((ydomain = yn_iter(ymounts, &inext)) != NULL) { - name = yang_argument_get(ydomain); + domain = yang_argument_get(ydomain); /* per module-set, first configuration, then main dbspec, then mountpoints */ cprintf(cbret, ""); - cprintf(cbret, "%s", name); + cprintf(cbret, "%s", domain); if (clixon_stats_module_get(h, ydomain, cbret) < 0) goto done; if (modules){ inext2 = 0; - while ((ym = yn_iter(ydomain, &inext2)) != NULL) { - cprintf(cbret, "%s", yang_argument_get(ym)); - if (clixon_stats_module_get(h, ym, cbret) < 0) - goto done; - cprintf(cbret, ""); + while ((yspec = yn_iter(ydomain, &inext2)) != NULL) { + inext3 = 0; + while ((ymodule = yn_iter(yspec, &inext3)) != NULL) { + cprintf(cbret, "%s", yang_argument_get(ymodule)); + if (clixon_stats_module_get(h, ymodule, cbret) < 0) + goto done; + cprintf(cbret, ""); + } } } cprintf(cbret, ""); diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c index d743943f..20cc8537 100644 --- a/apps/backend/backend_main.c +++ b/apps/backend/backend_main.c @@ -221,7 +221,7 @@ nacm_load_external(clixon_handle h) clixon_err(OE_UNIX, errno, "configure file: %s", filename); return -1; } - if ((yspec = yspec_new(h, YANG_NACM_TOP)) == NULL) + if ((yspec = yspec_new1(h, YANG_DOMAIN_TOP, YANG_NACM_TOP)) == NULL) goto done; if (yang_spec_parse_module(h, "ietf-netconf-acm", NULL, yspec) < 0) goto done; @@ -831,7 +831,7 @@ main(int argc, } yang_start(h); /* Create top-level data yangs */ - if ((yspec = yspec_new(h, YANG_DATA_TOP)) == NULL) + if ((yspec = yspec_new1(h, YANG_DOMAIN_TOP, YANG_DATA_TOP)) == NULL) goto done; /* Load backend plugins before yangs are loaded (eg extension callbacks) */ diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c index 175e94b1..f31485e3 100644 --- a/apps/cli/cli_generate.c +++ b/apps/cli/cli_generate.c @@ -270,7 +270,8 @@ yang2cli_print_alias(cbuf *cb, * @param[out] cb CLIgen buf * @param[in] delim Delimiter string that may not occur in any of the elements (except the last) * @param[in] tag Context-specific tag, eg "grouping" - * @param[in] domain Domain name (= yspec name) + * @param[in] domain Domain name + * @param[in] spec yspec name * @param[in] module Name of module (in domain context) * @param[in] id Top-level nodeid (schema-id) * @retval 0 Ok @@ -281,15 +282,17 @@ yang2cli_cmd_encode(cbuf *cb, const char *delim, char *tag, char *domain, + char *spec, char *module, char *id) { - if (tag == NULL || domain == NULL || module == NULL || id == NULL){ + if (tag == NULL || domain == NULL || spec == NULL || module == NULL || id == NULL){ clixon_err(OE_YANG, EINVAL, "tag, domain, module or id is NULL"); return -1; } cprintf(cb, "%s", tag); cprintf(cb, "%s%s", delim, domain); + cprintf(cb, "%s%s", delim, spec); cprintf(cb, "%s%s", delim, module); cprintf(cb, "%s%s", delim, id); return 0; @@ -300,7 +303,8 @@ yang2cli_cmd_encode(cbuf *cb, * @param[in] cmd CLIgen cmd string * @param[in] delim Delimiter string that may not occur in any of the elements (except the last) * @param[out] tag Context-specific tag, eg "grouping" - * @param[out] domain Domain name (= yspec name) + * @param[out] domain Domain name + * @param[out] spec Yspec name * @param[out] module Name of module (in domain context) * @param[out] id Top-level nodeid (schema-id) * @retval 0 Ok @@ -311,6 +315,7 @@ yang2cli_cmd_decode(char *cmd, const char *delim, char **tag, char **domain, + char **spec, char **modname, char **id) { @@ -339,6 +344,13 @@ yang2cli_cmd_decode(char *cmd, goto ok; *s2 = '\0'; s2 += strlen(delim); + if (spec) + *spec = s2; + s1 = s2; + if ((s2 = strstr(s1, delim)) == NULL) + goto ok; + *s2 = '\0'; + s2 += strlen(delim); if (modname) *modname = s2; s1 = s2; @@ -1307,6 +1319,7 @@ yang2cli_uses(clixon_handle h, if ((ns = yang_find_mynamespace(ygrouping)) == NULL) goto done; if (yang2cli_cmd_encode(cbtree, AUTOCLI_CMD_DELIM, "grouping", + yang_argument_get(ys_domain(ygrouping)), yang_argument_get(ys_spec(ygrouping)), yang_argument_get(ys_module(ygrouping)), id) < 0) @@ -1897,11 +1910,13 @@ yang2cli_grouping_wrap(cligen_handle ch, int retval = -1; clixon_handle h; yang_stmt *ymnt; + yang_stmt *ydomain; yang_stmt *yspec; yang_stmt *ymod; yang_stmt *ygrouping; char *tag = NULL; char *domain = NULL; + char *spec = NULL; char *modname = NULL; char *grouping = NULL; int ret; @@ -1912,7 +1927,7 @@ yang2cli_grouping_wrap(cligen_handle ch, } h = cligen_userhandle(ch); yspec = clicon_dbspec_yang(h); - if (yang2cli_cmd_decode(name, AUTOCLI_CMD_DELIM, &tag, &domain, &modname, &grouping) < 0) + if (yang2cli_cmd_decode(name, AUTOCLI_CMD_DELIM, &tag, &domain, &spec, &modname, &grouping) < 0) goto done; if (tag == NULL || strcmp(tag, "grouping") != 0) goto ok; @@ -1920,13 +1935,17 @@ yang2cli_grouping_wrap(cligen_handle ch, *namep = strdup(name); goto ok; } - if (domain == NULL || modname == NULL || grouping == NULL){ + if (domain == NULL || spec == NULL || modname == NULL || grouping == NULL){ clixon_err(OE_YANG, 0, "yang2cli cmd label invalid format"); goto done; } ymnt = clixon_yang_mounts_get(h); - if ((yspec = yang_find(ymnt, Y_SPEC, domain)) == NULL){ - clixon_err(OE_YANG, 0, "yang2cli cmd label no yspec %s", domain); + if ((ydomain = yang_find(ymnt, Y_DOMAIN, domain)) == NULL){ + clixon_err(OE_YANG, 0, "yang2cli cmd label no ydomain %s", domain); + goto done; + } + if ((yspec = yang_find(ydomain, Y_SPEC, spec)) == NULL){ + clixon_err(OE_YANG, 0, "yang2cli cmd label no yspec %s", spec); goto done; } if ((ymod = yang_find(yspec, 0, modname)) == NULL){ diff --git a/apps/cli/cli_generate.h b/apps/cli/cli_generate.h index e1b13950..c4995a24 100644 --- a/apps/cli/cli_generate.h +++ b/apps/cli/cli_generate.h @@ -63,8 +63,8 @@ /* * Prototypes */ -int yang2cli_cmd_encode(cbuf *cb, const char *delim, char *tag, char *domain, char *modname, char *id); -int yang2cli_cmd_decode(char *cmd, const char *delim, char **tag, char **domain, char **modname, char **id); +int yang2cli_cmd_encode(cbuf *cb, const char *delim, char *tag, char *domain, char *spec, char *modname, char *id); +int yang2cli_cmd_decode(char *cmd, const char *delim, char **tag, char **domain, char **spec, char **modname, char **id); int yang2cli_grouping(clixon_handle h, yang_stmt *ys, char *treename); int yang2cli_yspec(clixon_handle h, yang_stmt *yspec, char *treename); int yang2cli_grouping_wrap(cligen_handle ch, char *name, cvec *cvt, void *arg, char **namep); diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index 1afc88c0..e29335a1 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -847,7 +847,7 @@ main(int argc, xml_nsctx_namespace_netconf_default(h); /* Create top-level and store as option */ - if ((yspec = yspec_new(h, YANG_DATA_TOP)) == NULL) + if ((yspec = yspec_new1(h, YANG_DOMAIN_TOP, YANG_DATA_TOP)) == NULL) goto done; /* Load Yang modules diff --git a/apps/netconf/netconf_main.c b/apps/netconf/netconf_main.c index 4d27a07b..3a1b4d12 100644 --- a/apps/netconf/netconf_main.c +++ b/apps/netconf/netconf_main.c @@ -871,7 +871,7 @@ main(int argc, if (yang_metadata_init(h) < 0) goto done; /* Create top-level yang spec and store as option */ - if ((yspec = yspec_new(h, YANG_DATA_TOP)) == NULL) + if ((yspec = yspec_new1(h, YANG_DOMAIN_TOP, YANG_DATA_TOP)) == NULL) goto done; /* Load netconf plugins before yangs are loaded (eg extension callbacks) */ diff --git a/apps/restconf/restconf_main_fcgi.c b/apps/restconf/restconf_main_fcgi.c index c716e14b..b5498cb1 100644 --- a/apps/restconf/restconf_main_fcgi.c +++ b/apps/restconf/restconf_main_fcgi.c @@ -498,7 +498,7 @@ main(int argc, goto done; /* Create top-level yang spec and store as option */ - if ((yspec = yspec_new(h, YANG_DATA_TOP)) == NULL) + if ((yspec = yspec_new1(h, YANG_DOMAIN_TOP, YANG_DATA_TOP)) == NULL) goto done; /* Initialize plugin module by creating a handle holding plugin and callback lists */ diff --git a/apps/restconf/restconf_main_native.c b/apps/restconf/restconf_main_native.c index ded27bd2..3728e074 100644 --- a/apps/restconf/restconf_main_native.c +++ b/apps/restconf/restconf_main_native.c @@ -967,7 +967,7 @@ restconf_clixon_init(clixon_handle h, if (yang_metadata_init(h) < 0) goto done; /* Create top-level yang spec and store as option */ - if ((yspec = yspec_new(h, YANG_DATA_TOP)) == NULL) + if ((yspec = yspec_new1(h, YANG_DOMAIN_TOP, YANG_DATA_TOP)) == NULL) goto done; /* Load restconf plugins before yangs are loaded (eg extension callbacks) */ diff --git a/apps/snmp/snmp_main.c b/apps/snmp/snmp_main.c index ded93c99..27c54ad7 100644 --- a/apps/snmp/snmp_main.c +++ b/apps/snmp/snmp_main.c @@ -519,7 +519,7 @@ main(int argc, goto done; /* Create top-level yang spec and store as option */ - if ((yspec = yspec_new(h, YANG_DATA_TOP)) == NULL) + if ((yspec = yspec_new1(h, YANG_DOMAIN_TOP, YANG_DATA_TOP)) == NULL) goto done; /* Load Yang modules diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index 7d3e43ae..2e3ed866 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -102,6 +102,7 @@ */ /*! Names of top-level data YANGs */ +#define YANG_DOMAIN_TOP "top" #define YANG_DATA_TOP "data" /* "dbspec" */ #define YANG_CONFIG_TOP "config" #define YANG_NACM_TOP "nacm_ext_yang" @@ -190,8 +191,9 @@ enum rfc_6020{ Y_YANG_VERSION, Y_YIN_ELEMENT, /* Note, from here not actual yang statement from the RFC */ - Y_MOUNTS, /* Top-level all mounts */ - Y_SPEC /* Specifications on top, config or mount-points */ + Y_MOUNTS, /* Top-level root single object, see clixon_yang_mounts_get() */ + Y_DOMAIN, /* YANG domain: many module revisions allowed but name+revision unique */ + Y_SPEC /* Module set for single data, config and mount-point: unique module name */ }; /* Type used to group yang nodes used in some functions @@ -286,7 +288,9 @@ int yang_stats(yang_stmt *y, enum rfc_6020 keyw, uint64_t *nrp, size_t *s /* Other functions */ yang_stmt *yspec_new(clixon_handle h, char *name); +yang_stmt *yspec_new1(clixon_handle h, char *domain, char *name); yang_stmt *yspec_new_shared(clixon_handle h, char *name, char *domain, yang_stmt *yspec0); +yang_stmt *ydomain_new(clixon_handle h, char *domain); yang_stmt *ys_new(enum rfc_6020 keyw); yang_stmt *ys_prune(yang_stmt *yp, int i); int ys_prune_self(yang_stmt *ys); @@ -304,6 +308,7 @@ int ys_module_by_xml(yang_stmt *ysp, struct xml *xt, yang_stmt **ymodp); yang_stmt *ys_module(yang_stmt *ys); int ys_real_module(yang_stmt *ys, yang_stmt **ymod); yang_stmt *ys_spec(yang_stmt *ys); +yang_stmt *ys_domain(yang_stmt *ys); yang_stmt *ys_mounts(yang_stmt *ys); yang_stmt *yang_find(yang_stmt *yn, int keyword, const char *argument); yang_stmt *yang_find_datanode(yang_stmt *yn, char *argument); diff --git a/lib/src/clixon_data.c b/lib/src/clixon_data.c index 29ec8391..e171506f 100644 --- a/lib/src/clixon_data.c +++ b/lib/src/clixon_data.c @@ -354,11 +354,13 @@ clixon_yang_mounts_set(clixon_handle h, yang_stmt * clicon_dbspec_yang(clixon_handle h) { + yang_stmt *ymounts; + yang_stmt *ydomain; yang_stmt *ys = NULL; - yang_stmt *ymounts = NULL; - if ((ymounts = clixon_yang_mounts_get(h)) != NULL) - ys = yang_find(ymounts, Y_SPEC, YANG_DATA_TOP); + if ((ymounts = clixon_yang_mounts_get(h)) != NULL && + (ydomain = yang_find(ymounts, Y_DOMAIN, YANG_DOMAIN_TOP)) != NULL) + ys = yang_find(ydomain, Y_SPEC, YANG_DATA_TOP); return ys; } @@ -371,11 +373,13 @@ clicon_dbspec_yang(clixon_handle h) yang_stmt * clicon_config_yang(clixon_handle h) { - yang_stmt *ymounts = NULL; + yang_stmt *ymounts; + yang_stmt *ydomain; yang_stmt *ys = NULL; - if ((ymounts = clixon_yang_mounts_get(h)) != NULL) - ys = yang_find(ymounts, Y_SPEC, YANG_CONFIG_TOP); + if ((ymounts = clixon_yang_mounts_get(h)) != NULL && + (ydomain = yang_find(ymounts, Y_DOMAIN, YANG_DOMAIN_TOP)) != NULL) + ys = yang_find(ydomain, Y_SPEC, YANG_CONFIG_TOP); return ys; } @@ -388,11 +392,13 @@ clicon_config_yang(clixon_handle h) yang_stmt * clicon_nacm_ext_yang(clixon_handle h) { - yang_stmt *ymounts = NULL; + yang_stmt *ymounts; + yang_stmt *ydomain; yang_stmt *ys = NULL; - if ((ymounts = clixon_yang_mounts_get(h)) != NULL) - ys = yang_find(ymounts, Y_SPEC, YANG_NACM_TOP); + if ((ymounts = clixon_yang_mounts_get(h)) != NULL && + (ydomain = yang_find(ymounts, Y_DOMAIN, YANG_DOMAIN_TOP)) != NULL) + ys = yang_find(ydomain, Y_SPEC, YANG_NACM_TOP); return ys; } diff --git a/lib/src/clixon_datastore_read.c b/lib/src/clixon_datastore_read.c index 0f02ff4c..63ffcb31 100644 --- a/lib/src/clixon_datastore_read.c +++ b/lib/src/clixon_datastore_read.c @@ -708,7 +708,7 @@ xmldb_readfile(clixon_handle h, * Same ymodules are inserted into yspec1, ie pointers only */ if (needclone && xmodfile){ - if ((yspec1 = yspec_new(h, "tmp")) == NULL) + if ((yspec1 = yspec_new1(h, YANG_DOMAIN_TOP, "tmp")) == NULL) goto done; xmsd = NULL; while ((xmsd = xml_child_each(xmodfile, xmsd, CX_ELMNT)) != NULL) { diff --git a/lib/src/clixon_options.c b/lib/src/clixon_options.c index 8b66f81b..93fa2ce4 100644 --- a/lib/src/clixon_options.c +++ b/lib/src/clixon_options.c @@ -639,7 +639,7 @@ clicon_options_main(clixon_handle h) char *yangspec = "clixon-config"; /* Create configure yang-spec */ - if ((yspec = yspec_new(h, YANG_CONFIG_TOP)) == NULL) + if ((yspec = yspec_new1(h, YANG_DOMAIN_TOP, YANG_CONFIG_TOP)) == NULL) goto done; /* * Set configure file if not set by command-line above diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index b11bf2de..60e306ef 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -260,6 +260,8 @@ yang_argument_set(yang_stmt *ys, * * @param[in] ys Yang statement node * @param[in] arg Argument, is copied + * @retval 0 Ok + * @retval -1 Error */ int yang_argument_dup(yang_stmt *ys, @@ -829,27 +831,53 @@ yang_stats(yang_stmt *yt, /* stats end */ -/*! Create new yang specification, addd as child to top-level yang_mounts +/*! Create new yang specification for top domain, add as child to top-level yang_mounts * - * @retval yspec Free with ys_free() - * @retval NULL Error + * @param[in] h Clixon handle + * @param[in] domain Yang domain + * @param[in] name Yang spec name + * @retval yspec Yang spec, free with ys_free + * @retval NULL Error + * XXX Backward-compatible 7.1 */ yang_stmt * yspec_new(clixon_handle h, char *name) +{ + return yspec_new1(h, YANG_DOMAIN_TOP, name); +} + +/*! Create new yang specification, addd as child to top-level yang_mounts + * + * @param[in] h Clixon handle + * @param[in] domain Yang domain + * @param[in] name Yang spec name + * @retval yspec Yang spec, free with ys_free + * @retval NULL Error + * @see yspec_new Hardcoded to top-domain + */ +yang_stmt * +yspec_new1(clixon_handle h, + char *domain, + char *name) { yang_stmt *ymounts; + yang_stmt *ydomain; yang_stmt *yspec; if ((ymounts = clixon_yang_mounts_get(h)) == NULL){ clixon_err(OE_YANG, 0, "Yang-mounts not created"); goto done; } + if ((ydomain = yang_find(ymounts, Y_DOMAIN, domain)) == NULL){ + clixon_err(OE_YANG, 0, "Yang domain %s not found", domain); + goto done; + } if ((yspec = ys_new(Y_SPEC)) == NULL) goto done; - if (yang_argument_dup(yspec, name) < 0) + if (name != NULL && yang_argument_dup(yspec, name) < 0) goto done; - if (yn_insert(ymounts, yspec) < 0) + if (yn_insert(ydomain, yspec) < 0) goto done; return yspec; done: @@ -876,7 +904,8 @@ yspec_new_shared(clixon_handle h, yspec1 = yspec0; } else { - if ((yspec1 = yspec_new(h, domain)) == NULL) + // XXX domain used as name + if ((yspec1 = yspec_new1(h, domain, domain)) == NULL) goto done; yang_flag_set(yspec1, YANG_FLAG_SPEC_MOUNT); clixon_debug(CLIXON_DBG_YANG, "new yang-spec: %p", yspec1); @@ -889,6 +918,39 @@ yspec_new_shared(clixon_handle h, return yspec1; } +/*! Create new yang domain + * + * @param[in] h Clixon handle + * @param[in] domain Yang domain name + * @retval ydomain Yang spec, free with ys_free + * @retval NULL Error + */ +yang_stmt * +ydomain_new(clixon_handle h, + char *domain) +{ + yang_stmt *ymounts; + yang_stmt *ydomain; + + if (domain == NULL){ + clixon_err(OE_YANG, EINVAL, "domain is NULL"); + goto done; + } + if ((ymounts = clixon_yang_mounts_get(h)) == NULL){ + clixon_err(OE_YANG, 0, "Yang-mounts not created"); + goto done; + } + if ((ydomain = ys_new(Y_DOMAIN)) == NULL) + goto done; + if (yang_argument_dup(ydomain, domain) < 0) + goto done; + if (yn_insert(ymounts, ydomain) < 0) + goto done; + return ydomain; + done: + return NULL; +} + /*! Create new yang node/statement given size * * Size parameter for variable size, eg extended YANG struct @@ -2156,10 +2218,10 @@ ys_real_module(yang_stmt *ys, return retval; } -/*! Find top of tree, the yang specification from within the tree +/*! Find spec tree, the yang specification from within the tree * * @param[in] ys Any yang statement in a yang tree - * @retval yspec The top yang specification + * @retval yspec The yang specification * @see ys_module * @see yang_augment_node where shortcut is set for augment * @see yang_myroot for first node under (sub)module @@ -2177,6 +2239,21 @@ ys_spec(yang_stmt *ys) return ys; } +/*! Find domain tree, + * + * @param[in] ys Any yang statement in a yang tree + * @retval ydomain The yang domain specification + */ +yang_stmt * +ys_domain(yang_stmt *ys) +{ + yang_stmt *yn; + + if ((yn = ys_spec(ys)) != NULL) + return yn->ys_parent; + return NULL; +} + /*! Find top of tree, the yang specification from within the tree * * @param[in] ys Any yang statement in a yang tree @@ -2296,8 +2373,10 @@ int yang_mounts_print(FILE *f, yang_stmt *ymounts) { + yang_stmt *ydomain; yang_stmt *yspec; int inext; + int inext2; cg_var *cv; cvec *cvv; @@ -2306,15 +2385,19 @@ yang_mounts_print(FILE *f, return -1; } inext = 0; - while ((yspec = yn_iter(ymounts, &inext)) != NULL) { - fprintf(f, " %s\n", yang_argument_get(yspec)); - if ((cv = yang_cv_get(yspec)) != NULL){ - cv_print(f, yang_cv_get(yspec)); - fprintf(f, "\n"); - } - if ((cvv = yang_cvec_get(yspec)) != NULL){ - cvec_print(f, cvv); - fprintf(f, "\n"); + while ((ydomain = yn_iter(ymounts, &inext)) != NULL) { + fprintf(f, "domain:%s\n", yang_argument_get(ydomain)); + inext2 = 0; + while ((yspec = yn_iter(ydomain, &inext2)) != NULL) { + fprintf(f, " spec:%s\n", yang_argument_get(yspec)); + if ((cv = yang_cv_get(yspec)) != NULL){ + cv_print(f, yang_cv_get(yspec)); + fprintf(f, "\n"); + } + if ((cvv = yang_cvec_get(yspec)) != NULL){ + cvec_print(f, cvv); + fprintf(f, "\n"); + } } } return 0; @@ -4486,6 +4569,8 @@ yang_init(clixon_handle h) goto done; if (clixon_yang_mounts_set(h, ymounts) < 0) goto done; + if (ydomain_new(h, YANG_DOMAIN_TOP) == NULL) + goto done; retval = 0; done: return retval; diff --git a/lib/src/clixon_yang_schema_mount.c b/lib/src/clixon_yang_schema_mount.c index b16d539d..fc6bf50a 100644 --- a/lib/src/clixon_yang_schema_mount.c +++ b/lib/src/clixon_yang_schema_mount.c @@ -197,20 +197,28 @@ yang_mount_get(yang_stmt *ys, { int retval = 1; yang_stmt *ymounts; + yang_stmt *ydomain; yang_stmt *yspec = NULL; int inext; + int inext2; if ((ymounts = ys_mounts(ys)) == NULL){ clixon_err(OE_YANG, ENOENT, "Top-level yang mounts not found"); goto done; } inext = 0; - while ((yspec = yn_iter(ymounts, &inext)) != NULL) { - if (yang_keyword_get(yspec) != Y_SPEC || - yang_cvec_get(yspec) == NULL || - yang_flag_get(yspec, YANG_FLAG_SPEC_MOUNT) == 0) - continue; - if (xpath == NULL || cvec_find(yang_cvec_get(yspec), xpath) != NULL) + ydomain = NULL; + while ((ydomain = yn_iter(ymounts, &inext)) != NULL) { + inext2 = 0; + while ((yspec = yn_iter(ydomain, &inext2)) != NULL) { + if (yang_keyword_get(yspec) != Y_SPEC || + yang_cvec_get(yspec) == NULL || + yang_flag_get(yspec, YANG_FLAG_SPEC_MOUNT) == 0) + continue; + if (xpath == NULL || cvec_find(yang_cvec_get(yspec), xpath) != NULL) + break; + } + if (yspec != NULL) break; } *yspecp = yspec; @@ -712,6 +720,7 @@ yang_schema_yanglib_parse_mount(clixon_handle h, cxobj *xyanglib = NULL; cxobj *xb; yang_stmt *ymounts; + yang_stmt *ydomain; yang_stmt *yspec0 = NULL; yang_stmt *yspec1 = NULL; char *xpath = NULL; @@ -742,7 +751,11 @@ yang_schema_yanglib_parse_mount(clixon_handle h, clixon_err(OE_YANG, ENOENT, "Top-level yang mounts not found"); goto done; } - yspec0 = yang_find(ymounts, Y_SPEC, domain); + if ((ydomain = yang_find(ymounts, Y_DOMAIN, domain)) == NULL){ + if ((ydomain = ydomain_new(h, domain)) == NULL) + goto done; + } + yspec0 = yang_find(ydomain, Y_SPEC, domain); // XXX name? if ((yspec1 = yspec_new_shared(h, xpath, domain, yspec0)) < 0) goto done; /* Either yspec0 = NULL and yspec1 is new, or yspec0 == yspec1 != NULL (shared) */ diff --git a/test/test_autocli_grouping.sh b/test/test_autocli_grouping.sh index 4b2b3468..0841d3ac 100755 --- a/test/test_autocli_grouping.sh +++ b/test/test_autocli_grouping.sh @@ -209,10 +209,10 @@ EOF # The testcase assumes enabled if ${grouping_treeref}; then new "verify grouping is enabled" - expectpart "$($clixon_cli -f $cfg -G -1 2>&1)" 0 "@grouping--data--example--pg1" "@grouping--data--example-external--pg2" # "@grouping--data--example-external--pg3" + expectpart "$($clixon_cli -f $cfg -G -1 2>&1)" 0 "@grouping--top--data--example--pg1" "@grouping--top--data--example-external--pg2" # "@grouping--top--data--example-external--pg3" else new "verify grouping is disabled" - expectpart "$($clixon_cli -f $cfg -G -1 2>&1)" 0 --not-- "@grouping--data--example--pg1" "@grouping--data--example-external--pg2" "@grouping--data-example-external-pg3" + expectpart "$($clixon_cli -f $cfg -G -1 2>&1)" 0 --not-- "@grouping--top--data--example--pg1" "@grouping--top--data--example-external--pg2" "@grouping--top--data-example-external-pg3" fi new "set top-level grouping" diff --git a/test/test_nacm_mount.sh b/test/test_nacm_mount.sh index 06586ab5..521203c6 100755 --- a/test/test_nacm_mount.sh +++ b/test/test_nacm_mount.sh @@ -189,7 +189,7 @@ RULES=$(cat < EOF ) -// /ex:top/ex:mylist/ex:mnt/m0:mymount0/m0:mylist0 +# /ex:top/ex:mylist/ex:mnt/m0:mymount0/m0:mylist0 new "test params: -f $cfg"