renamed xml_spec_populate*() to xml_bind_yang*()

This commit is contained in:
Olof hagsand 2020-03-17 15:55:47 +01:00
parent c5e2039cac
commit b726c5008e
17 changed files with 191 additions and 185 deletions

View file

@ -79,8 +79,14 @@ features include optimized search functions and a repair callback.
* All uses of `api_path2xpath_cvv()` should be replaced by `api_path2xpath()` * All uses of `api_path2xpath_cvv()` should be replaced by `api_path2xpath()`
* `api_path2xpath()` added an `xerr` argument. * `api_path2xpath()` added an `xerr` argument.
* Parse and validation API more capable * Parse and validation API more capable
* `xml_spec_populate` family of functions extended with three-value return values * `xml_spec_populate` has been split into a family of functions
* -1: error, 0: parse OK, 1: parse and YANG binding OK. * `xml_bind_yang_rpc()`
* `xml_bind_yang_rpc_reply()`
* `xml_bind_yang0()`
* `xml_bind_yang0_parent()`
* `xml_bind_yang()`
* `xml_bind_yang_parent()`
* All have three-value return values: -1: error, 0: parse OK, 1: parse and YANG binding OK.
* `xml_parse` and `json_parse` API changes * `xml_parse` and `json_parse` API changes
* Three value returns: -1: error, 0: parse OK, 1: parse and YANG binding OK. * Three value returns: -1: error, 0: parse OK, 1: parse and YANG binding OK.
* Extended `xml_parse_file2` and `xml_parse_string2` extended API functions with all options available. * Extended `xml_parse_file2` and `xml_parse_string2` extended API functions with all options available.

View file

@ -670,7 +670,7 @@ from_client_edit_config(clicon_handle h,
xml_spec_set(xc, NULL); xml_spec_set(xc, NULL);
/* Populate XML with Yang spec (why not do this in parser?) /* Populate XML with Yang spec (why not do this in parser?)
*/ */
if (xml_spec_populate(xc, yspec, NULL) < 0) if (xml_bind_yang(xc, yspec, NULL) < 0)
goto done; goto done;
/* Maybe validate xml here as in text_modify_top? */ /* Maybe validate xml here as in text_modify_top? */
if (xml_apply(xc, CX_ELMNT, xml_non_config_data, &non_config) < 0) if (xml_apply(xc, CX_ELMNT, xml_non_config_data, &non_config) < 0)
@ -1593,7 +1593,7 @@ from_client_msg(clicon_handle h,
* should really have been dealt with by decode above * should really have been dealt with by decode above
* but it still is needed - test_cli debug test fails * but it still is needed - test_cli debug test fails
*/ */
if (xml_spec_populate_rpc(x, yspec, NULL) < 0) if (xml_bind_yang_rpc(x, yspec, NULL) < 0)
goto done; goto done;
if ((ret = xml_yang_validate_rpc(h, x, &xret)) < 0) if ((ret = xml_yang_validate_rpc(h, x, &xret)) < 0)
goto done; goto done;

View file

@ -214,7 +214,7 @@ startup_common(clicon_handle h,
goto done; goto done;
} }
/* After upgrading, XML tree needs to be sorted and yang spec populated */ /* After upgrading, XML tree needs to be sorted and yang spec populated */
if (xml_spec_populate(xt, yspec, NULL) < 0) if (xml_bind_yang(xt, yspec, NULL) < 0)
goto done; goto done;
if (xml_apply0(xt, CX_ELMNT, xml_sort, h) < 0) if (xml_apply0(xt, CX_ELMNT, xml_sort, h) < 0)
goto done; goto done;

View file

@ -128,7 +128,7 @@ clixon_plugin_statedata(clicon_handle h,
if (debug) if (debug)
clicon_log_xml(LOG_DEBUG, x, "%s STATE:", __FUNCTION__); clicon_log_xml(LOG_DEBUG, x, "%s STATE:", __FUNCTION__);
#endif #endif
if (xml_spec_populate(x, yspec, NULL) < 0) if (xml_bind_yang(x, yspec, NULL) < 0)
goto done; goto done;
if ((ret = netconf_trymerge(x, yspec, xret)) < 0) if ((ret = netconf_trymerge(x, yspec, xret)) < 0)
goto done; goto done;

View file

@ -148,7 +148,7 @@ netconf_input_packet(clicon_handle h,
free(str0); free(str0);
if ((xrpc=xpath_first(xreq, NULL, "//rpc")) != NULL){ if ((xrpc=xpath_first(xreq, NULL, "//rpc")) != NULL){
isrpc++; isrpc++;
if (xml_spec_populate_rpc(xrpc, yspec, NULL) < 0) if (xml_bind_yang_rpc(xrpc, yspec, NULL) < 0)
goto done; goto done;
if ((ret = xml_yang_validate_rpc(h, xrpc, &xret)) < 0) if ((ret = xml_yang_validate_rpc(h, xrpc, &xret)) < 0)
goto done; goto done;

View file

@ -586,8 +586,8 @@ netconf_application_rpc(clicon_handle h,
if (yrpc != NULL){ if (yrpc != NULL){
/* 1. Check xn arguments with input statement. */ /* 1. Check xn arguments with input statement. */
if ((yinput = yang_find(yrpc, Y_INPUT, NULL)) != NULL){ if ((yinput = yang_find(yrpc, Y_INPUT, NULL)) != NULL){
xml_spec_set(xn, yinput); /* needed for xml_spec_populate */ xml_spec_set(xn, yinput); /* needed for xml_bind_yang */
if (xml_spec_populate(xn, yspec, NULL) < 0) if (xml_bind_yang(xn, yspec, NULL) < 0)
goto done; goto done;
if ((ret = xml_yang_validate_all_top(h, xn, &xerr)) < 0) if ((ret = xml_yang_validate_all_top(h, xn, &xerr)) < 0)
goto done; goto done;
@ -618,8 +618,8 @@ netconf_application_rpc(clicon_handle h,
if (0) if (0)
if ((youtput = yang_find(yrpc, Y_OUTPUT, NULL)) != NULL){ if ((youtput = yang_find(yrpc, Y_OUTPUT, NULL)) != NULL){
xoutput=xpath_first(*xret, NULL, "/"); xoutput=xpath_first(*xret, NULL, "/");
xml_spec_set(xoutput, youtput); /* needed for xml_spec_populate */ xml_spec_set(xoutput, youtput); /* needed for xml_bind_yang */
if (xml_spec_populate(xoutput, yspec, NULL) < 0) if (xml_bind_yang(xoutput, yspec, NULL) < 0)
goto done; goto done;
if ((ret = xml_yang_validate_all_top(h, xoutput, &xerr)) < 0) if ((ret = xml_yang_validate_all_top(h, xoutput, &xerr)) < 0)
goto done; goto done;

View file

@ -609,9 +609,9 @@ api_operations_post_output(clicon_handle h,
* (2) Uncertain how validation errors should be logged/handled * (2) Uncertain how validation errors should be logged/handled
*/ */
if (youtput != NULL){ if (youtput != NULL){
xml_spec_set(xoutput, youtput); /* needed for xml_spec_populate */ xml_spec_set(xoutput, youtput); /* needed for xml_bind_yang */
#if 0 #if 0
if (xml_spec_populate(xoutput, yspec, NULL) < 0) if (xml_bind_yang(xoutput, yspec, NULL) < 0)
goto done; goto done;
if ((ret = xml_yang_validate_all(xoutput, &xerr)) < 0) if ((ret = xml_yang_validate_all(xoutput, &xerr)) < 0)
goto done; goto done;
@ -832,7 +832,7 @@ api_operations_post(clicon_handle h,
clicon_log_xml(LOG_DEBUG, xtop, "%s 5. Translate input args:", __FUNCTION__); clicon_log_xml(LOG_DEBUG, xtop, "%s 5. Translate input args:", __FUNCTION__);
#endif #endif
/* 6. Validate outgoing RPC and fill in defaults */ /* 6. Validate outgoing RPC and fill in defaults */
if (xml_spec_populate_rpc(xtop, yspec, NULL) < 0) /* */ if (xml_bind_yang_rpc(xtop, yspec, NULL) < 0) /* */
goto done; goto done;
if ((ret = xml_yang_validate_rpc(h, xtop, &xret)) < 0) if ((ret = xml_yang_validate_rpc(h, xtop, &xret)) < 0)
goto done; goto done;

View file

@ -61,12 +61,12 @@ int xml_namespace_change(cxobj *x, char *namespace, char *prefix);
int xml_default(cxobj *x, void *arg); int xml_default(cxobj *x, void *arg);
int xml_sanity(cxobj *x, void *arg); int xml_sanity(cxobj *x, void *arg);
int xml_non_config_data(cxobj *xt, void *arg); int xml_non_config_data(cxobj *xt, void *arg);
int xml_spec_populate_rpc(cxobj *xrpc, yang_stmt *yspec, cxobj **xerr); int xml_bind_yang_rpc(cxobj *xrpc, yang_stmt *yspec, cxobj **xerr);
int xml_spec_populate_rpc_reply(cxobj *xrpc, char *name, yang_stmt *yspec, cxobj **xerr); int xml_bind_yang_rpc_reply(cxobj *xrpc, char *name, yang_stmt *yspec, cxobj **xerr);
int xml_spec_populate0(cxobj *xt, yang_stmt *yspec, cxobj **xerr); int xml_bind_yang0(cxobj *xt, yang_stmt *yspec, cxobj **xerr);
int xml_spec_populate0_parent(cxobj *xt, cxobj **xerr); int xml_bind_yang0_parent(cxobj *xt, cxobj **xerr);
int xml_spec_populate(cxobj *xt, yang_stmt *yspec, cxobj **xerr); int xml_bind_yang(cxobj *xt, yang_stmt *yspec, cxobj **xerr);
int xml_spec_populate_parent(cxobj *xt, cxobj **xerr); int xml_bind_yang_parent(cxobj *xt, cxobj **xerr);
int xml2xpath(cxobj *x, char **xpath); int xml2xpath(cxobj *x, char **xpath);
int assign_namespaces(cxobj *x0, cxobj *x1, cxobj *x1p); int assign_namespaces(cxobj *x0, cxobj *x1, cxobj *x1p);

View file

@ -1220,7 +1220,7 @@ _json_parse(char *str,
if (ret == 0) if (ret == 0)
goto fail; goto fail;
/* Now assign yang stmts to each XML node /* Now assign yang stmts to each XML node
* XXX should be xml_spec_populate0_parent() sometimes. * XXX should be xml_bind_yang0_parent() sometimes.
*/ */
switch (yb){ switch (yb){
case YB_RPC: case YB_RPC:
@ -1228,13 +1228,13 @@ _json_parse(char *str,
case YB_NONE: case YB_NONE:
break; break;
case YB_PARENT: case YB_PARENT:
if ((ret = xml_spec_populate0_parent(x, xerr)) < 0) if ((ret = xml_bind_yang0_parent(x, xerr)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
failed++; failed++;
break; break;
case YB_TOP: case YB_TOP:
if (xml_spec_populate0(x, yspec, xerr) < 0) if (xml_bind_yang0(x, yspec, xerr) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
failed++; failed++;

View file

@ -270,7 +270,7 @@ clicon_rpc_netconf_xml(clicon_handle h,
xml_find_type(xreply, NULL, "rpc-error", CX_ELMNT) == NULL){ xml_find_type(xreply, NULL, "rpc-error", CX_ELMNT) == NULL){
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);
/* Here use rpc name to bind to yang */ /* Here use rpc name to bind to yang */
if (xml_spec_populate_rpc_reply(xreply, rpcname, yspec, NULL) < 0) if (xml_bind_yang_rpc_reply(xreply, rpcname, yspec, NULL) < 0)
goto done; goto done;
} }
retval = 0; retval = 0;
@ -403,7 +403,7 @@ clicon_rpc_get_config(clicon_handle h,
} }
else{ else{
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);
if ((ret = xml_spec_populate(xd, yspec, &xerr)) < 0) if ((ret = xml_bind_yang(xd, yspec, &xerr)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
if ((xd = xpath_first(xerr, NULL, "rpc-error")) == NULL){ if ((xd = xpath_first(xerr, NULL, "rpc-error")) == NULL){
@ -759,7 +759,7 @@ clicon_rpc_get(clicon_handle h,
} }
else{ else{
yspec = clicon_dbspec_yang(h); yspec = clicon_dbspec_yang(h);
if ((ret = xml_spec_populate(xd, yspec, &xerr)) < 0) if ((ret = xml_bind_yang(xd, yspec, &xerr)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
if ((xd = xpath_first(xerr, NULL, "rpc-error")) == NULL){ if ((xd = xpath_first(xerr, NULL, "rpc-error")) == NULL){

View file

@ -66,9 +66,9 @@
#include "clixon_log.h" #include "clixon_log.h"
#include "clixon_yang.h" #include "clixon_yang.h"
#include "clixon_xml.h" #include "clixon_xml.h"
#include "clixon_options.h" /* xml_spec_populate */ #include "clixon_options.h" /* xml_bind_yang */
#include "clixon_yang_module.h" #include "clixon_yang_module.h"
#include "clixon_xml_map.h" /* xml_spec_populate */ #include "clixon_xml_map.h" /* xml_bind_yang */
#include "clixon_xml_vec.h" #include "clixon_xml_vec.h"
#include "clixon_xml_sort.h" #include "clixon_xml_sort.h"
#include "clixon_xml_io.h" #include "clixon_xml_io.h"

View file

@ -66,9 +66,9 @@
#include "clixon_log.h" #include "clixon_log.h"
#include "clixon_yang.h" #include "clixon_yang.h"
#include "clixon_xml.h" #include "clixon_xml.h"
#include "clixon_options.h" /* xml_spec_populate */ #include "clixon_options.h" /* xml_bind_yang */
#include "clixon_yang_module.h" #include "clixon_yang_module.h"
#include "clixon_xml_map.h" /* xml_spec_populate */ #include "clixon_xml_map.h" /* xml_bind_yang */
#include "clixon_xml_vec.h" #include "clixon_xml_vec.h"
#include "clixon_xml_sort.h" #include "clixon_xml_sort.h"
#include "clixon_xml_nsctx.h" #include "clixon_xml_nsctx.h"
@ -431,7 +431,7 @@ _xml_parse(const char *str,
/* xt:n Has spec /* xt:n Has spec
* x: <a> <-- populate from parent * x: <a> <-- populate from parent
*/ */
if ((ret = xml_spec_populate0_parent(x, xerr)) < 0) if ((ret = xml_bind_yang0_parent(x, xerr)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
failed++; failed++;
@ -448,12 +448,12 @@ _xml_parse(const char *str,
* x: <config> * x: <config>
* <a> <-- populate from modules * <a> <-- populate from modules
*/ */
if ((ret = xml_spec_populate(x, yspec, xerr)) < 0) if ((ret = xml_bind_yang(x, yspec, xerr)) < 0)
goto done; goto done;
} }
else else
#endif #endif
if ((ret = xml_spec_populate0(x, yspec, xerr)) < 0) if ((ret = xml_bind_yang0(x, yspec, xerr)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
failed++; failed++;

View file

@ -1022,134 +1022,6 @@ xml_non_config_data(cxobj *xt,
return retval; return retval;
} }
/*! Find yang spec association of XML node for incoming RPC starting with <rpc>
*
* Incoming RPC has an "input" structure that is not taken care of by xml_spec_populate
* @param[in] xrpc XML rpc node
* @param[in] yspec Yang spec
* @param[out] xerr Reason for failure, or NULL
* @retval 1 OK yang assignment made
* @retval 0 Partial or no yang assigment made (at least one failed) and xerr set
* @retval -1 Error
* The
* @code
* if (xml_spec_populate_rpc(h, x, NULL) < 0)
* err;
* @endcode
* @see xml_spec_populate For other generic cases
* @see xml_spec_populate_rpc_reply
*/
int
xml_spec_populate_rpc(cxobj *xrpc,
yang_stmt *yspec,
cxobj **xerr)
{
int retval = -1;
yang_stmt *yrpc = NULL; /* yang node */
yang_stmt *ymod=NULL; /* yang module */
yang_stmt *yi = NULL; /* input */
cxobj *x;
int ret;
if ((strcmp(xml_name(xrpc), "rpc")) != 0){
clicon_err(OE_UNIX, EINVAL, "RPC expected");
goto done;
}
x = NULL;
while ((x = xml_child_each(xrpc, x, CX_ELMNT)) != NULL) {
if (ys_module_by_xml(yspec, x, &ymod) < 0)
goto done;
if (ymod != NULL)
yrpc = yang_find(ymod, Y_RPC, xml_name(x));
/* Non-strict semantics: loop through all modules to find the node
*/
if (yrpc){
xml_spec_set(x, yrpc);
if ((yi = yang_find(yrpc, Y_INPUT, NULL)) != NULL){
/* xml_spec_populate need to have parent with yang spec for
* recursive population to work. Therefore, assign input yang
* to rpc level although not 100% intuitive */
xml_spec_set(x, yi);
if ((ret = xml_spec_populate_parent(x, xerr)) < 0)
goto done;
if (ret == 0)
goto fail;
}
}
}
retval = 1;
done:
return retval;
fail:
retval = 0;
goto done;
}
/*! Find yang spec association of XML node for outgoing RPC starting with <rpc-reply>
*
* Incoming RPC has an "input" structure that is not taken care of by xml_spec_populate
* @param[in] xrpc XML rpc node
* @param[in] name Name of RPC (not seen in output/reply)
* @param[in] yspec Yang spec
* @param[out] xerr Reason for failure, or NULL
* @retval 1 OK yang assignment made
* @retval 0 Partial or no yang assigment made (at least one failed) and xerr set
* @retval -1 Error
*
* @code
* if (xml_spec_populate_rpc_reply(x, "get-config", yspec, name) < 0)
* err;
* @endcode
* @see xml_spec_populate For other generic cases
*/
int
xml_spec_populate_rpc_reply(cxobj *xrpc,
char *name,
yang_stmt *yspec,
cxobj **xerr)
{
int retval = -1;
yang_stmt *yrpc = NULL; /* yang node */
yang_stmt *ymod=NULL; /* yang module */
yang_stmt *yo = NULL; /* output */
cxobj *x;
int ret;
if (strcmp(xml_name(xrpc), "rpc-reply")){
clicon_err(OE_UNIX, EINVAL, "rpc-reply expected");
goto done;
}
x = NULL;
while ((x = xml_child_each(xrpc, x, CX_ELMNT)) != NULL) {
if (ys_module_by_xml(yspec, x, &ymod) < 0)
goto done;
if (ymod == NULL)
continue;
if ((yrpc = yang_find(ymod, Y_RPC, name)) == NULL)
continue;
// xml_spec_set(xrpc, yrpc);
if ((yo = yang_find(yrpc, Y_OUTPUT, NULL)) == NULL)
continue;
/* xml_spec_populate need to have parent with yang spec for
* recursive population to work. Therefore, assign input yang
* to rpc level although not 100% intuitive */
break;
}
if (yo != NULL){
xml_spec_set(xrpc, yo);
if ((ret = xml_spec_populate(xrpc, yspec, xerr)) < 0)
goto done;
if (ret == 0)
goto fail;
}
retval = 1;
done:
return retval;
fail:
retval = 0;
goto done;
}
/*! Associate XML node x with x:s parents yang:s matching child /*! Associate XML node x with x:s parents yang:s matching child
* *
* @param[in] xt XML tree node * @param[in] xt XML tree node
@ -1329,20 +1201,20 @@ strip_whitespace(cxobj *xt)
* @retval 0 Partial or no yang assigment made (at least one failed) and xerr set * @retval 0 Partial or no yang assigment made (at least one failed) and xerr set
* @retval -1 Error * @retval -1 Error
* @code * @code
* if (xml_spec_populate(x, yspec, NULL) < 0) * if (xml_bind_yang(x, yspec, NULL) < 0)
* err; * err;
* @endcode * @endcode
* @note For subs to anyxml nodes will not have spec set * @note For subs to anyxml nodes will not have spec set
* There are several functions in the API family * There are several functions in the API family
* @see xml_spec_populate_rpc for incoming rpc * @see xml_bind_yang_rpc for incoming rpc
* @see xml_spec_populate_parent Not top-level and parent is properly yang populated * @see xml_bind_yang_parent Not top-level and parent is properly yang populated
* @see xml_spec_populate0 If the calling xml object should also be populated * @see xml_bind_yang0 If the calling xml object should also be populated
* @see xml_spec_populate0_parent * @see xml_bind_yang0_parent
*/ */
int int
xml_spec_populate(cxobj *xt, xml_bind_yang(cxobj *xt,
yang_stmt *yspec, yang_stmt *yspec,
cxobj **xerr) cxobj **xerr)
{ {
int retval = -1; int retval = -1;
cxobj *xc; /* xml child */ cxobj *xc; /* xml child */
@ -1352,7 +1224,7 @@ xml_spec_populate(cxobj *xt,
strip_whitespace(xt); strip_whitespace(xt);
xc = NULL; /* Apply on children */ xc = NULL; /* Apply on children */
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) { while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) {
if ((ret = xml_spec_populate0(xc, yspec, xerr)) < 0) if ((ret = xml_bind_yang0(xc, yspec, xerr)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
failed++; failed++;
@ -1367,8 +1239,8 @@ xml_spec_populate(cxobj *xt,
* Populate xt:s children outgoing from that xt is populated * Populate xt:s children outgoing from that xt is populated
*/ */
int int
xml_spec_populate_parent(cxobj *xt, xml_bind_yang_parent(cxobj *xt,
cxobj **xerr) cxobj **xerr)
{ {
int retval = -1; int retval = -1;
cxobj *xc; /* xml child */ cxobj *xc; /* xml child */
@ -1378,7 +1250,7 @@ xml_spec_populate_parent(cxobj *xt,
strip_whitespace(xt); strip_whitespace(xt);
xc = NULL; /* Apply on children */ xc = NULL; /* Apply on children */
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) { while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) {
if ((ret = xml_spec_populate0_parent(xc, xerr)) < 0) if ((ret = xml_bind_yang0_parent(xc, xerr)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
failed++; failed++;
@ -1399,9 +1271,9 @@ xml_spec_populate_parent(cxobj *xt,
* Populate xt as top-level node * Populate xt as top-level node
*/ */
int int
xml_spec_populate0(cxobj *xt, xml_bind_yang0(cxobj *xt,
yang_stmt *yspec, yang_stmt *yspec,
cxobj **xerr) cxobj **xerr)
{ {
int retval = -1; int retval = -1;
cxobj *xc; /* xml child */ cxobj *xc; /* xml child */
@ -1415,7 +1287,7 @@ xml_spec_populate0(cxobj *xt,
strip_whitespace(xt); strip_whitespace(xt);
xc = NULL; /* Apply on children */ xc = NULL; /* Apply on children */
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) { while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) {
if ((ret = xml_spec_populate0_parent(xc, xerr)) < 0) if ((ret = xml_bind_yang0_parent(xc, xerr)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
failed++; failed++;
@ -1435,8 +1307,8 @@ xml_spec_populate0(cxobj *xt,
* Populate xt as if xt:s parent is populated * Populate xt as if xt:s parent is populated
*/ */
int int
xml_spec_populate0_parent(cxobj *xt, xml_bind_yang0_parent(cxobj *xt,
cxobj **xerr) cxobj **xerr)
{ {
int retval = -1; int retval = -1;
cxobj *xc; /* xml child */ cxobj *xc; /* xml child */
@ -1450,7 +1322,7 @@ xml_spec_populate0_parent(cxobj *xt,
strip_whitespace(xt); strip_whitespace(xt);
xc = NULL; /* Apply on children */ xc = NULL; /* Apply on children */
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) { while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) {
if ((ret = xml_spec_populate0_parent(xc, xerr)) < 0) if ((ret = xml_bind_yang0_parent(xc, xerr)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 0)
failed++; failed++;
@ -1465,6 +1337,134 @@ xml_spec_populate0_parent(cxobj *xt,
goto done; goto done;
} }
/*! Find yang spec association of XML node for incoming RPC starting with <rpc>
*
* Incoming RPC has an "input" structure that is not taken care of by xml_bind_yang
* @param[in] xrpc XML rpc node
* @param[in] yspec Yang spec
* @param[out] xerr Reason for failure, or NULL
* @retval 1 OK yang assignment made
* @retval 0 Partial or no yang assigment made (at least one failed) and xerr set
* @retval -1 Error
* The
* @code
* if (xml_bind_yang_rpc(h, x, NULL) < 0)
* err;
* @endcode
* @see xml_bind_yang For other generic cases
* @see xml_bind_yang_rpc_reply
*/
int
xml_bind_yang_rpc(cxobj *xrpc,
yang_stmt *yspec,
cxobj **xerr)
{
int retval = -1;
yang_stmt *yrpc = NULL; /* yang node */
yang_stmt *ymod=NULL; /* yang module */
yang_stmt *yi = NULL; /* input */
cxobj *x;
int ret;
if ((strcmp(xml_name(xrpc), "rpc")) != 0){
clicon_err(OE_UNIX, EINVAL, "RPC expected");
goto done;
}
x = NULL;
while ((x = xml_child_each(xrpc, x, CX_ELMNT)) != NULL) {
if (ys_module_by_xml(yspec, x, &ymod) < 0)
goto done;
if (ymod != NULL)
yrpc = yang_find(ymod, Y_RPC, xml_name(x));
/* Non-strict semantics: loop through all modules to find the node
*/
if (yrpc){
xml_spec_set(x, yrpc);
if ((yi = yang_find(yrpc, Y_INPUT, NULL)) != NULL){
/* xml_bind_yang need to have parent with yang spec for
* recursive population to work. Therefore, assign input yang
* to rpc level although not 100% intuitive */
xml_spec_set(x, yi);
if ((ret = xml_bind_yang_parent(x, xerr)) < 0)
goto done;
if (ret == 0)
goto fail;
}
}
}
retval = 1;
done:
return retval;
fail:
retval = 0;
goto done;
}
/*! Find yang spec association of XML node for outgoing RPC starting with <rpc-reply>
*
* Incoming RPC has an "input" structure that is not taken care of by xml_bind_yang
* @param[in] xrpc XML rpc node
* @param[in] name Name of RPC (not seen in output/reply)
* @param[in] yspec Yang spec
* @param[out] xerr Reason for failure, or NULL
* @retval 1 OK yang assignment made
* @retval 0 Partial or no yang assigment made (at least one failed) and xerr set
* @retval -1 Error
*
* @code
* if (xml_bind_yang_rpc_reply(x, "get-config", yspec, name) < 0)
* err;
* @endcode
* @see xml_bind_yang For other generic cases
*/
int
xml_bind_yang_rpc_reply(cxobj *xrpc,
char *name,
yang_stmt *yspec,
cxobj **xerr)
{
int retval = -1;
yang_stmt *yrpc = NULL; /* yang node */
yang_stmt *ymod=NULL; /* yang module */
yang_stmt *yo = NULL; /* output */
cxobj *x;
int ret;
if (strcmp(xml_name(xrpc), "rpc-reply")){
clicon_err(OE_UNIX, EINVAL, "rpc-reply expected");
goto done;
}
x = NULL;
while ((x = xml_child_each(xrpc, x, CX_ELMNT)) != NULL) {
if (ys_module_by_xml(yspec, x, &ymod) < 0)
goto done;
if (ymod == NULL)
continue;
if ((yrpc = yang_find(ymod, Y_RPC, name)) == NULL)
continue;
// xml_spec_set(xrpc, yrpc);
if ((yo = yang_find(yrpc, Y_OUTPUT, NULL)) == NULL)
continue;
/* xml_bind_yang need to have parent with yang spec for
* recursive population to work. Therefore, assign input yang
* to rpc level although not 100% intuitive */
break;
}
if (yo != NULL){
xml_spec_set(xrpc, yo);
if ((ret = xml_bind_yang(xrpc, yspec, xerr)) < 0)
goto done;
if (ret == 0)
goto fail;
}
retval = 1;
done:
return retval;
fail:
retval = 0;
goto done;
}
/*! Given an XML node, build an xpath to root, internal function /*! Given an XML node, build an xpath to root, internal function
* @retval 0 OK * @retval 0 OK
* @retval -1 Error. eg XML malformed * @retval -1 Error. eg XML malformed

View file

@ -270,7 +270,7 @@ xml_parse_bslash(clixon_xml_yacc *xy,
* So the rule is: if there is at least on element, then remove all bodies. * So the rule is: if there is at least on element, then remove all bodies.
* See also code in xml_parse_whitespace * See also code in xml_parse_whitespace
* But there is more: when YANG is assigned, if not leaf/leaf-lists, then all contents should * But there is more: when YANG is assigned, if not leaf/leaf-lists, then all contents should
* be stripped, see xml_spec_populate() * be stripped, see xml_bind_yang()
*/ */
xc = NULL; xc = NULL;
while ((xc = xml_child_each(x, xc, CX_ELMNT)) != NULL) while ((xc = xml_child_each(x, xc, CX_ELMNT)) != NULL)

View file

@ -152,7 +152,7 @@ main(int argc, char **argv)
clicon_err(OE_XML, 0, "Parsing base xml: %s", x0str); clicon_err(OE_XML, 0, "Parsing base xml: %s", x0str);
goto done; goto done;
} }
if (xml_spec_populate(x0, yspec, NULL) < 0) if (xml_bind_yang(x0, yspec, NULL) < 0)
goto done; goto done;
if ((xb = xpath_first(x0, NULL, "%s", xpath)) == NULL){ if ((xb = xpath_first(x0, NULL, "%s", xpath)) == NULL){
clicon_err(OE_XML, 0, "xpath: %s not found in x0", xpath); clicon_err(OE_XML, 0, "xpath: %s not found in x0", xpath);
@ -167,7 +167,7 @@ main(int argc, char **argv)
clicon_err(OE_XML, 0, "Parsing insert xml: %s", xistr); clicon_err(OE_XML, 0, "Parsing insert xml: %s", xistr);
goto done; goto done;
} }
if (xml_spec_populate(xi, yspec, NULL) < 0) if (xml_bind_yang(xi, yspec, NULL) < 0)
goto done; goto done;
if ((xi = xpath_first(xi, NULL, "%s", xpath)) == NULL){ if ((xi = xpath_first(xi, NULL, "%s", xpath)) == NULL){
clicon_err(OE_XML, 0, "xpath: %s not found in xi", xpath); clicon_err(OE_XML, 0, "xpath: %s not found in xi", xpath);

View file

@ -220,7 +220,7 @@ main(int argc,
/* Validate XML as well */ /* Validate XML as well */
if (yang_file_dir){ if (yang_file_dir){
/* Populate */ /* Populate */
if (xml_spec_populate(x, yspec, NULL) < 0) if (xml_bind_yang(x, yspec, NULL) < 0)
goto done; goto done;
/* Add default values */ /* Add default values */
if (xml_apply(x, CX_ELMNT, xml_default, h) < 0) if (xml_apply(x, CX_ELMNT, xml_default, h) < 0)

View file

@ -288,7 +288,7 @@ main(int argc,
/* Validate XML as well */ /* Validate XML as well */
if (yang_file_dir){ if (yang_file_dir){
/* Populate */ /* Populate */
if (xml_spec_populate(x0, yspec, NULL) < 0) if (xml_bind_yang(x0, yspec, NULL) < 0)
goto done; goto done;
/* Sort */ /* Sort */
if (xml_apply(x0, CX_ELMNT, xml_sort, h) < 0) if (xml_apply(x0, CX_ELMNT, xml_sort, h) < 0)