XML creation and parse API changes
This commit is contained in:
parent
056b5c97dd
commit
4742fde1e9
21 changed files with 309 additions and 258 deletions
19
CHANGELOG.md
19
CHANGELOG.md
|
|
@ -12,16 +12,15 @@
|
||||||
|
|
||||||
* Moved XML_CHILD_HASH to variable instead of constant.
|
* Moved XML_CHILD_HASH to variable instead of constant.
|
||||||
|
|
||||||
* Added yang to XML API
|
* Changed XML creation and parse API for more coherency and closer YANG/XML integration. A new yang spec parameter has been added (default NULL) and functions have been removed and renamed. You may need to change the XML calls as follows.
|
||||||
|
* xml_new(name, parent) --> xml_new(name, xn_parent, yspec)
|
||||||
* xml_new(char *name, cxobj *xn_parent) --> xml_new(char *name, cxobj *xn_parent, void *spec)
|
* xml_new_spec(name, parent, spec) --> xml_new(name, parent, spec)
|
||||||
* xml_new_spec(char *name, cxobj *xn_parent, void *spec) --> xml_new(char *name, cxobj *xn_parent, void *spec)
|
* clicon_xml_parse_file(fd, &xt, endtag) --> xml_parse_file(fd, endtag, yspec, &xt)
|
||||||
* clicon_xml_parse_string --> clicon_xml_parse_str
|
* clicon_xml_parse_string(&str, &xt) --> xml_parse_string(str, yspec, &xt)
|
||||||
* clicon_xml_parse_file(int fd, cxobj **xml_top, char *endtag) --> clicon_xml_parse_file(int fd, char *endtag, yang_spec *yspec, cxobj **xt)
|
* xml_parse(str, xt) --> xml_parse_string(str, yspec, &xt)
|
||||||
* clicon_xml_parse_str(char *str, cxobj **xml_top) --> clicon_xml_parse_str(char *str, yang_spec *yspec, cxobj **xml_top)
|
* clicon_xml_parse(&xt, format, ...) --> xml_parse_va(&xt, yspec, format, ...)
|
||||||
* clicon_xml_parse(cxobj **cxtop, char *format, ...) --> clicon_xml_parse(cxobj **cxtop, yang_spec *yspec, char *format, ...)
|
* clicon_xml_parse_str(str, &xt) --> xml_parse_string(str, yspec, &xt)
|
||||||
* xml_parse(char *str, cxobj *xt) --> xml_parse(char *str, yang_spec *yspec, cxobj *xt);
|
|
||||||
|
|
||||||
## 3.3.3 (25 November 2017)
|
## 3.3.3 (25 November 2017)
|
||||||
|
|
||||||
Thanks to Matthew Smith, Joe Loeliger at Netgate; Fredrik Pettai at
|
Thanks to Matthew Smith, Joe Loeliger at Netgate; Fredrik Pettai at
|
||||||
|
|
|
||||||
|
|
@ -296,7 +296,7 @@ rundb_main(clicon_handle h,
|
||||||
clicon_err(OE_UNIX, errno, "open(%s)", extraxml_file);
|
clicon_err(OE_UNIX, errno, "open(%s)", extraxml_file);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (clicon_xml_parse_file(fd, &xt, "</clicon>") < 0)
|
if (xml_parse_file(fd, &xt, "</clicon>") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xn = xml_child_i(xt, 0)) != NULL)
|
if ((xn = xml_child_i(xt, 0)) != NULL)
|
||||||
if (xmldb_put(h, "tmp", OP_MERGE, xn) < 0)
|
if (xmldb_put(h, "tmp", OP_MERGE, xn) < 0)
|
||||||
|
|
@ -442,7 +442,7 @@ load_extraxml(clicon_handle h,
|
||||||
clicon_err(OE_UNIX, errno, "open(%s)", filename);
|
clicon_err(OE_UNIX, errno, "open(%s)", filename);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (clicon_xml_parse_file(fd, "</config>", NULL, &xt) < 0)
|
if (xml_parse_file(fd, "</config>", NULL, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Replace parent w first child */
|
/* Replace parent w first child */
|
||||||
if (xml_rootchild(xt, 0, &xt) < 0)
|
if (xml_rootchild(xt, 0, &xt) < 0)
|
||||||
|
|
@ -827,7 +827,7 @@ main(int argc, char **argv)
|
||||||
if (xmldb_setopt(h, "yangspec", clicon_dbspec_yang(h)) < 0)
|
if (xmldb_setopt(h, "yangspec", clicon_dbspec_yang(h)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xml_cache = clicon_option_bool(h, "CLICON_XMLDB_CACHE")) >= 0)
|
if ((xml_cache = clicon_option_bool(h, "CLICON_XMLDB_CACHE")) >= 0)
|
||||||
if (xmldb_setopt(h, "xml_cache", (void*)xml_cache) < 0)
|
if (xmldb_setopt(h, "xml_cache", (void*)(intptr_t)xml_cache) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* If startup mode is not defined, eg via OPTION or -s, assume old method */
|
/* If startup mode is not defined, eg via OPTION or -s, assume old method */
|
||||||
startup_mode = clicon_startup_mode(h);
|
startup_mode = clicon_startup_mode(h);
|
||||||
|
|
|
||||||
|
|
@ -746,7 +746,7 @@ load_config_file(clicon_handle h,
|
||||||
clicon_err(OE_UNIX, errno, "%s: open(%s)", __FUNCTION__, filename);
|
clicon_err(OE_UNIX, errno, "%s: open(%s)", __FUNCTION__, filename);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (clicon_xml_parse_file(fd, "</clicon>", NULL, &xt) < 0)
|
if (xml_parse_file(fd, "</clicon>", NULL, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xt == NULL)
|
if (xt == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ netconf_output(int s,
|
||||||
clicon_debug(1, "SEND %s", msg);
|
clicon_debug(1, "SEND %s", msg);
|
||||||
if (debug > 1){ /* XXX: below only works to stderr, clicon_debug may log to syslog */
|
if (debug > 1){ /* XXX: below only works to stderr, clicon_debug may log to syslog */
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
if (clicon_xml_parse_str(buf, NULL, &xt) == 0){
|
if (xml_parse_string(buf, NULL, &xt) == 0){
|
||||||
clicon_xml2file(stderr, xml_child_i(xt, 0), 0, 0);
|
clicon_xml2file(stderr, xml_child_i(xt, 0), 0, 0);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
xml_free(xt);
|
xml_free(xt);
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ process_incoming_packet(clicon_handle h,
|
||||||
}
|
}
|
||||||
str = str0;
|
str = str0;
|
||||||
/* Parse incoming XML message */
|
/* Parse incoming XML message */
|
||||||
if (clicon_xml_parse_str(str, NULL, &xreq) < 0){
|
if (xml_parse_string(str, NULL, &xreq) < 0){
|
||||||
if ((cbret = cbuf_new()) == NULL){
|
if ((cbret = cbuf_new()) == NULL){
|
||||||
cprintf(cbret, "<rpc-reply><rpc-error>"
|
cprintf(cbret, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,9 @@ catch:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! See if there is any callback registered for this tag
|
/*! See if there is any callback registered for this tag
|
||||||
|
*
|
||||||
|
* Look for local (client-side) netconf plugins. This feature may no
|
||||||
|
* longer be necessary as generic RPC:s should be handled by backend.
|
||||||
*
|
*
|
||||||
* @param[in] h clicon handle
|
* @param[in] h clicon handle
|
||||||
* @param[in] xn Sub-tree (under xorig) at child of rpc: <rpc><xn></rpc>.
|
* @param[in] xn Sub-tree (under xorig) at child of rpc: <rpc><xn></rpc>.
|
||||||
|
|
@ -214,13 +217,7 @@ netconf_plugin_callbacks(clicon_handle h,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
netconf_reg_t *nreg;
|
netconf_reg_t *nreg;
|
||||||
yang_spec *yspec = NULL; /* application yspec */
|
|
||||||
yang_stmt *yrpc;
|
|
||||||
yang_stmt *yinput;
|
|
||||||
yang_stmt *youtput;
|
|
||||||
cxobj *xoutput;
|
|
||||||
cbuf *cb = NULL;
|
|
||||||
|
|
||||||
if (deps != NULL){
|
if (deps != NULL){
|
||||||
nreg = deps;
|
nreg = deps;
|
||||||
do {
|
do {
|
||||||
|
|
@ -233,70 +230,8 @@ netconf_plugin_callbacks(clicon_handle h,
|
||||||
nreg = NEXTQ(netconf_reg_t *, nreg);
|
nreg = NEXTQ(netconf_reg_t *, nreg);
|
||||||
} while (nreg != deps);
|
} while (nreg != deps);
|
||||||
}
|
}
|
||||||
/* First check system / netconf RPC:s */
|
|
||||||
if ((cb = cbuf_new()) == NULL){
|
|
||||||
clicon_err(OE_UNIX, 0, "cbuf_new");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* create absolute path */
|
|
||||||
if (xml_namespace(xn))
|
|
||||||
cprintf(cb, "/%s:%s", xml_namespace(xn), xml_name(xn));
|
|
||||||
else
|
|
||||||
cprintf(cb, "/nc:%s", xml_name(xn)); /* Hardcoded for netconf */
|
|
||||||
/* Find yang rpc statement, return yang rpc statement if found */
|
|
||||||
if (yrpc == NULL){
|
|
||||||
/* Then check application RPC */
|
|
||||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
|
||||||
clicon_err(OE_YANG, ENOENT, "No yang spec");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
cbuf_reset(cb);
|
|
||||||
if (xml_namespace(xn))
|
|
||||||
cprintf(cb, "/%s:%s", xml_namespace(xn), xml_name(xn));
|
|
||||||
else
|
|
||||||
cprintf(cb, "/%s", xml_name(xn)); /* XXX not accepdted by below */
|
|
||||||
/* Find yang rpc statement, return yang rpc statement if found */
|
|
||||||
if (yang_abs_schema_nodeid(yspec, cbuf_get(cb), &yrpc) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* Check if found */
|
|
||||||
if (yrpc != NULL){
|
|
||||||
if ((yinput = yang_find((yang_node*)yrpc, Y_INPUT, NULL)) != NULL){
|
|
||||||
xml_spec_set(xn, yinput); /* needed for xml_spec_populate */
|
|
||||||
if (xml_apply(xn, CX_ELMNT, xml_spec_populate, yinput) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_apply(xn, CX_ELMNT,
|
|
||||||
(xml_applyfn_t*)xml_yang_validate_all, NULL) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_yang_validate_add(xn, NULL) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* 1. Check xn arguments with input statement.
|
|
||||||
* 2. Send to backend as clicon_msg-encode()
|
|
||||||
* 3. In backend to similar but there call actual backend
|
|
||||||
*/
|
|
||||||
if (clicon_rpc_netconf_xml(h, xml_parent(xn), xret, NULL) < 0)
|
|
||||||
goto done;
|
|
||||||
/* Sanity check of outgoing XML */
|
|
||||||
if ((youtput = yang_find((yang_node*)yrpc, Y_OUTPUT, NULL)) != NULL){
|
|
||||||
xoutput=xpath_first(*xret, "/");
|
|
||||||
xml_spec_set(xoutput, youtput); /* needed for xml_spec_populate */
|
|
||||||
if (xml_apply(xoutput, CX_ELMNT, xml_spec_populate, youtput) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_apply(xoutput, CX_ELMNT,
|
|
||||||
(xml_applyfn_t*)xml_yang_validate_all, NULL) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_yang_validate_add(xoutput, NULL) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
retval = 1; /* handled by callback */
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (cb)
|
|
||||||
cbuf_free(cb);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ netconf_get_config(clicon_handle h,
|
||||||
cxobj *xconf;
|
cxobj *xconf;
|
||||||
|
|
||||||
if ((source = netconf_get_target(xn, "source")) == NULL){
|
if ((source = netconf_get_target(xn, "source")) == NULL){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>missing-element</error-tag>"
|
"<error-tag>missing-element</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -163,7 +163,7 @@ netconf_get_config(clicon_handle h,
|
||||||
/* xml_filter removes parts of xml tree not matching */
|
/* xml_filter removes parts of xml tree not matching */
|
||||||
if ((strcmp(xml_name(xfilterconf), xml_name(xconf))!=0) ||
|
if ((strcmp(xml_name(xfilterconf), xml_name(xconf))!=0) ||
|
||||||
xml_filter(xfilterconf, xconf) < 0){
|
xml_filter(xfilterconf, xconf) < 0){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-type>applicatio</error-type>"
|
"<error-type>applicatio</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -173,7 +173,7 @@ netconf_get_config(clicon_handle h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-type>applicatio</error-type>"
|
"<error-type>applicatio</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -241,7 +241,7 @@ get_edit_opts(cxobj *xn,
|
||||||
retval = 1; /* hunky dory */
|
retval = 1; /* hunky dory */
|
||||||
return retval;
|
return retval;
|
||||||
parerr: /* parameter error, xret set */
|
parerr: /* parameter error, xret set */
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>invalid-value</error-tag>"
|
"<error-tag>invalid-value</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -317,7 +317,7 @@ netconf_edit_config(clicon_handle h,
|
||||||
/* must have target, and it should be candidate */
|
/* must have target, and it should be candidate */
|
||||||
if ((target = netconf_get_target(xn, "target")) == NULL ||
|
if ((target = netconf_get_target(xn, "target")) == NULL ||
|
||||||
strcmp(target, "candidate")){
|
strcmp(target, "candidate")){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>missing-element</error-tag>"
|
"<error-tag>missing-element</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -329,7 +329,7 @@ netconf_edit_config(clicon_handle h,
|
||||||
if ((xfilter = xpath_first(xn, "filter")) != NULL) {
|
if ((xfilter = xpath_first(xn, "filter")) != NULL) {
|
||||||
if ((ftype = xml_find_value(xfilter, "type")) != NULL)
|
if ((ftype = xml_find_value(xfilter, "type")) != NULL)
|
||||||
if (strcmp(ftype,"restconf")){
|
if (strcmp(ftype,"restconf")){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>invalid-value</error-tag>"
|
"<error-tag>invalid-value</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -339,7 +339,7 @@ netconf_edit_config(clicon_handle h,
|
||||||
}
|
}
|
||||||
if ((x = xpath_first(xn, "default-operation")) != NULL){
|
if ((x = xpath_first(xn, "default-operation")) != NULL){
|
||||||
if (xml_operation(xml_body(x), &operation) < 0){
|
if (xml_operation(xml_body(x), &operation) < 0){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>invalid-value</error-tag>"
|
"<error-tag>invalid-value</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -353,7 +353,7 @@ netconf_edit_config(clicon_handle h,
|
||||||
goto ok;
|
goto ok;
|
||||||
/* not supported opts */
|
/* not supported opts */
|
||||||
if (testopt!=TEST_THEN_SET || erropt!=STOP_ON_ERROR){
|
if (testopt!=TEST_THEN_SET || erropt!=STOP_ON_ERROR){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-not-supported</error-tag>"
|
"<error-tag>operation-not-supported</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -403,7 +403,7 @@ netconf_copy_config(clicon_handle h,
|
||||||
char *target; /* filenames */
|
char *target; /* filenames */
|
||||||
|
|
||||||
if ((source = netconf_get_target(xn, "source")) == NULL){
|
if ((source = netconf_get_target(xn, "source")) == NULL){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>missing-element</error-tag>"
|
"<error-tag>missing-element</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -412,7 +412,7 @@ netconf_copy_config(clicon_handle h,
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
if ((target = netconf_get_target(xn, "target")) == NULL){
|
if ((target = netconf_get_target(xn, "target")) == NULL){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>missing-element</error-tag>"
|
"<error-tag>missing-element</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -450,7 +450,7 @@ netconf_delete_config(clicon_handle h,
|
||||||
|
|
||||||
if ((target = netconf_get_target(xn, "target")) == NULL ||
|
if ((target = netconf_get_target(xn, "target")) == NULL ||
|
||||||
strcmp(target, "running")==0){
|
strcmp(target, "running")==0){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>missing-element</error-tag>"
|
"<error-tag>missing-element</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -486,7 +486,7 @@ netconf_lock(clicon_handle h,
|
||||||
char *target;
|
char *target;
|
||||||
|
|
||||||
if ((target = netconf_get_target(xn, "target")) == NULL){
|
if ((target = netconf_get_target(xn, "target")) == NULL){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>missing-element</error-tag>"
|
"<error-tag>missing-element</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -566,7 +566,7 @@ netconf_get(clicon_handle h,
|
||||||
/* xml_filter removes parts of xml tree not matching */
|
/* xml_filter removes parts of xml tree not matching */
|
||||||
if ((strcmp(xml_name(xfilterconf), xml_name(xconf))!=0) ||
|
if ((strcmp(xml_name(xfilterconf), xml_name(xconf))!=0) ||
|
||||||
xml_filter(xfilterconf, xconf) < 0){
|
xml_filter(xfilterconf, xconf) < 0){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-type>applicatio</error-type>"
|
"<error-type>applicatio</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -576,7 +576,7 @@ netconf_get(clicon_handle h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-type>applicatio</error-type>"
|
"<error-type>applicatio</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -627,7 +627,7 @@ netconf_kill_session(clicon_handle h,
|
||||||
cxobj *xs;
|
cxobj *xs;
|
||||||
|
|
||||||
if ((xs = xpath_first(xn, "//session-id")) == NULL){
|
if ((xs = xpath_first(xn, "//session-id")) == NULL){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>missing-element</error-tag>"
|
"<error-tag>missing-element</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -658,7 +658,7 @@ netconf_validate(clicon_handle h,
|
||||||
char *target;
|
char *target;
|
||||||
|
|
||||||
if ((target = netconf_get_target(xn, "source")) == NULL){
|
if ((target = netconf_get_target(xn, "source")) == NULL){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>missing-element</error-tag>"
|
"<error-tag>missing-element</error-tag>"
|
||||||
"<error-type>protocol</error-type>"
|
"<error-type>protocol</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -826,7 +826,7 @@ netconf_create_subscription(clicon_handle h,
|
||||||
if ((xfilter = xpath_first(xn, "//filter")) != NULL){
|
if ((xfilter = xpath_first(xn, "//filter")) != NULL){
|
||||||
if ((ftype = xml_find_value(xfilter, "type")) != NULL){
|
if ((ftype = xml_find_value(xfilter, "type")) != NULL){
|
||||||
if (strcmp(ftype, "xpath") != 0){
|
if (strcmp(ftype, "xpath") != 0){
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-type>application</error-type>"
|
"<error-type>application</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
@ -850,6 +850,92 @@ netconf_create_subscription(clicon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! See if there is any callback registered for this tag
|
||||||
|
*
|
||||||
|
* @param[in] h clicon handle
|
||||||
|
* @param[in] xn Sub-tree (under xorig) at child of rpc: <rpc><xn></rpc>.
|
||||||
|
* @param[out] xret Return XML, error or OK
|
||||||
|
*
|
||||||
|
* @retval -1 Error
|
||||||
|
* @retval 0 OK, not found handler.
|
||||||
|
* @retval 1 OK, handler called
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
netconf_application_rpc(clicon_handle h,
|
||||||
|
cxobj *xn,
|
||||||
|
cxobj **xret)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
yang_spec *yspec = NULL; /* application yspec */
|
||||||
|
yang_stmt *yrpc = NULL;
|
||||||
|
yang_stmt *yinput;
|
||||||
|
yang_stmt *youtput;
|
||||||
|
cxobj *xoutput;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
|
/* First check system / netconf RPC:s */
|
||||||
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, 0, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* Find yang rpc statement, return yang rpc statement if found
|
||||||
|
Check application RPC */
|
||||||
|
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
||||||
|
clicon_err(OE_YANG, ENOENT, "No yang spec");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cbuf_reset(cb);
|
||||||
|
// if (xml_namespace(xn))
|
||||||
|
cprintf(cb, "/%s:%s", xml_namespace(xn), xml_name(xn));
|
||||||
|
// else
|
||||||
|
// cprintf(cb, "/%s", xml_name(xn)); /* XXX not accepdted by below */
|
||||||
|
/* Find yang rpc statement, return yang rpc statement if found */
|
||||||
|
if (yang_abs_schema_nodeid(yspec, cbuf_get(cb), &yrpc) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Check if found */
|
||||||
|
if (yrpc != NULL){
|
||||||
|
if ((yinput = yang_find((yang_node*)yrpc, Y_INPUT, NULL)) != NULL){
|
||||||
|
xml_spec_set(xn, yinput); /* needed for xml_spec_populate */
|
||||||
|
if (xml_apply(xn, CX_ELMNT, xml_spec_populate, yinput) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xml_apply(xn, CX_ELMNT,
|
||||||
|
(xml_applyfn_t*)xml_yang_validate_all, NULL) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xml_yang_validate_add(xn, NULL) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 1. Check xn arguments with input statement.
|
||||||
|
* 2. Send to backend as clicon_msg-encode()
|
||||||
|
* 3. In backend to similar but there call actual backend
|
||||||
|
*/
|
||||||
|
if (clicon_rpc_netconf_xml(h, xml_parent(xn), xret, NULL) < 0)
|
||||||
|
goto done;
|
||||||
|
/* Sanity check of outgoing XML */
|
||||||
|
if ((youtput = yang_find((yang_node*)yrpc, Y_OUTPUT, NULL)) != NULL){
|
||||||
|
xoutput=xpath_first(*xret, "/");
|
||||||
|
xml_spec_set(xoutput, youtput); /* needed for xml_spec_populate */
|
||||||
|
if (xml_apply(xoutput, CX_ELMNT, xml_spec_populate, youtput) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xml_apply(xoutput, CX_ELMNT,
|
||||||
|
(xml_applyfn_t*)xml_yang_validate_all, NULL) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xml_yang_validate_add(xoutput, NULL) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 1; /* handled by callback */
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! The central netconf rpc dispatcher. Look at first tag and dispach to sub-functions.
|
/*! The central netconf rpc dispatcher. Look at first tag and dispach to sub-functions.
|
||||||
* Call plugin handler if tag not found. If not handled by any handler, return
|
* Call plugin handler if tag not found. If not handled by any handler, return
|
||||||
* error.
|
* error.
|
||||||
|
|
@ -932,10 +1018,16 @@ netconf_rpc_dispatch(clicon_handle h,
|
||||||
}
|
}
|
||||||
/* Others */
|
/* Others */
|
||||||
else {
|
else {
|
||||||
|
/* Look for local (client-side) netconf plugins. This feature may no
|
||||||
|
* longer be necessary as generic RPC:s should be handled by backend.
|
||||||
|
*/
|
||||||
if ((retval = netconf_plugin_callbacks(h, xe, xret)) < 0)
|
if ((retval = netconf_plugin_callbacks(h, xe, xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (retval == 0)
|
||||||
|
if ((retval = netconf_application_rpc(h, xe, xret)) < 0)
|
||||||
|
goto done;
|
||||||
if (retval == 0){ /* not handled by callback */
|
if (retval == 0){ /* not handled by callback */
|
||||||
clicon_xml_parse(xret, NULL, "<rpc-reply><rpc-error>"
|
xml_parse_va(xret, NULL, "<rpc-reply><rpc-error>"
|
||||||
"<error-tag>operation-failed</error-tag>"
|
"<error-tag>operation-failed</error-tag>"
|
||||||
"<error-type>rpc</error-type>"
|
"<error-type>rpc</error-type>"
|
||||||
"<error-severity>error</error-severity>"
|
"<error-severity>error</error-severity>"
|
||||||
|
|
|
||||||
|
|
@ -376,7 +376,7 @@ api_data_post(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
/* Parse input data as json or xml into xml */
|
/* Parse input data as json or xml into xml */
|
||||||
if (parse_xml){
|
if (parse_xml){
|
||||||
if (clicon_xml_parse_str(data, NULL, &xdata) < 0){
|
if (xml_parse_string(data, NULL, &xdata) < 0){
|
||||||
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -495,7 +495,7 @@ api_data_put(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
/* Parse input data as json or xml into xml */
|
/* Parse input data as json or xml into xml */
|
||||||
if (parse_xml){
|
if (parse_xml){
|
||||||
if (clicon_xml_parse_str(data, NULL, &xdata) < 0){
|
if (xml_parse_string(data, NULL, &xdata) < 0){
|
||||||
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -729,7 +729,7 @@ api_operation_post(clicon_handle h,
|
||||||
if (data && strlen(data)){
|
if (data && strlen(data)){
|
||||||
/* Parse input data as json or xml into xml */
|
/* Parse input data as json or xml into xml */
|
||||||
if (parse_xml){
|
if (parse_xml){
|
||||||
if (clicon_xml_parse_str(data, NULL, &xdata) < 0){
|
if (xml_parse_string(data, NULL, &xdata) < 0){
|
||||||
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,7 @@ main(int argc, char **argv)
|
||||||
clicon_err(OE_DB, 0, "Unrecognized operation: %s", argv[1]);
|
clicon_err(OE_DB, 0, "Unrecognized operation: %s", argv[1]);
|
||||||
usage(argv0);
|
usage(argv0);
|
||||||
}
|
}
|
||||||
if (clicon_xml_parse_str(argv[2], NULL, &xt) < 0)
|
if (xml_parse_string(argv[2], NULL, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(xt, 0, &xt) < 0)
|
if (xml_rootchild(xt, 0, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -431,7 +431,7 @@ text_get(xmldb_handle xh,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Parse file into XML tree */
|
/* Parse file into XML tree */
|
||||||
if ((clicon_xml_parse_file(fd, "</config>", yspec, &xt)) < 0)
|
if ((xml_parse_file(fd, "</config>", yspec, &xt)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Always assert a top-level called "config".
|
/* Always assert a top-level called "config".
|
||||||
To ensure that, deal with two cases:
|
To ensure that, deal with two cases:
|
||||||
|
|
@ -856,7 +856,7 @@ text_put(xmldb_handle xh,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Parse file into XML tree */
|
/* Parse file into XML tree */
|
||||||
if ((clicon_xml_parse_file(fd, "</config>", yspec, &x0)) < 0)
|
if ((xml_parse_file(fd, "</config>", yspec, &x0)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Always assert a top-level called "config".
|
/* Always assert a top-level called "config".
|
||||||
To ensure that, deal with two cases:
|
To ensure that, deal with two cases:
|
||||||
|
|
@ -1345,7 +1345,7 @@ main(int argc, char **argv)
|
||||||
if (strcmp(cmd, "put")==0){
|
if (strcmp(cmd, "put")==0){
|
||||||
if (argc != 6)
|
if (argc != 6)
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
if (clicon_xml_parse_file(0, "</clicon>", NULL, &xt) < 0)
|
if (xml_parse_file(0, "</clicon>", NULL, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(xt, 0, &xn) < 0)
|
if (xml_rootchild(xt, 0, &xn) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -165,11 +165,11 @@ plugin_statedata(clicon_handle h,
|
||||||
cxobj **xvec = NULL;
|
cxobj **xvec = NULL;
|
||||||
|
|
||||||
/* Example of (static) statedata, real code would poll state */
|
/* Example of (static) statedata, real code would poll state */
|
||||||
if (xml_parse("<interfaces-state><interface>"
|
if (xml_parse_string("<interfaces-state><interface>"
|
||||||
"<name>eth0</name>"
|
"<name>eth0</name>"
|
||||||
"<type>eth</type>"
|
"<type>eth</type>"
|
||||||
"<if-index>42</if-index>"
|
"<if-index>42</if-index>"
|
||||||
"</interface></interfaces-state>", NULL, xstate) < 0)
|
"</interface></interfaces-state>", NULL, &xstate) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -225,7 +225,7 @@ plugin_reset(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
|
|
||||||
if (clicon_xml_parse_str("<config><interfaces><interface>"
|
if (xml_parse_string("<config><interfaces><interface>"
|
||||||
"<name>lo</name><type>local</type>"
|
"<name>lo</name><type>local</type>"
|
||||||
"</interface></interfaces></config>", NULL, &xt) < 0)
|
"</interface></interfaces></config>", NULL, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ fib_route_rpc(clicon_handle h,
|
||||||
/* User supplied variable in CLI command */
|
/* User supplied variable in CLI command */
|
||||||
instance = cvec_find(cvv, "instance"); /* get a cligen variable from vector */
|
instance = cvec_find(cvv, "instance"); /* get a cligen variable from vector */
|
||||||
/* Create XML for fib-route netconf RPC */
|
/* Create XML for fib-route netconf RPC */
|
||||||
if (clicon_xml_parse(&xtop, NULL, "<rpc><fib-route><routing-instance-name>%s</routing-instance-name></fib-route></rpc>", instance) < 0)
|
if (xml_parse_va(&xtop, NULL, "<rpc><fib-route><routing-instance-name>%s</routing-instance-name></fib-route></rpc>", instance) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Skip top-level */
|
/* Skip top-level */
|
||||||
xrpc = xml_child_i(xtop, 0);
|
xrpc = xml_child_i(xtop, 0);
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,12 @@ cxobj *xml_child_each(cxobj *xparent, cxobj *xprev, enum cxobj_type type);
|
||||||
|
|
||||||
cxobj **xml_childvec_get(cxobj *x);
|
cxobj **xml_childvec_get(cxobj *x);
|
||||||
int xml_childvec_set(cxobj *x, int len);
|
int xml_childvec_set(cxobj *x, int len);
|
||||||
|
#ifdef OBSOLETE /* Changed in 3.3.3, see CHANGELOG */
|
||||||
|
/* Changed: */
|
||||||
|
cxobj *xml_new(char *name, cxobj *xn_parent);
|
||||||
|
/* Removed: */
|
||||||
|
cxobj *xml_new_spec(char *name, cxobj *xn_parent, void *spec);
|
||||||
|
#endif
|
||||||
cxobj *xml_new(char *name, cxobj *xn_parent, yang_stmt *spec);
|
cxobj *xml_new(char *name, cxobj *xn_parent, yang_stmt *spec);
|
||||||
yang_stmt *xml_spec(cxobj *x);
|
yang_stmt *xml_spec(cxobj *x);
|
||||||
int xml_spec_set(cxobj *x, yang_stmt *spec);
|
int xml_spec_set(cxobj *x, yang_stmt *spec);
|
||||||
|
|
@ -136,12 +142,18 @@ int xml_free(cxobj *xn);
|
||||||
int xml_print(FILE *f, cxobj *xn);
|
int xml_print(FILE *f, cxobj *xn);
|
||||||
int clicon_xml2file(FILE *f, cxobj *xn, int level, int prettyprint);
|
int clicon_xml2file(FILE *f, cxobj *xn, int level, int prettyprint);
|
||||||
int clicon_xml2cbuf(cbuf *xf, cxobj *xn, int level, int prettyprint);
|
int clicon_xml2cbuf(cbuf *xf, cxobj *xn, int level, int prettyprint);
|
||||||
int clicon_xml_parse_file(int fd, char *endtag, yang_spec *yspec, cxobj **xt);
|
#ifdef OBSOLETE /* Changed in 3.3.3, see CHANGELOG */
|
||||||
int clicon_xml_parse_str(char *str, yang_spec *yspec, cxobj **xml_top);
|
/* Changed: */
|
||||||
/* XXX obsolete */
|
int clicon_xml_parse(cxobj **cxtop, char *format, ...);
|
||||||
#define clicon_xml_parse_string(str, x) clicon_xml_parse_str((*str), NULL, x)
|
int clicon_xml_parse_file(int fd, cxobj **xml_top, char *endtag);
|
||||||
int clicon_xml_parse(cxobj **cxtop, yang_spec *yspec, char *format, ...);
|
int clicon_xml_parse_str(char *str, cxobj **xml_top);
|
||||||
|
/* Removed: */
|
||||||
int xml_parse(char *str, yang_spec *yspec, cxobj *xt);
|
int xml_parse(char *str, yang_spec *yspec, cxobj *xt);
|
||||||
|
int clicon_xml_parse_string(char **str, cxobj **xml_top);
|
||||||
|
#endif
|
||||||
|
int xml_parse_file(int fd, char *endtag, yang_spec *yspec, cxobj **xt);
|
||||||
|
int xml_parse_string(const char *str, yang_spec *yspec, cxobj **xml_top);
|
||||||
|
int xml_parse_va(cxobj **xt, yang_spec *yspec, const char *format, ...);
|
||||||
|
|
||||||
int xmltree2cbuf(cbuf *cb, cxobj *x, int level);
|
int xmltree2cbuf(cbuf *cb, cxobj *x, int level);
|
||||||
int xml_copy_one(cxobj *xn0, cxobj *xn1);
|
int xml_copy_one(cxobj *xn0, cxobj *xn1);
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ clicon_option_readfile_xml(clicon_hash_t *copt,
|
||||||
}
|
}
|
||||||
clicon_debug(2, "Reading config file %s", __FUNCTION__, filename);
|
clicon_debug(2, "Reading config file %s", __FUNCTION__, filename);
|
||||||
fd = fileno(f);
|
fd = fileno(f);
|
||||||
if (clicon_xml_parse_file(fd, "</clicon>", yspec, &xt) < 0)
|
if (xml_parse_file(fd, "</clicon>", yspec, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_child_nr(xt)==1 && xml_child_nr_type(xt, CX_BODY)==1){
|
if (xml_child_nr(xt)==1 && xml_child_nr_type(xt, CX_BODY)==1){
|
||||||
clicon_err(OE_CFG, 0, "Config file %s: Expected XML but is probably old sh style", filename);
|
clicon_err(OE_CFG, 0, "Config file %s: Expected XML but is probably old sh style", filename);
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ clicon_msg_decode(struct clicon_msg *msg,
|
||||||
/* body */
|
/* body */
|
||||||
xmlstr = msg->op_body;
|
xmlstr = msg->op_body;
|
||||||
clicon_debug(1, "%s %s", __FUNCTION__, xmlstr);
|
clicon_debug(1, "%s %s", __FUNCTION__, xmlstr);
|
||||||
if (clicon_xml_parse_str(xmlstr, NULL, xml) < 0)
|
if (xml_parse_string(xmlstr, NULL, xml) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ clicon_rpc_msg(clicon_handle h,
|
||||||
}
|
}
|
||||||
clicon_debug(1, "%s retdata:%s", __FUNCTION__, retdata);
|
clicon_debug(1, "%s retdata:%s", __FUNCTION__, retdata);
|
||||||
if (retdata &&
|
if (retdata &&
|
||||||
clicon_xml_parse_str(retdata, NULL, &xret) < 0)
|
xml_parse_string(retdata, NULL, &xret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xret0){
|
if (xret0){
|
||||||
*xret0 = xret;
|
*xret0 = xret;
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,12 @@
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
#define BUFLEN 1024 /* Size of xml read buffer */
|
/* Size of xml read buffer */
|
||||||
#define XML_INDENT 3 /* maybe we should set this programmatically? */
|
#define BUFLEN 1024
|
||||||
|
/* Indentation for xml pretty-print. Consider option? */
|
||||||
|
#define XML_INDENT 3
|
||||||
|
/* Name of xml top object created by xml parse functions */
|
||||||
|
#define XML_TOP_SYMBOL "top"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Types
|
* Types
|
||||||
|
|
@ -923,6 +927,10 @@ xml_free(cxobj *x)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
* XML printing functions. Output a parse tree to file, string cligen buf
|
||||||
|
*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/*! Print an XML tree structure to an output stream
|
/*! Print an XML tree structure to an output stream
|
||||||
*
|
*
|
||||||
* Uses clicon_xml2cbuf internally
|
* Uses clicon_xml2cbuf internally
|
||||||
|
|
@ -1130,44 +1138,6 @@ clicon_xml2cbuf(cbuf *cb,
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Basic xml parsing function.
|
|
||||||
* @param[in] str Pointer to string containing XML definition.
|
|
||||||
* @param[in] yspec Yang specification or NULL
|
|
||||||
* @param[out] xtop Top of XML parse tree. Assume created.
|
|
||||||
* @see clicon_xml_parse_file clicon_xml_parse_string
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_parse(char *str,
|
|
||||||
yang_spec *yspec,
|
|
||||||
cxobj *xt)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
struct xml_parse_yacc_arg ya = {0,};
|
|
||||||
|
|
||||||
if (xt == NULL){
|
|
||||||
clicon_err(OE_XML, errno, "Unexpected NULL XML");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if ((ya.ya_parse_string = strdup(str)) == NULL){
|
|
||||||
clicon_err(OE_XML, errno, "strdup");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ya.ya_xparent = xt;
|
|
||||||
ya.ya_skipspace = 1; /* remove all non-terminal bodies (strip pretty-print) */
|
|
||||||
ya.ya_yspec = yspec;
|
|
||||||
if (clixon_xml_parsel_init(&ya) < 0)
|
|
||||||
goto done;
|
|
||||||
if (clixon_xml_parseparse(&ya) != 0) /* yacc returns 1 on error */
|
|
||||||
goto done;
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
clixon_xml_parsel_exit(&ya);
|
|
||||||
if(ya.ya_parse_string != NULL)
|
|
||||||
free(ya.ya_parse_string);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Print actual xml tree datastructures (not xml), mainly for debugging
|
/*! Print actual xml tree datastructures (not xml), mainly for debugging
|
||||||
* @param[in,out] cb Cligen buffer to write to
|
* @param[in,out] cb Cligen buffer to write to
|
||||||
* @param[in] xn Clicon xml tree
|
* @param[in] xn Clicon xml tree
|
||||||
|
|
@ -1207,7 +1177,51 @@ xmltree2cbuf(cbuf *cb,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! FSM to detect a substring
|
/*--------------------------------------------------------------------
|
||||||
|
* XML parsing functions. Create XML parse tree from string and file.
|
||||||
|
*--------------------------------------------------------------------*/
|
||||||
|
/*! Common internal xml parsing function string to parse-tree
|
||||||
|
*
|
||||||
|
* Given a string containing XML, parse into existing XML tree and return
|
||||||
|
* @param[in] str Pointer to string containing XML definition.
|
||||||
|
* @param[in] yspec Yang specification or NULL
|
||||||
|
* @param[in,out] xtop Top of XML parse tree. Assume created. Holds new tree.
|
||||||
|
* @see xml_parse_file
|
||||||
|
* @see xml_parse_string
|
||||||
|
* @see xml_parse_va
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xml_parse(const char *str,
|
||||||
|
yang_spec *yspec,
|
||||||
|
cxobj *xt)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
struct xml_parse_yacc_arg ya = {0,};
|
||||||
|
|
||||||
|
if (xt == NULL){
|
||||||
|
clicon_err(OE_XML, errno, "Unexpected NULL XML");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((ya.ya_parse_string = strdup(str)) == NULL){
|
||||||
|
clicon_err(OE_XML, errno, "strdup");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ya.ya_xparent = xt;
|
||||||
|
ya.ya_skipspace = 1; /* remove all non-terminal bodies (strip pretty-print) */
|
||||||
|
ya.ya_yspec = yspec;
|
||||||
|
if (clixon_xml_parsel_init(&ya) < 0)
|
||||||
|
goto done;
|
||||||
|
if (clixon_xml_parseparse(&ya) != 0) /* yacc returns 1 on error */
|
||||||
|
goto done;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
clixon_xml_parsel_exit(&ya);
|
||||||
|
if(ya.ya_parse_string != NULL)
|
||||||
|
free(ya.ya_parse_string);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! FSM to detect substring
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int
|
||||||
FSM(char *tag,
|
FSM(char *tag,
|
||||||
|
|
@ -1223,31 +1237,27 @@ FSM(char *tag,
|
||||||
/*! Read an XML definition from file and parse it into a parse-tree.
|
/*! Read an XML definition from file and parse it into a parse-tree.
|
||||||
*
|
*
|
||||||
* @param[in] fd A file descriptor containing the XML file (as ASCII characters)
|
* @param[in] fd A file descriptor containing the XML file (as ASCII characters)
|
||||||
* @param[out] xt Pointer to an (on entry empty) pointer to an XML parse tree
|
* @param[in] endtag Read until encounter "endtag" in the stream, or NULL
|
||||||
* _created_ by this function.
|
|
||||||
* @param[in] endtag Read until you encounter "endtag" in the stream, or NULL
|
|
||||||
* @param[in] yspec Yang specification, or NULL
|
* @param[in] yspec Yang specification, or NULL
|
||||||
* @retval 0 OK
|
* @param[in,out] xt Pointer to XML parse tree. If empty, create.
|
||||||
* @retval -1 Error with clicon_err called
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error with clicon_err called
|
||||||
*
|
*
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xt = NULL;
|
* cxobj *xt = NULL;
|
||||||
* clicon_xml_parse_file(0, &xt, "</clicon>");
|
* xml_parse_file(0, "</config>", yspec, &xt);
|
||||||
* xml_free(xt);
|
* xml_free(xt);
|
||||||
* @endcode
|
* @endcode
|
||||||
* * @see clicon_xml_parse_str
|
* @see xml_parse_string
|
||||||
* Note, you need to free the xml parse tree after use, using xml_free()
|
* @see xml_parse_va
|
||||||
* Note, xt will add a top-level symbol called "top" meaning that <tree../> will look as:
|
* @note, If xt empty, a top-level symbol will be added so that <tree../> will be: <top><tree.../></tree></top>
|
||||||
* <top><tree.../></tree>
|
* @note May block on file I/O
|
||||||
* XXX: There is a potential leak here on some return values.
|
|
||||||
* XXX: What happens if endtag is different?
|
|
||||||
* May block
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_xml_parse_file(int fd,
|
xml_parse_file(int fd,
|
||||||
char *endtag,
|
char *endtag,
|
||||||
yang_spec *yspec,
|
yang_spec *yspec,
|
||||||
cxobj **xt)
|
cxobj **xt)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
@ -1255,19 +1265,19 @@ clicon_xml_parse_file(int fd,
|
||||||
char ch;
|
char ch;
|
||||||
char *xmlbuf = NULL;
|
char *xmlbuf = NULL;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int maxbuf = BUFLEN;
|
int xmlbuflen = BUFLEN; /* start size */
|
||||||
int endtaglen = 0;
|
int endtaglen = 0;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
int oldmaxbuf;
|
int oldxmlbuflen;
|
||||||
|
|
||||||
if (endtag != NULL)
|
if (endtag != NULL)
|
||||||
endtaglen = strlen(endtag);
|
endtaglen = strlen(endtag);
|
||||||
*xt = NULL;
|
*xt = NULL;
|
||||||
if ((xmlbuf = malloc(maxbuf)) == NULL){
|
if ((xmlbuf = malloc(xmlbuflen)) == NULL){
|
||||||
clicon_err(OE_XML, errno, "%s: malloc", __FUNCTION__);
|
clicon_err(OE_XML, errno, "%s: malloc", __FUNCTION__);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
memset(xmlbuf, 0, maxbuf);
|
memset(xmlbuf, 0, xmlbuflen);
|
||||||
ptr = xmlbuf;
|
ptr = xmlbuf;
|
||||||
while (1){
|
while (1){
|
||||||
if ((ret = read(fd, &ch, 1)) < 0){
|
if ((ret = read(fd, &ch, 1)) < 0){
|
||||||
|
|
@ -1284,20 +1294,21 @@ clicon_xml_parse_file(int fd,
|
||||||
if (ret == 0 ||
|
if (ret == 0 ||
|
||||||
(endtag && (state == endtaglen))){
|
(endtag && (state == endtaglen))){
|
||||||
state = 0;
|
state = 0;
|
||||||
if ((*xt = xml_new("top", NULL, NULL)) == NULL)
|
if (*xt == NULL)
|
||||||
break;
|
if ((*xt = xml_new(XML_TOP_SYMBOL, NULL, NULL)) == NULL)
|
||||||
|
goto done;
|
||||||
if (xml_parse(ptr, yspec, *xt) < 0)
|
if (xml_parse(ptr, yspec, *xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (len>=maxbuf-1){ /* Space: one for the null character */
|
if (len>=xmlbuflen-1){ /* Space: one for the null character */
|
||||||
oldmaxbuf = maxbuf;
|
oldxmlbuflen = xmlbuflen;
|
||||||
maxbuf *= 2;
|
xmlbuflen *= 2;
|
||||||
if ((xmlbuf = realloc(xmlbuf, maxbuf)) == NULL){
|
if ((xmlbuf = realloc(xmlbuf, xmlbuflen)) == NULL){
|
||||||
clicon_err(OE_XML, errno, "%s: realloc", __FUNCTION__);
|
clicon_err(OE_XML, errno, "%s: realloc", __FUNCTION__);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
memset(xmlbuf+oldmaxbuf, 0, maxbuf-oldmaxbuf);
|
memset(xmlbuf+oldxmlbuflen, 0, xmlbuflen-oldxmlbuflen);
|
||||||
ptr = xmlbuf;
|
ptr = xmlbuf;
|
||||||
}
|
}
|
||||||
} /* while */
|
} /* while */
|
||||||
|
|
@ -1314,56 +1325,58 @@ clicon_xml_parse_file(int fd,
|
||||||
|
|
||||||
/*! Read an XML definition from string and parse it into a parse-tree.
|
/*! Read an XML definition from string and parse it into a parse-tree.
|
||||||
*
|
*
|
||||||
* @param[in] str Pointer to string containing XML definition.
|
* @param[in] str String containing XML definition.
|
||||||
* @param[out] xml_top Top of XML parse tree. Will add extra top element called 'top'.
|
* @param[in] yspec Yang specification, or NULL
|
||||||
* you must free it after use, using xml_free()
|
* @param[in,out] xt Pointer to XML parse tree. If empty will be created.
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error with clicon_err called
|
* @retval -1 Error with clicon_err called
|
||||||
*
|
*
|
||||||
* @code
|
* @code
|
||||||
* cxobj *cx = NULL;
|
* cxobj *xt = NULL;
|
||||||
* if (clicon_xml_parse_str(str, &cx) < 0)
|
* if (xml_parse_string(str, yspec, &xt) < 0)
|
||||||
* err;
|
* err;
|
||||||
* xml_free(cx);
|
* xml_free(xt);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see clicon_xml_parse_file
|
* @see xml_parse_file
|
||||||
|
* @see xml_parse_va
|
||||||
* @note you need to free the xml parse tree after use, using xml_free()
|
* @note you need to free the xml parse tree after use, using xml_free()
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_xml_parse_str(char *str,
|
xml_parse_string(const char *str,
|
||||||
yang_spec *yspec,
|
yang_spec *yspec,
|
||||||
cxobj **cxtop)
|
cxobj **xtop)
|
||||||
{
|
{
|
||||||
if ((*cxtop = xml_new("top", NULL, NULL)) == NULL)
|
if (*xtop == NULL)
|
||||||
return -1;
|
if ((*xtop = xml_new(XML_TOP_SYMBOL, NULL, NULL)) == NULL)
|
||||||
return xml_parse(str, yspec, *cxtop);
|
return -1;
|
||||||
|
return xml_parse(str, yspec, *xtop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Read XML from var-arg list and parse it into xml tree
|
||||||
/*! Read XML definition from variable argument string and parse it into parse-tree.
|
|
||||||
*
|
*
|
||||||
* Utility function using stdarg instead of static string.
|
* Utility function using stdarg instead of static string.
|
||||||
* @param[out] xml_top Top of XML parse tree. Will add extra top element called 'top'.
|
* @param[in,out] xtop Top of XML parse tree. If it is NULL, top element
|
||||||
* you must free it after use, using xml_free()
|
called 'top' will be created. Call xml_free() after use
|
||||||
* @param[in] yspec Yang specification, or NULL
|
* @param[in] yspec Yang specification, or NULL
|
||||||
* @param[in] format Pointer to string containing XML definition.
|
* @param[in] format Format string for stdarg according to printf(3)
|
||||||
|
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error with clicon_err called
|
* @retval -1 Error with clicon_err called
|
||||||
*
|
*
|
||||||
* @code
|
* @code
|
||||||
* cxobj *cx = NULL;
|
* cxobj *xt = NULL;
|
||||||
* if (clicon_xml_parse(&cx, "<xml>%d</xml>", 22) < 0)
|
* if (xml_parse_va(&xt, NULL, "<xml>%d</xml>", 22) < 0)
|
||||||
* err;
|
* err;
|
||||||
* xml_free(cx);
|
* xml_free(xt);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see clicon_xml_parse_str
|
* @see xml_parse_string
|
||||||
* @note you need to free the xml parse tree after use, using xml_free()
|
* @see xml_parse_file
|
||||||
|
* @note If vararg list is empty, consider using xml_parse_string()
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_xml_parse(cxobj **cxtop,
|
xml_parse_va(cxobj **xtop,
|
||||||
yang_spec *yspec,
|
yang_spec *yspec,
|
||||||
char *format, ...)
|
const char *format, ...)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
@ -1381,9 +1394,10 @@ clicon_xml_parse(cxobj **cxtop,
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
len = vsnprintf(str, len, format, args) + 1;
|
len = vsnprintf(str, len, format, args) + 1;
|
||||||
va_end(args);
|
va_end(args);
|
||||||
if ((*cxtop = xml_new("top", NULL, NULL)) == NULL)
|
if (*xtop == NULL)
|
||||||
return -1;
|
if ((*xtop = xml_new(XML_TOP_SYMBOL, NULL, NULL)) == NULL)
|
||||||
if (xml_parse(str, yspec, *cxtop) < 0)
|
goto done;
|
||||||
|
if (xml_parse(str, yspec, *xtop) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -2103,7 +2117,7 @@ main(int argc, char **argv)
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (clicon_xml_parse_file(0, &xt, "</config>") < 0){
|
if (xml_parse_file(0, "</config>", NULL,&xt) < 0){
|
||||||
fprintf(stderr, "parsing 2\n");
|
fprintf(stderr, "parsing 2\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -382,7 +382,7 @@ xmldb_get(clicon_handle h,
|
||||||
* The xml may contain the "operation" attribute which defines the operation.
|
* The xml may contain the "operation" attribute which defines the operation.
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xt;
|
* cxobj *xt;
|
||||||
* if (clicon_xml_parse_str("<a>17</a>", &xt) < 0)
|
* if (xml_parse_string("<a>17</a>", yspec, &xt) < 0)
|
||||||
* err;
|
* err;
|
||||||
* if (xmldb_put(xh, "running", OP_MERGE, xt) < 0)
|
* if (xmldb_put(xh, "running", OP_MERGE, xt) < 0)
|
||||||
* err;
|
* err;
|
||||||
|
|
|
||||||
|
|
@ -1174,7 +1174,7 @@ main(int argc, char **argv)
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (clicon_xml_parse_file(0, &x, "</clicon>") < 0){
|
if (xml_parse_file(0, &x, "</clicon>") < 0){
|
||||||
fprintf(stderr, "parsing 2\n");
|
fprintf(stderr, "parsing 2\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ main(int argc, char **argv)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (clicon_xml_parse_str(buf, &x) < 0)
|
if (xml_parse_string(buf, &x) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (xpath_vec(x, xpath, &xv, &xlen) < 0)
|
if (xpath_vec(x, xpath, &xv, &xlen) < 0)
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
# include err() and new() functions
|
# include err() and new() functions
|
||||||
. ./lib.sh
|
. ./lib.sh
|
||||||
|
clixon_cf="-f /usr/local/etc/routing.xml"
|
||||||
|
|
||||||
# For memcheck
|
# For memcheck
|
||||||
#clixon_cli="valgrind --leak-check=full --show-leak-kinds=all clixon_cli"
|
#clixon_cli="valgrind --leak-check=full --show-leak-kinds=all clixon_cli"
|
||||||
|
|
@ -16,83 +17,81 @@ clixon_cli=clixon_cli
|
||||||
|
|
||||||
# kill old backend (if any)
|
# kill old backend (if any)
|
||||||
new "kill old backend"
|
new "kill old backend"
|
||||||
sudo clixon_backend -zf $clixon_cf
|
sudo clixon_backend -z $clixon_cf
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
new "start backend"
|
new "start backend"
|
||||||
# start new backend
|
# start new backend
|
||||||
sudo clixon_backend -s init -f $clixon_cf
|
sudo clixon_backend -s init $clixon_cf
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
new "cli tests"
|
new "cli tests"
|
||||||
|
|
||||||
new "cli configure top"
|
new "cli configure top"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf set interfaces" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf set interfaces" "^$"
|
||||||
|
|
||||||
new "cli show configuration top (no presence)"
|
new "cli show configuration top (no presence)"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf show conf cli" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf show conf cli" "^$"
|
||||||
|
|
||||||
new "cli configure delete top"
|
new "cli configure delete top"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf delete interfaces" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf delete interfaces" "^$"
|
||||||
|
|
||||||
new "cli show configuration delete top"
|
new "cli show configuration delete top"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf show conf cli" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf show conf cli" "^$"
|
||||||
|
|
||||||
new "cli configure"
|
new "cli configure"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf set interfaces interface eth/0/0" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf set interfaces interface eth/0/0" "^$"
|
||||||
|
|
||||||
new "cli show configuration"
|
new "cli show configuration"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf show conf cli" "^interfaces interface name eth/0/0" "interfaces interface enabled true$"
|
expectfn "$clixon_cli -1 $clixon_cf show conf cli" "^interfaces interface name eth/0/0" "interfaces interface enabled true$"
|
||||||
|
|
||||||
new "cli failed validate"
|
new "cli failed validate"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o validate" "Missing mandatory variable"
|
expectfn "$clixon_cli -1 $clixon_cf -l o validate" "Missing mandatory variable"
|
||||||
|
|
||||||
new "cli configure more"
|
new "cli configure more"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf set interfaces interface eth/0/0 ipv4 address 1.2.3.4 prefix-length 24" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf set interfaces interface eth/0/0 ipv4 address 1.2.3.4 prefix-length 24" "^$"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf set interfaces interface eth/0/0 description mydesc" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf set interfaces interface eth/0/0 description mydesc" "^$"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf set interfaces interface eth/0/0 type bgp" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf set interfaces interface eth/0/0 type bgp" "^$"
|
||||||
|
|
||||||
new "cli show xpath description"
|
new "cli show xpath description"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o show xpath /interfaces/interface/description" "<description>mydesc</description>"
|
expectfn "$clixon_cli -1 $clixon_cf -l o show xpath /interfaces/interface/description" "<description>mydesc</description>"
|
||||||
|
|
||||||
new "cli delete description"
|
new "cli delete description"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o delete interfaces interface eth/0/0 description mydesc"
|
expectfn "$clixon_cli -1 $clixon_cf -l o delete interfaces interface eth/0/0 description mydesc"
|
||||||
|
|
||||||
new "cli show xpath no description"
|
new "cli show xpath no description"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o show xpath /interfaces/interface/description" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf -l o show xpath /interfaces/interface/description" "^$"
|
||||||
|
|
||||||
new "cli copy interface"
|
new "cli copy interface"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf copy interface eth/0/0 to eth99" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf copy interface eth/0/0 to eth99" "^$"
|
||||||
|
|
||||||
new "cli success validate"
|
new "cli success validate"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o validate" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf -l o validate" "^$"
|
||||||
|
|
||||||
new "cli commit"
|
new "cli commit"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o commit" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf -l o commit" "^$"
|
||||||
|
|
||||||
new "cli save"
|
new "cli save"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o save /tmp/foo" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf -l o save /tmp/foo" "^$"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
new "cli delete all"
|
new "cli delete all"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o delete all" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf -l o delete all" "^$"
|
||||||
|
|
||||||
new "cli load"
|
new "cli load"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o load /tmp/foo" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf -l o load /tmp/foo" "^$"
|
||||||
|
|
||||||
new "cli check load"
|
new "cli check load"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o show conf cli" "^interfaces interface name eth/0/0" "interfaces interface enabled true$"
|
expectfn "$clixon_cli -1 $clixon_cf -l o show conf cli" "^interfaces interface name eth/0/0" "interfaces interface enabled true$"
|
||||||
|
|
||||||
new "cli debug"
|
new "cli debug"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o debug level 1" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf -l o debug level 1" "^$"
|
||||||
# How to test this?
|
# How to test this?
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o debug level 0" "^$"
|
expectfn "$clixon_cli -1 $clixon_cf -l o debug level 0" "^$"
|
||||||
|
|
||||||
new "cli rpc"
|
new "cli rpc"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -l o rpc ipv4" "^<rpc-reply>"
|
expectfn "$clixon_cli -1 $clixon_cf -l o rpc ipv4" "^<rpc-reply>"
|
||||||
|
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if still alive
|
# Check if still alive
|
||||||
|
|
@ -101,7 +100,7 @@ if [ -z "$pid" ]; then
|
||||||
err "backend already dead"
|
err "backend already dead"
|
||||||
fi
|
fi
|
||||||
# kill backend
|
# kill backend
|
||||||
sudo clixon_backend -zf $clixon_cf
|
sudo clixon_backend -z $clixon_cf
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err "kill backend"
|
err "kill backend"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue