Fixed [changing interface name not support with openconfig module #195](https://github.com/clicon/clixon/issues/195)
This commit is contained in:
parent
d8be601606
commit
7412bb7b3d
5 changed files with 140 additions and 41 deletions
|
|
@ -85,6 +85,7 @@ Developers may need to change their code
|
||||||
|
|
||||||
### Corrected Bugs
|
### Corrected Bugs
|
||||||
|
|
||||||
|
* Fixed [changing interface name not support with openconfig module #195](https://github.com/clicon/clixon/issues/195)
|
||||||
* Fixed [making cli_show_options's output more human readable #199](https://github.com/clicon/clixon/issues/199)
|
* Fixed [making cli_show_options's output more human readable #199](https://github.com/clicon/clixon/issues/199)
|
||||||
* Fixed Yang parsing of comments in (extension) unknown statements, to allow multiple white space
|
* Fixed Yang parsing of comments in (extension) unknown statements, to allow multiple white space
|
||||||
* this also caused spaces to be printed to stdout after clixon-restconf was terminated
|
* this also caused spaces to be printed to stdout after clixon-restconf was terminated
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,74 @@
|
||||||
#include "clixon_cli_api.h"
|
#include "clixon_cli_api.h"
|
||||||
#include "cli_common.h" /* internal functions */
|
#include "cli_common.h" /* internal functions */
|
||||||
|
|
||||||
|
/*! Given an xpath encoded in a cbuf, append a second xpath into the first
|
||||||
|
* The method reuses prefixes from xpath1 if they exist, otherwise the module prefix
|
||||||
|
* from y is used. Unless the element is .., .
|
||||||
|
* XXX: Predicates not handled
|
||||||
|
* The algorithm is not fool-proof, there are many cases it may not work
|
||||||
|
* To make it more complete, maybe parse the xpath to a tree and put it
|
||||||
|
* back to an xpath after modifcations, something like:
|
||||||
|
if (xpath_parse(yang_argument_get(ypath), &xpt) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xpath_tree2cbuf(xpt, xcb) < 0)
|
||||||
|
goto done;
|
||||||
|
and
|
||||||
|
traverse_canonical
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xpath_myappend(cbuf *xpath0,
|
||||||
|
char *xpath1,
|
||||||
|
yang_stmt *y,
|
||||||
|
cvec *nsc)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char **vec = NULL;
|
||||||
|
char *v;
|
||||||
|
int nvec;
|
||||||
|
int i;
|
||||||
|
char *myprefix;
|
||||||
|
char *id = NULL;
|
||||||
|
char *prefix = NULL;
|
||||||
|
|
||||||
|
if (xpath0 == NULL){
|
||||||
|
clicon_err(OE_XML, EINVAL, "xpath0 is NULL");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ((myprefix = yang_find_myprefix(y)) == NULL)
|
||||||
|
goto done;
|
||||||
|
if ((vec = clicon_strsep(xpath1, "/", &nvec)) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (xpath1 && xpath1[0] == '/')
|
||||||
|
cbuf_reset(xpath0);
|
||||||
|
for (i=0; i<nvec; i++){
|
||||||
|
v = vec[i];
|
||||||
|
if (strlen(v) == 0)
|
||||||
|
continue;
|
||||||
|
if (nodeid_split(v, &prefix, &id) < 0)
|
||||||
|
goto done;
|
||||||
|
if (strcmp(id, "..") == 0 || strcmp(id, ".") == 0)
|
||||||
|
cprintf(xpath0, "/%s", id);
|
||||||
|
else
|
||||||
|
cprintf(xpath0, "/%s:%s", prefix?prefix:myprefix, id);
|
||||||
|
if (prefix){
|
||||||
|
free(prefix);
|
||||||
|
prefix = NULL;
|
||||||
|
}
|
||||||
|
if (id){
|
||||||
|
free(id);
|
||||||
|
id = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (prefix)
|
||||||
|
free(prefix);
|
||||||
|
if (id)
|
||||||
|
free(id);
|
||||||
|
free(vec);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Completion callback intended for automatically generated data model
|
/*! Completion callback intended for automatically generated data model
|
||||||
*
|
*
|
||||||
* Returns an expand-type list of commands as used by cligen 'expand'
|
* Returns an expand-type list of commands as used by cligen 'expand'
|
||||||
|
|
@ -116,12 +184,11 @@ expand_dbvar(void *h,
|
||||||
yang_stmt *yp;
|
yang_stmt *yp;
|
||||||
yang_stmt *ytype;
|
yang_stmt *ytype;
|
||||||
yang_stmt *ypath;
|
yang_stmt *ypath;
|
||||||
cxobj *xcur;
|
|
||||||
char *xpathcur;
|
|
||||||
char *reason = NULL;
|
char *reason = NULL;
|
||||||
cvec *nsc = NULL;
|
cvec *nsc = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
int cvvi = 0;
|
int cvvi = 0;
|
||||||
|
cbuf *cbxpath = NULL;
|
||||||
|
|
||||||
if (argv == NULL || cvec_len(argv) != 2){
|
if (argv == NULL || cvec_len(argv) != 2){
|
||||||
clicon_err(OE_PLUGIN, EINVAL, "requires arguments: <db> <xmlkeyfmt>");
|
clicon_err(OE_PLUGIN, EINVAL, "requires arguments: <db> <xmlkeyfmt>");
|
||||||
|
|
@ -153,18 +220,6 @@ expand_dbvar(void *h,
|
||||||
*/
|
*/
|
||||||
if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path, &cvvi) < 0)
|
if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path, &cvvi) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (api_path2xpath(api_path, yspec, &xpath, &nsc, NULL) < 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Get configuration */
|
|
||||||
if (clicon_rpc_get_config(h, NULL, dbstr, xpath, nsc, &xt) < 0) /* XXX */
|
|
||||||
goto done;
|
|
||||||
if ((xe = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
|
||||||
clixon_netconf_error(xe, "Get configuration", NULL);
|
|
||||||
goto ok;
|
|
||||||
}
|
|
||||||
xcur = xt; /* default top-of-tree */
|
|
||||||
xpathcur = xpath;
|
|
||||||
/* Create config top-of-tree */
|
/* Create config top-of-tree */
|
||||||
if ((xtop = xml_new(DATASTORE_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
if ((xtop = xml_new(DATASTORE_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -184,7 +239,22 @@ expand_dbvar(void *h,
|
||||||
if (y==NULL)
|
if (y==NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
||||||
|
/* Transform api-path to xpath for netconf */
|
||||||
|
if (api_path2xpath(api_path, yspec, &xpath, &nsc, NULL) < 0)
|
||||||
|
goto done;
|
||||||
|
if (nsc != NULL){
|
||||||
|
cvec_free(nsc);
|
||||||
|
nsc = NULL;
|
||||||
|
}
|
||||||
|
if (xml_nsctx_yang(y, &nsc) < 0)
|
||||||
|
goto done;
|
||||||
|
if ((cbxpath = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cprintf(cbxpath, "%s", xpath);
|
||||||
|
if ((ytype = yang_find(y, Y_TYPE, NULL)) != NULL &&
|
||||||
|
strcmp(yang_argument_get(ytype), "leafref") == 0){
|
||||||
/* Special case for leafref. Detect leafref via Yang-type,
|
/* Special case for leafref. Detect leafref via Yang-type,
|
||||||
* Get Yang path element, tentatively add the new syntax to the whole
|
* Get Yang path element, tentatively add the new syntax to the whole
|
||||||
* tree and apply the path to that.
|
* tree and apply the path to that.
|
||||||
|
|
@ -193,25 +263,41 @@ expand_dbvar(void *h,
|
||||||
* Here the whole syntax tree is loaded, and it would be better to offload
|
* Here the whole syntax tree is loaded, and it would be better to offload
|
||||||
* such operations to the datastore by a generic xpath function.
|
* such operations to the datastore by a generic xpath function.
|
||||||
*/
|
*/
|
||||||
if ((ytype = yang_find(y, Y_TYPE, NULL)) != NULL)
|
|
||||||
if (strcmp(yang_argument_get(ytype), "leafref")==0){
|
/*
|
||||||
|
* The syntax for a path argument is a subset of the XPath abbreviated
|
||||||
|
* syntax. Predicates are used only for constraining the values for the
|
||||||
|
* key nodes for list entries. Each predicate consists of exactly one
|
||||||
|
* equality test per key, and multiple adjacent predicates MAY be
|
||||||
|
* present if a list has multiple keys. The syntax is formally defined
|
||||||
|
* by the rule "path-arg" in Section 14.
|
||||||
|
* The "path" XPath expression is conceptually evaluated in the
|
||||||
|
* following context, in addition to the definition in Section 6.4.1:
|
||||||
|
*
|
||||||
|
* - If the "path" statement is defined within a typedef, the context
|
||||||
|
* node is the leaf or leaf-list node in the data tree that
|
||||||
|
* references the typedef.
|
||||||
|
* - Otherwise, the context node is the node in the data tree for which
|
||||||
|
* the "path" statement is defined.
|
||||||
|
*/
|
||||||
if ((ypath = yang_find(ytype, Y_PATH, NULL)) == NULL){
|
if ((ypath = yang_find(ytype, Y_PATH, NULL)) == NULL){
|
||||||
clicon_err(OE_DB, 0, "Leafref %s requires path statement", yang_argument_get(ytype));
|
clicon_err(OE_DB, 0, "Leafref %s requires path statement", yang_argument_get(ytype));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
xpathcur = yang_argument_get(ypath);
|
/* */
|
||||||
if (xml_merge(xt, xtop, yspec, &reason) < 0) /* Merge xtop into xt */
|
/* Extend xpath with leafref path: Append yang_argument_get(ypath) to xpath
|
||||||
goto done;
|
*/
|
||||||
if (reason){
|
if (xpath_myappend(cbxpath, yang_argument_get(ypath), y, nsc) < 0)
|
||||||
fprintf(stderr, "%s\n", reason);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((xcur = xpath_first(xt, nsc, "%s", xpath)) == NULL){
|
/* Get configuration based on cbxpath */
|
||||||
clicon_err(OE_DB, 0, "xpath %s should return merged content", xpath);
|
if (clicon_rpc_get_config(h, NULL, dbstr, cbuf_get(cbxpath), nsc, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if ((xe = xpath_first(xt, NULL, "/rpc-error")) != NULL){
|
||||||
|
clixon_netconf_error(xe, "Get configuration", NULL);
|
||||||
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, xpath) < 0)
|
||||||
if (xpath_vec(xcur, nsc, "%s", &xvec, &xlen, xpathcur) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
/* Loop for inserting into commands cvec.
|
/* Loop for inserting into commands cvec.
|
||||||
* Detect duplicates: for ordered-by system assume list is ordered, so you need
|
* Detect duplicates: for ordered-by system assume list is ordered, so you need
|
||||||
|
|
@ -252,6 +338,8 @@ expand_dbvar(void *h,
|
||||||
ok:
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cbxpath)
|
||||||
|
cbuf_free(cbxpath);
|
||||||
if (xerr)
|
if (xerr)
|
||||||
xml_free(xerr);
|
xml_free(xerr);
|
||||||
if (nsc)
|
if (nsc)
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,13 @@
|
||||||
|
|
||||||
Clixon implements NETCONF as external access, and also as an internal protocol between backend and frontent clients.
|
Clixon implements NETCONF as external access, and also as an internal protocol between backend and frontent clients.
|
||||||
|
|
||||||
|
You can expose ``clixon_netconf`` as an SSH subsystem according to `RFC 6242`. Register the subsystem in ``/etc/sshd_config``::
|
||||||
|
|
||||||
|
Subsystem netconf /usr/local/bin/clixon_netconf
|
||||||
|
|
||||||
|
and then invoke it from a client using::
|
||||||
|
|
||||||
|
ssh -s <host> netconf
|
||||||
|
|
||||||
|
|
||||||
For more defails see [Clixon docs netconf](https://clixon-docs.readthedocs.io/en/latest/standards.html#netconf)
|
For more defails see [Clixon docs netconf](https://clixon-docs.readthedocs.io/en/latest/standards.html#netconf)
|
||||||
|
|
@ -480,6 +480,7 @@ xpath_tree_free(xpath_tree *xs)
|
||||||
* xpath_tree_free(xpt);
|
* xpath_tree_free(xpt);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see xpath_tree_free
|
* @see xpath_tree_free
|
||||||
|
* @see xpath_tree2cbuf for unparsing, ie producing an original xpath string
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xpath_parse(const char *xpath,
|
xpath_parse(const char *xpath,
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ cat <<EOF > $cfg
|
||||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
<!--CLICON_CLI_AUTOCLI_EXCLUDE>clixon-restconf</CLICON_CLI_AUTOCLI_EXCLUDE-->
|
<CLICON_CLI_AUTOCLI_EXCLUDE>clixon-restconf ietf-interfaces</CLICON_CLI_AUTOCLI_EXCLUDE>
|
||||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
|
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue