Added "canonical" global namespace context: nsctx_global
This commit is contained in:
parent
06c2793e79
commit
52629d7b35
11 changed files with 149 additions and 14 deletions
|
|
@ -3,6 +3,9 @@
|
||||||
## 4.3.0 (Expected: ~December 2019)
|
## 4.3.0 (Expected: ~December 2019)
|
||||||
|
|
||||||
### Minor changes
|
### Minor changes
|
||||||
|
* Added "canonical" global namespace context: `nsctx_global`
|
||||||
|
* This is a normalized XML prefix:namespace pair vector computed from all loaded Yang modules. Useful when writing XML and XPATH expressions in callbacks.
|
||||||
|
* Get it with `clicon_nsctx_global_get(h)`
|
||||||
* Added wildcard `*` as a mode to `CLICON_MODE` in clispec files
|
* Added wildcard `*` as a mode to `CLICON_MODE` in clispec files
|
||||||
* If you set "CLICON_MODE="*";" in a clispec file it means that syntax will appear in all CLI spec modes.
|
* If you set "CLICON_MODE="*";" in a clispec file it means that syntax will appear in all CLI spec modes.
|
||||||
* State callbacks provided by user are validated. If they are invalid an internal error is returned.
|
* State callbacks provided by user are validated. If they are invalid an internal error is returned.
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ backend_terminate(clicon_handle h)
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int ss;
|
int ss;
|
||||||
|
cvec *nsctx;
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
if ((ss = clicon_socket_get(h)) != -1)
|
if ((ss = clicon_socket_get(h)) != -1)
|
||||||
|
|
@ -108,6 +109,8 @@ backend_terminate(clicon_handle h)
|
||||||
xml_free(x);
|
xml_free(x);
|
||||||
if ((yspec = clicon_dbspec_yang(h)) != NULL)
|
if ((yspec = clicon_dbspec_yang(h)) != NULL)
|
||||||
yspec_free(yspec);
|
yspec_free(yspec);
|
||||||
|
if ((nsctx = clicon_nsctx_global_get(h)) != NULL)
|
||||||
|
cvec_free(nsctx);
|
||||||
if ((yspec = clicon_config_yang(h)) != NULL)
|
if ((yspec = clicon_config_yang(h)) != NULL)
|
||||||
yspec_free(yspec);
|
yspec_free(yspec);
|
||||||
if ((x = clicon_nacm_ext(h)) != NULL)
|
if ((x = clicon_nacm_ext(h)) != NULL)
|
||||||
|
|
@ -451,6 +454,7 @@ main(int argc,
|
||||||
int ret;
|
int ret;
|
||||||
char *dir;
|
char *dir;
|
||||||
gid_t gid = -1;
|
gid_t gid = -1;
|
||||||
|
cvec *nsctx_global = NULL; /* Global namespace context */
|
||||||
|
|
||||||
/* In the startup, logs to stderr & syslog and debug flag set later */
|
/* In the startup, logs to stderr & syslog and debug flag set later */
|
||||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||||
|
|
@ -743,6 +747,14 @@ main(int argc,
|
||||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
|
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
|
||||||
yang_spec_parse_module(h, "clixon-rfc5277", NULL, yspec)< 0)
|
yang_spec_parse_module(h, "clixon-rfc5277", NULL, yspec)< 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* Here all modules are loaded
|
||||||
|
* Compute and set canonical namespace context
|
||||||
|
*/
|
||||||
|
if (xml_nsctx_yangspec(yspec, &nsctx_global) < 0)
|
||||||
|
goto done;
|
||||||
|
if (clicon_nsctx_global_set(h, nsctx_global) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Initialize server socket and save it to handle */
|
/* Initialize server socket and save it to handle */
|
||||||
if (backend_rpc_init(h) < 0)
|
if (backend_rpc_init(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,7 @@ static int
|
||||||
cli_terminate(clicon_handle h)
|
cli_terminate(clicon_handle h)
|
||||||
{
|
{
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
|
cvec *nsctx;
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
|
|
||||||
clicon_rpc_close_session(h);
|
clicon_rpc_close_session(h);
|
||||||
|
|
@ -170,6 +171,8 @@ cli_terminate(clicon_handle h)
|
||||||
yspec_free(yspec);
|
yspec_free(yspec);
|
||||||
if ((yspec = clicon_config_yang(h)) != NULL)
|
if ((yspec = clicon_config_yang(h)) != NULL)
|
||||||
yspec_free(yspec);
|
yspec_free(yspec);
|
||||||
|
if ((nsctx = clicon_nsctx_global_get(h)) != NULL)
|
||||||
|
cvec_free(nsctx);
|
||||||
if ((x = clicon_conf_xml(h)) != NULL)
|
if ((x = clicon_conf_xml(h)) != NULL)
|
||||||
xml_free(x);
|
xml_free(x);
|
||||||
cli_plugin_finish(h);
|
cli_plugin_finish(h);
|
||||||
|
|
@ -286,6 +289,7 @@ main(int argc, char **argv)
|
||||||
int tabmode;
|
int tabmode;
|
||||||
char *dir;
|
char *dir;
|
||||||
uint32_t id = 0;
|
uint32_t id = 0;
|
||||||
|
cvec *nsctx_global = NULL; /* Global namespace context */
|
||||||
|
|
||||||
/* Defaults */
|
/* Defaults */
|
||||||
once = 0;
|
once = 0;
|
||||||
|
|
@ -513,6 +517,14 @@ main(int argc, char **argv)
|
||||||
if (netconf_module_load(h) < 0)
|
if (netconf_module_load(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
/* Here all modules are loaded
|
||||||
|
* Compute and set canonical namespace context
|
||||||
|
*/
|
||||||
|
if (xml_nsctx_yangspec(yspec, &nsctx_global) < 0)
|
||||||
|
goto done;
|
||||||
|
if (clicon_nsctx_global_set(h, nsctx_global) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Create tree generated from dataspec. If no other trees exists, this is
|
/* Create tree generated from dataspec. If no other trees exists, this is
|
||||||
* the only one.
|
* the only one.
|
||||||
* The following code creates the tree @datamodel
|
* The following code creates the tree @datamodel
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,7 @@ static int
|
||||||
netconf_terminate(clicon_handle h)
|
netconf_terminate(clicon_handle h)
|
||||||
{
|
{
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
|
cvec *nsctx;
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
|
|
||||||
clixon_plugin_exit(h);
|
clixon_plugin_exit(h);
|
||||||
|
|
@ -332,6 +333,8 @@ netconf_terminate(clicon_handle h)
|
||||||
yspec_free(yspec);
|
yspec_free(yspec);
|
||||||
if ((yspec = clicon_config_yang(h)) != NULL)
|
if ((yspec = clicon_config_yang(h)) != NULL)
|
||||||
yspec_free(yspec);
|
yspec_free(yspec);
|
||||||
|
if ((nsctx = clicon_nsctx_global_get(h)) != NULL)
|
||||||
|
cvec_free(nsctx);
|
||||||
if ((x = clicon_conf_xml(h)) != NULL)
|
if ((x = clicon_conf_xml(h)) != NULL)
|
||||||
xml_free(x);
|
xml_free(x);
|
||||||
event_exit();
|
event_exit();
|
||||||
|
|
@ -395,6 +398,7 @@ main(int argc,
|
||||||
yang_stmt *yspecfg = NULL; /* For config XXX clixon bug */
|
yang_stmt *yspecfg = NULL; /* For config XXX clixon bug */
|
||||||
char *str;
|
char *str;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
cvec *nsctx_global = NULL; /* Global namespace context */
|
||||||
|
|
||||||
/* Create handle */
|
/* Create handle */
|
||||||
if ((h = clicon_handle_init()) == NULL)
|
if ((h = clicon_handle_init()) == NULL)
|
||||||
|
|
@ -554,6 +558,14 @@ main(int argc,
|
||||||
/* Add netconf yang spec, used by netconf client and as internal protocol */
|
/* Add netconf yang spec, used by netconf client and as internal protocol */
|
||||||
if (netconf_module_load(h) < 0)
|
if (netconf_module_load(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* Here all modules are loaded
|
||||||
|
* Compute and set canonical namespace context
|
||||||
|
*/
|
||||||
|
if (xml_nsctx_yangspec(yspec, &nsctx_global) < 0)
|
||||||
|
goto done;
|
||||||
|
if (clicon_nsctx_global_set(h, nsctx_global) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Call start function is all plugins before we go interactive */
|
/* Call start function is all plugins before we go interactive */
|
||||||
if (clixon_plugin_start(h) < 0)
|
if (clixon_plugin_start(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -593,6 +593,7 @@ int
|
||||||
restconf_terminate(clicon_handle h)
|
restconf_terminate(clicon_handle h)
|
||||||
{
|
{
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
|
cvec *nsctx;
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
int fs; /* fgcx socket */
|
int fs; /* fgcx socket */
|
||||||
|
|
||||||
|
|
@ -606,6 +607,8 @@ restconf_terminate(clicon_handle h)
|
||||||
yspec_free(yspec);
|
yspec_free(yspec);
|
||||||
if ((yspec = clicon_config_yang(h)) != NULL)
|
if ((yspec = clicon_config_yang(h)) != NULL)
|
||||||
yspec_free(yspec);
|
yspec_free(yspec);
|
||||||
|
if ((nsctx = clicon_nsctx_global_get(h)) != NULL)
|
||||||
|
cvec_free(nsctx);
|
||||||
if ((x = clicon_conf_xml(h)) != NULL)
|
if ((x = clicon_conf_xml(h)) != NULL)
|
||||||
xml_free(x);
|
xml_free(x);
|
||||||
clicon_handle_exit(h);
|
clicon_handle_exit(h);
|
||||||
|
|
|
||||||
|
|
@ -589,6 +589,7 @@ main(int argc,
|
||||||
char *str;
|
char *str;
|
||||||
clixon_plugin *cp = NULL;
|
clixon_plugin *cp = NULL;
|
||||||
uint32_t id = 0;
|
uint32_t id = 0;
|
||||||
|
cvec *nsctx_global = NULL; /* Global namespace context */
|
||||||
|
|
||||||
/* In the startup, logs to stderr & debug flag set later */
|
/* In the startup, logs to stderr & debug flag set later */
|
||||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||||
|
|
@ -760,6 +761,14 @@ main(int argc,
|
||||||
yang_spec_parse_module(h, "clixon-rfc5277", NULL, yspec)< 0)
|
yang_spec_parse_module(h, "clixon-rfc5277", NULL, yspec)< 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
/* Here all modules are loaded
|
||||||
|
* Compute and set canonical namespace context
|
||||||
|
*/
|
||||||
|
if (xml_nsctx_yangspec(yspec, &nsctx_global) < 0)
|
||||||
|
goto done;
|
||||||
|
if (clicon_nsctx_global_set(h, nsctx_global) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* Dump configuration options on debug */
|
/* Dump configuration options on debug */
|
||||||
if (debug)
|
if (debug)
|
||||||
clicon_option_dump(h, debug);
|
clicon_option_dump(h, debug);
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,9 @@ typedef struct {
|
||||||
yang_stmt * clicon_dbspec_yang(clicon_handle h);
|
yang_stmt * clicon_dbspec_yang(clicon_handle h);
|
||||||
int clicon_dbspec_yang_set(clicon_handle h, yang_stmt *ys);
|
int clicon_dbspec_yang_set(clicon_handle h, yang_stmt *ys);
|
||||||
|
|
||||||
|
cvec *clicon_nsctx_global_get(clicon_handle h);
|
||||||
|
int clicon_nsctx_global_set(clicon_handle h, cvec *nsctx);
|
||||||
|
|
||||||
cxobj * clicon_nacm_ext(clicon_handle h);
|
cxobj * clicon_nacm_ext(clicon_handle h);
|
||||||
int clicon_nacm_ext_set(clicon_handle h, cxobj *xn);
|
int clicon_nacm_ext_set(clicon_handle h, cxobj *xn);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,5 +55,6 @@ int xml_nsctx_get_prefix(cvec *cvv, char *namespace, char **prefix);
|
||||||
int xml_nsctx_add(cvec *nsc, char *prefix, char *namespace);
|
int xml_nsctx_add(cvec *nsc, char *prefix, char *namespace);
|
||||||
int xml_nsctx_node(cxobj *x, cvec **ncp);
|
int xml_nsctx_node(cxobj *x, cvec **ncp);
|
||||||
int xml_nsctx_yang(yang_stmt *yn, cvec **ncp);
|
int xml_nsctx_yang(yang_stmt *yn, cvec **ncp);
|
||||||
|
int xml_nsctx_yangspec(yang_stmt *yspec, cvec **ncp);
|
||||||
|
|
||||||
#endif /* _CLIXON_XML_NSCTX_H */
|
#endif /* _CLIXON_XML_NSCTX_H */
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,8 @@
|
||||||
|
|
||||||
/*! Get YANG specification for application
|
/*! Get YANG specification for application
|
||||||
* Must use hash functions directly since they are not strings.
|
* Must use hash functions directly since they are not strings.
|
||||||
|
* @param[in] h Clicon handle
|
||||||
|
* @retval yspec Yang spec
|
||||||
*/
|
*/
|
||||||
yang_stmt *
|
yang_stmt *
|
||||||
clicon_dbspec_yang(clicon_handle h)
|
clicon_dbspec_yang(clicon_handle h)
|
||||||
|
|
@ -90,6 +92,8 @@ clicon_dbspec_yang(clicon_handle h)
|
||||||
|
|
||||||
/*! Set yang specification for application
|
/*! Set yang specification for application
|
||||||
* ys must be a malloced pointer
|
* ys must be a malloced pointer
|
||||||
|
* @param[in] h Clicon handle
|
||||||
|
* @param[in] yspec Yang spec
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_dbspec_yang_set(clicon_handle h,
|
clicon_dbspec_yang_set(clicon_handle h,
|
||||||
|
|
@ -105,6 +109,42 @@ clicon_dbspec_yang_set(clicon_handle h,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Get Global "canonical" namespace context
|
||||||
|
* Canonical: use prefix and namespace specified in the yang modules.
|
||||||
|
* @param[in] h Clicon handle
|
||||||
|
* @retval nsctx Namespace context (malloced)
|
||||||
|
*/
|
||||||
|
cvec *
|
||||||
|
clicon_nsctx_global_get(clicon_handle h)
|
||||||
|
{
|
||||||
|
clicon_hash_t *cdat = clicon_data(h);
|
||||||
|
size_t len;
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
if ((p = clicon_hash_value(cdat, "nsctx_global", &len)) != NULL)
|
||||||
|
return *(cvec **)p;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Set global "canonical" namespace context
|
||||||
|
* Canonical: use prefix and namespace specified in the yang modules.
|
||||||
|
* @param[in] h Clicon handle
|
||||||
|
* @param[in] nsctx Namespace context (malloced)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clicon_nsctx_global_set(clicon_handle h,
|
||||||
|
cvec *nsctx)
|
||||||
|
{
|
||||||
|
clicon_hash_t *cdat = clicon_data(h);
|
||||||
|
|
||||||
|
/* It is the pointer to cvec that should be copied by hash,
|
||||||
|
so we send a ptr to the ptr to indicate what to copy.
|
||||||
|
*/
|
||||||
|
if (clicon_hash_add(cdat, "nsctx_global", &nsctx, sizeof(nsctx)) == NULL)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Get NACM (rfc 8341) XML parse tree if external not in std xml config
|
/*! Get NACM (rfc 8341) XML parse tree if external not in std xml config
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @retval xn XML NACM tree, or NULL
|
* @retval xn XML NACM tree, or NULL
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,6 @@ xml_nsctx_add(cvec *cvv,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
xml_nsctx_node1(cxobj *xn,
|
xml_nsctx_node1(cxobj *xn,
|
||||||
cvec *nsc)
|
cvec *nsc)
|
||||||
|
|
@ -268,10 +267,10 @@ xml_nsctx_node(cxobj *xn,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Create and initialize XML namespace from Yang node
|
/*! Create and initialize XML namespace context from Yang node
|
||||||
* Primary use is Yang path statements, eg leafrefs and others
|
* Primary use is Yang path statements, eg leafrefs and others
|
||||||
* Fully explore all prefix:namespace pairs from context of one node
|
* Fully explore all prefix:namespace pairs from context of one node
|
||||||
* @param[in] xn XML node
|
* @param[in] yn Yang statement in module tree (or module itself)
|
||||||
* @param[out] ncp XML namespace context
|
* @param[out] ncp XML namespace context
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
|
@ -354,3 +353,44 @@ xml_nsctx_yang(yang_stmt *yn,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Create and initialize XML namespace context from Yang spec
|
||||||
|
*
|
||||||
|
* That is, create a "canonical" XML namespace mapping from all loaded yang
|
||||||
|
* modules which are children of the yang specification.
|
||||||
|
* ALso add netconf base namespace: nc , urn:ietf:params:xml:ns:netconf:base:1.0
|
||||||
|
* Fully explore all prefix:namespace pairs of all yang modules
|
||||||
|
* @param[in] yspec Yang spec
|
||||||
|
* @param[out] ncp XML namespace context
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xml_nsctx_yangspec(yang_stmt *yspec,
|
||||||
|
cvec **ncp)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cvec *nc = NULL;
|
||||||
|
yang_stmt *ymod = NULL;
|
||||||
|
yang_stmt *yprefix;
|
||||||
|
yang_stmt *ynamespace;
|
||||||
|
|
||||||
|
if ((nc = cvec_new(0)) == NULL){
|
||||||
|
clicon_err(OE_XML, errno, "cvec_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
ymod = NULL;
|
||||||
|
while ((ymod = yn_each(yspec, ymod)) != NULL){
|
||||||
|
if (yang_keyword_get(ymod) != Y_MODULE)
|
||||||
|
continue;
|
||||||
|
if ((yprefix = yang_find(ymod, Y_PREFIX, NULL)) == NULL)
|
||||||
|
continue;
|
||||||
|
if ((ynamespace = yang_find(ymod, Y_NAMESPACE, NULL)) == NULL)
|
||||||
|
continue;
|
||||||
|
if (xml_nsctx_add(nc, yang_argument_get(yprefix), yang_argument_get(ynamespace)) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (xml_nsctx_add(nc, NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE) < 0)
|
||||||
|
goto done;
|
||||||
|
*ncp = nc;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -766,7 +766,7 @@ yang_find_myprefix(yang_stmt *ys)
|
||||||
}
|
}
|
||||||
if ((yprefix = yang_find(ymod, Y_PREFIX, NULL)) == NULL)
|
if ((yprefix = yang_find(ymod, Y_PREFIX, NULL)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
prefix = yprefix->ys_argument;
|
prefix = yang_argument_get(yprefix);
|
||||||
done:
|
done:
|
||||||
return prefix;
|
return prefix;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue