* More YANG extension functionality,
* See [Augment auto-cli for hiding/modifying cli syntax #156](https://github.com/clicon/clixon/issues/156) and [hiding auto-generated CLI entries #153](https://github.com/clicon/clixon/issues/153) * Extensions can be used in augmentations * Extension `autocli-op` has been added to add "hidden" commands in the autocli * Documentation: https://clixon-docs.readthedocs.io/en/latest/misc.html#extensions
This commit is contained in:
parent
e1b94d94d2
commit
b8641f30bd
14 changed files with 547 additions and 50 deletions
|
|
@ -64,6 +64,11 @@ Developers may need to change their code
|
||||||
|
|
||||||
### Minor changes
|
### Minor changes
|
||||||
|
|
||||||
|
* More YANG extension functionality,
|
||||||
|
* See [Augment auto-cli for hiding/modifying cli syntax #156](https://github.com/clicon/clixon/issues/156) and [hiding auto-generated CLI entries #153](https://github.com/clicon/clixon/issues/153)
|
||||||
|
* Extensions can be used in augmentations
|
||||||
|
* Extension `autocli-op` has been added to add "hidden" commands in the autocli
|
||||||
|
* Documentation: https://clixon-docs.readthedocs.io/en/latest/misc.html#extensions
|
||||||
* Added new revision of main example yang: `clixon-example@2020-12-01.yang`
|
* Added new revision of main example yang: `clixon-example@2020-12-01.yang`
|
||||||
* Support for building static lib: `LINKAGE=static configure`
|
* Support for building static lib: `LINKAGE=static configure`
|
||||||
* Change comment character to be active anywhere to beginning of _word_ only.
|
* Change comment character to be active anywhere to beginning of _word_ only.
|
||||||
|
|
|
||||||
|
|
@ -659,10 +659,12 @@ yang2cli_leaf(clicon_handle h,
|
||||||
int key_leaf,
|
int key_leaf,
|
||||||
cbuf *cb)
|
cbuf *cb)
|
||||||
{
|
{
|
||||||
yang_stmt *yd; /* description */
|
yang_stmt *yd; /* description */
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *helptext = NULL;
|
char *helptext = NULL;
|
||||||
char *s;
|
char *s;
|
||||||
|
char *opext = NULL;
|
||||||
|
int extralevel = 0;
|
||||||
|
|
||||||
/* description */
|
/* description */
|
||||||
if ((yd = yang_find(ys, Y_DESCRIPTION, NULL)) != NULL){
|
if ((yd = yang_find(ys, Y_DESCRIPTION, NULL)) != NULL){
|
||||||
|
|
@ -674,27 +676,40 @@ yang2cli_leaf(clicon_handle h,
|
||||||
*s = '\0';
|
*s = '\0';
|
||||||
}
|
}
|
||||||
cprintf(cb, "%*s", level*3, "");
|
cprintf(cb, "%*s", level*3, "");
|
||||||
|
/* Look for autocli-op defined in clixon-lib.yang */
|
||||||
|
if (yang_extension_value(ys, "autocli-op", CLIXON_LIB_NS, &opext) < 0)
|
||||||
|
goto done;
|
||||||
if (gt == GT_VARS|| gt == GT_ALL || gt == GT_HIDE){
|
if (gt == GT_VARS|| gt == GT_ALL || gt == GT_HIDE){
|
||||||
cprintf(cb, "%s", yang_argument_get(ys));
|
cprintf(cb, "%s", yang_argument_get(ys));
|
||||||
yang2cli_helptext(cb, helptext);
|
yang2cli_helptext(cb, helptext);
|
||||||
cprintf(cb, " ");
|
cprintf(cb, " ");
|
||||||
if ((show_tree == 0) || (key_leaf == 1)) {
|
if (!show_tree || key_leaf) {
|
||||||
|
if (opext && strcmp(opext, "hide") == 0){
|
||||||
|
cprintf(cb, ",hide{");
|
||||||
|
extralevel = 1;
|
||||||
|
}
|
||||||
|
if (yang2cli_var(h, ys, helptext, cb) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (opext && strcmp(opext, "hide") == 0){
|
||||||
|
cprintf(cb, ",hide");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (!show_tree || key_leaf) {
|
||||||
if (yang2cli_var(h, ys, helptext, cb) < 0)
|
if (yang2cli_var(h, ys, helptext, cb) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
if ((show_tree == 0) || (key_leaf == 1)) {
|
|
||||||
if (yang2cli_var(h, ys, helptext, cb) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback){
|
if (callback){
|
||||||
if (cli_callback_generate(h, ys, cb) < 0)
|
if (cli_callback_generate(h, ys, cb) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
cprintf(cb, ";\n");
|
cprintf(cb, ";\n");
|
||||||
}
|
}
|
||||||
|
if (extralevel)
|
||||||
|
cprintf(cb, "}\n");
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (helptext)
|
if (helptext)
|
||||||
|
|
@ -787,9 +802,18 @@ yang2cli_list(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *helptext = NULL;
|
char *helptext = NULL;
|
||||||
char *s;
|
char *s;
|
||||||
int list_has_callback = 0;
|
int last_key = 0;
|
||||||
|
int extralevel = 0;
|
||||||
|
char *opext = NULL;
|
||||||
|
|
||||||
cprintf(cb, "%*s%s", level*3, "", yang_argument_get(ys));
|
cprintf(cb, "%*s%s", level*3, "", yang_argument_get(ys));
|
||||||
|
/* Look for autocli-op defined in clixon-lib.yang */
|
||||||
|
if (yang_extension_value(ys, "autocli-op", CLIXON_LIB_NS, &opext) < 0)
|
||||||
|
goto done;
|
||||||
|
if (opext != NULL && strcmp(opext, "hide") == 0){
|
||||||
|
cprintf(cb, ",hide");
|
||||||
|
extralevel = 1;
|
||||||
|
}
|
||||||
if ((yd = yang_find(ys, Y_DESCRIPTION, NULL)) != NULL){
|
if ((yd = yang_find(ys, Y_DESCRIPTION, NULL)) != NULL){
|
||||||
if ((helptext = strdup(yang_argument_get(yd))) == NULL){
|
if ((helptext = strdup(yang_argument_get(yd))) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
|
|
@ -811,25 +835,25 @@ yang2cli_list(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Print key variable now, and skip it in loop below
|
/* Print key variable now, and skip it in loop below
|
||||||
Note, only print callback on last statement
|
* Note, only print callback on last statement
|
||||||
*/
|
*/
|
||||||
list_has_callback = cvec_next(cvk, cvi)?0:1;
|
last_key = cvec_next(cvk, cvi)?0:1;
|
||||||
if (show_tree == 1) {
|
if (last_key){
|
||||||
if (list_has_callback) {
|
if (show_tree) {
|
||||||
if (cli_callback_generate(h, ys, cb) < 0)
|
if (cli_callback_generate(h, ys, cb) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
cprintf(cb, ";\n");
|
cprintf(cb, ";\n");
|
||||||
cprintf(cb, "{\n");
|
cprintf(cb, "{\n");
|
||||||
}
|
}
|
||||||
|
else if (extralevel)
|
||||||
|
cprintf(cb, "{\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yang2cli_leaf(h, yleaf,
|
if (yang2cli_leaf(h, yleaf,
|
||||||
(gt==GT_VARS||gt==GT_HIDE)?GT_NONE:gt, level+1,
|
(gt==GT_VARS||gt==GT_HIDE)?GT_NONE:gt, level+1,
|
||||||
list_has_callback, show_tree, 1,
|
last_key, show_tree, 1,
|
||||||
cb) < 0)
|
cb) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
cprintf(cb, "{\n");
|
cprintf(cb, "{\n");
|
||||||
yc = NULL;
|
yc = NULL;
|
||||||
while ((yc = yn_each(ys, yc)) != NULL) {
|
while ((yc = yn_each(ys, yc)) != NULL) {
|
||||||
|
|
@ -848,7 +872,7 @@ yang2cli_list(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
cprintf(cb, "%*s}\n", level*3, "");
|
cprintf(cb, "%*s}\n", level*3, "");
|
||||||
if ((show_tree == 1) && (list_has_callback)) {
|
if (last_key && (show_tree||extralevel)) {
|
||||||
cprintf(cb, "%*s}\n", level*3, "");
|
cprintf(cb, "%*s}\n", level*3, "");
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -1013,8 +1037,7 @@ yang2cli(clicon_handle h,
|
||||||
if ((globals = cvec_new(0)) == NULL)
|
if ((globals = cvec_new(0)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
/* load cli syntax */
|
/* load cli syntax */
|
||||||
if (cligen_parse_str(cli_cligen(h), cbuf_get(cb),
|
if (cligen_parse_str(cli_cligen(h), cbuf_get(cb), "yang2cli", pt, globals) < 0)
|
||||||
"yang2cli", pt, globals) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
cvec_free(globals);
|
cvec_free(globals);
|
||||||
/* Resolve the expand callback functions in the generated syntax.
|
/* Resolve the expand callback functions in the generated syntax.
|
||||||
|
|
|
||||||
|
|
@ -257,6 +257,6 @@ int yang_type_cache_get(yang_stmt *ytype, yang_stmt **resolved, int *opti
|
||||||
int yang_type_cache_set(yang_stmt *ys, yang_stmt *resolved, int options, cvec *cvv,
|
int yang_type_cache_set(yang_stmt *ys, yang_stmt *resolved, int options, cvec *cvv,
|
||||||
cvec *patterns, uint8_t fraction);
|
cvec *patterns, uint8_t fraction);
|
||||||
yang_stmt *yang_anydata_add(yang_stmt *yp, char *name);
|
yang_stmt *yang_anydata_add(yang_stmt *yp, char *name);
|
||||||
|
int yang_extension_value(yang_stmt *ys, char *name, char *ns, char **value);
|
||||||
|
|
||||||
#endif /* _CLIXON_YANG_H_ */
|
#endif /* _CLIXON_YANG_H_ */
|
||||||
|
|
|
||||||
|
|
@ -985,8 +985,8 @@ yang_find_schemanode(yang_stmt *yn,
|
||||||
* @retval NULL No prefix found. This is an error
|
* @retval NULL No prefix found. This is an error
|
||||||
* @retval prefix OK: Prefix as char* pointer into yang tree
|
* @retval prefix OK: Prefix as char* pointer into yang tree
|
||||||
* @code
|
* @code
|
||||||
* char *myprefix;
|
* char *myprefix;
|
||||||
* myprefix = yang_find_myprefix(ys);
|
* myprefix = yang_find_myprefix(ys);
|
||||||
* @endcode
|
* @endcode
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
|
|
@ -3236,6 +3236,65 @@ yang_anydata_add(yang_stmt *yp,
|
||||||
return ys;
|
return ys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Find extension argument and return extension argument value
|
||||||
|
* @param[in] ys Yang statement
|
||||||
|
* @param[in] name Name of the extension
|
||||||
|
* @param[in] ns The namespace
|
||||||
|
* @param[out] value clispec operator (hide/none) - direct pointer into yang, dont free
|
||||||
|
* This is for extensions with an argument
|
||||||
|
* @code
|
||||||
|
* char *value = NULL;
|
||||||
|
* if (yang_extension_value(ys, "mymode", "urn:example:lib", &value) < 0)
|
||||||
|
* err;
|
||||||
|
* if (value != NULL){
|
||||||
|
* // use extension value
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
yang_extension_value(yang_stmt *ys,
|
||||||
|
char *name,
|
||||||
|
char *ns,
|
||||||
|
char **value)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
yang_stmt *yext;
|
||||||
|
yang_stmt *ymod;
|
||||||
|
cg_var *cv;
|
||||||
|
char *prefix = NULL;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
yext = NULL; /* This loop gets complicated in trhe case the extension is augmented */
|
||||||
|
while ((yext = yn_each(ys, yext)) != NULL) {
|
||||||
|
if (yang_keyword_get(yext) != Y_UNKNOWN)
|
||||||
|
continue;
|
||||||
|
if ((ymod = ys_module(yext)) == NULL)
|
||||||
|
continue;
|
||||||
|
if (yang_find_prefix_by_namespace(ymod, ns, &prefix) < 0)
|
||||||
|
goto ok;
|
||||||
|
cprintf(cb, "%s:%s", prefix, name);
|
||||||
|
if (strcmp(yang_argument_get(yext), cbuf_get(cb)) != 0)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (yext != NULL){ /* Found */
|
||||||
|
if ((cv = yang_cv_get(yext)) == NULL)
|
||||||
|
goto ok;
|
||||||
|
if (value)
|
||||||
|
*value = cv_string_get(cv);
|
||||||
|
}
|
||||||
|
ok:
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef XML_EXPLICIT_INDEX
|
#ifdef XML_EXPLICIT_INDEX
|
||||||
/*! Mark element as search_index in list
|
/*! Mark element as search_index in list
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
|
|
|
||||||
|
|
@ -1393,6 +1393,7 @@ augment_substmt : when_stmt { clicon_debug(3,"augment-substmt -> when-s
|
||||||
| case_stmt { clicon_debug(3,"augment-substmt -> case-stmt");}
|
| case_stmt { clicon_debug(3,"augment-substmt -> case-stmt");}
|
||||||
| action_stmt { clicon_debug(3,"augment-substmt -> action-stmt");}
|
| action_stmt { clicon_debug(3,"augment-substmt -> action-stmt");}
|
||||||
| notification_stmt { clicon_debug(3,"augment-substmt -> notification-stmt");}
|
| notification_stmt { clicon_debug(3,"augment-substmt -> notification-stmt");}
|
||||||
|
| unknown_stmt { clicon_debug(3,"augment-substmt -> unknown-stmt");}
|
||||||
| { clicon_debug(3,"augment-substmt -> "); }
|
| { clicon_debug(3,"augment-substmt -> "); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -253,15 +253,6 @@ yang_augment_node(yang_stmt *ys)
|
||||||
/* The target node MUST be either a container, list, choice, case, input, output, or notification node.
|
/* The target node MUST be either a container, list, choice, case, input, output, or notification node.
|
||||||
* which means it is slightly different than a schema-nodeid ? */
|
* which means it is slightly different than a schema-nodeid ? */
|
||||||
targetkey = yang_keyword_get(ytarget);
|
targetkey = yang_keyword_get(ytarget);
|
||||||
if (targetkey != Y_CONTAINER && targetkey != Y_LIST && targetkey != Y_CHOICE &&
|
|
||||||
targetkey != Y_CASE && targetkey != Y_INPUT &&
|
|
||||||
targetkey != Y_OUTPUT && targetkey != Y_NOTIFICATION){
|
|
||||||
clicon_log(LOG_WARNING, "Warning: Augment failed in module %s: target node %s has wrong type %s",
|
|
||||||
yang_argument_get(ys_module(ys)),
|
|
||||||
schema_nodeid,
|
|
||||||
yang_key2str(targetkey));
|
|
||||||
goto ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find when statement, if present */
|
/* Find when statement, if present */
|
||||||
if ((ywhen = yang_find(ys, Y_WHEN, NULL)) != NULL){
|
if ((ywhen = yang_find(ys, Y_WHEN, NULL)) != NULL){
|
||||||
|
|
@ -272,16 +263,17 @@ yang_augment_node(yang_stmt *ys)
|
||||||
/* Extend ytarget with ys' schemanode children */
|
/* Extend ytarget with ys' schemanode children */
|
||||||
yc0 = NULL;
|
yc0 = NULL;
|
||||||
while ((yc0 = yn_each(ys, yc0)) != NULL) {
|
while ((yc0 = yn_each(ys, yc0)) != NULL) {
|
||||||
if (!yang_schemanode(yc0))
|
|
||||||
continue;
|
|
||||||
childkey = yang_keyword_get(yc0);
|
childkey = yang_keyword_get(yc0);
|
||||||
|
/* Only shemanodes and extensions */
|
||||||
|
if (!yang_schemanode(yc0) && childkey != Y_UNKNOWN)
|
||||||
|
continue;
|
||||||
switch (targetkey){
|
switch (targetkey){
|
||||||
case Y_CONTAINER:
|
case Y_CONTAINER:
|
||||||
case Y_LIST:
|
case Y_LIST:
|
||||||
/* If the target node is a container or list node, the "action" and
|
/* If the target node is a container or list node, the "action" and
|
||||||
"notification" statements can be used within the "augment" statement.
|
"notification" statements can be used within the "augment" statement.
|
||||||
*/
|
*/
|
||||||
if (childkey != Y_ACTION && childkey != Y_NOTIFICATION &&
|
if (childkey != Y_ACTION && childkey != Y_NOTIFICATION && childkey != Y_UNKNOWN &&
|
||||||
childkey != Y_CONTAINER && childkey != Y_LEAF && childkey != Y_LIST &&
|
childkey != Y_CONTAINER && childkey != Y_LEAF && childkey != Y_LIST &&
|
||||||
childkey != Y_LEAF_LIST && childkey != Y_USES && childkey != Y_CHOICE){
|
childkey != Y_LEAF_LIST && childkey != Y_USES && childkey != Y_CHOICE){
|
||||||
clicon_log(LOG_WARNING, "Warning: A Augment failed in module %s: node %s %d cannot be added to target node %s",
|
clicon_log(LOG_WARNING, "Warning: A Augment failed in module %s: node %s %d cannot be added to target node %s",
|
||||||
|
|
@ -300,8 +292,9 @@ yang_augment_node(yang_stmt *ys)
|
||||||
notification node, the "container", "leaf", "list", "leaf-list",
|
notification node, the "container", "leaf", "list", "leaf-list",
|
||||||
"uses", and "choice" statements can be used within the "augment"
|
"uses", and "choice" statements can be used within the "augment"
|
||||||
statement. */
|
statement. */
|
||||||
if (childkey != Y_CONTAINER && childkey != Y_LEAF && childkey != Y_LIST &&
|
if (childkey != Y_CONTAINER && childkey != Y_LEAF && childkey != Y_LIST &&
|
||||||
childkey != Y_LEAF_LIST && childkey != Y_USES && childkey != Y_CHOICE){
|
childkey != Y_LEAF_LIST && childkey != Y_USES && childkey != Y_CHOICE &&
|
||||||
|
childkey != Y_UNKNOWN){
|
||||||
clicon_log(LOG_WARNING, "Warning: B Augment failed in module %s: node %s %d cannot be added to target node %s",
|
clicon_log(LOG_WARNING, "Warning: B Augment failed in module %s: node %s %d cannot be added to target node %s",
|
||||||
yang_argument_get(ys_module(ys)),
|
yang_argument_get(ys_module(ys)),
|
||||||
yang_key2str(childkey),
|
yang_key2str(childkey),
|
||||||
|
|
|
||||||
288
test/test_cli_auto_extension.sh
Executable file
288
test/test_cli_auto_extension.sh
Executable file
|
|
@ -0,0 +1,288 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Tests for using autocli extension defined in clixon-lib
|
||||||
|
# This is both a test of yang extensions and autocli
|
||||||
|
# The extension is autocli-op and can take the value "hide" (maybe more)
|
||||||
|
# Try both inline and augmented mode
|
||||||
|
# @see https://clixon-docs.readthedocs.io/en/latest/misc.html#extensions
|
||||||
|
# Magic line must be first in script (see README.md)
|
||||||
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
||||||
|
APPNAME=example
|
||||||
|
|
||||||
|
fin=$dir/in
|
||||||
|
cfg=$dir/conf_yang.xml
|
||||||
|
fyang=$dir/example.yang
|
||||||
|
fyang2=$dir/$APPNAME-augment.yang
|
||||||
|
clidir=$dir/cli
|
||||||
|
if [ -d $clidir ]; then
|
||||||
|
rm -rf $clidir/*
|
||||||
|
else
|
||||||
|
mkdir $clidir
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use yang in example
|
||||||
|
|
||||||
|
cat <<EOF > $cfg
|
||||||
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
|
<CLICON_FEATURE>ietf-netconf:startup</CLICON_FEATURE>
|
||||||
|
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||||
|
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
|
||||||
|
<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>
|
||||||
|
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||||
|
<CLICON_CLISPEC_DIR>$clidir</CLICON_CLISPEC_DIR>
|
||||||
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
|
<CLICON_CLI_GENMODEL>2</CLICON_CLI_GENMODEL>
|
||||||
|
<CLICON_CLI_GENMODEL_TYPE>VARS</CLICON_CLI_GENMODEL_TYPE>
|
||||||
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
|
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
|
||||||
|
<CLICON_MODULE_LIBRARY_RFC7895>false</CLICON_MODULE_LIBRARY_RFC7895>
|
||||||
|
</clixon-config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
cat <<EOF > $clidir/ex.cli
|
||||||
|
CLICON_MODE="example";
|
||||||
|
CLICON_PROMPT="%U@%H %W> ";
|
||||||
|
|
||||||
|
# Autocli syntax tree operations
|
||||||
|
edit @datamodel, cli_auto_edit("datamodel");
|
||||||
|
up, cli_auto_up("datamodel");
|
||||||
|
top, cli_auto_top("datamodel");
|
||||||
|
set @datamodel, cli_auto_set();
|
||||||
|
merge @datamodel, cli_auto_merge();
|
||||||
|
create @datamodel, cli_auto_create();
|
||||||
|
delete("Delete a configuration item") {
|
||||||
|
@datamodel, cli_auto_del();
|
||||||
|
all("Delete whole candidate configuration"), delete_all("candidate");
|
||||||
|
}
|
||||||
|
show("Show a particular state of the system"){
|
||||||
|
configuration("Show configuration"), cli_auto_show("datamodel", "candidate", "text", true, false);{
|
||||||
|
xml("Show configuration as XML"), cli_auto_show("datamodel", "candidate", "xml", false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Yang specs must be here first for backend. But then the specs are changed but just for CLI
|
||||||
|
# Annotate original Yang spec example directly
|
||||||
|
# First annotate /table/parameter
|
||||||
|
cat <<EOF > $fyang
|
||||||
|
module example {
|
||||||
|
namespace "urn:example:clixon";
|
||||||
|
prefix ex;
|
||||||
|
import clixon-lib{
|
||||||
|
prefix cl;
|
||||||
|
}
|
||||||
|
container table{
|
||||||
|
list parameter{
|
||||||
|
key name;
|
||||||
|
leaf name{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
cl:autocli-op hide; /* This is the extension */
|
||||||
|
leaf value{
|
||||||
|
description "a value";
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
list index{
|
||||||
|
key i;
|
||||||
|
leaf i{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf iv{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Original no annotations for backend
|
||||||
|
cat <<EOF > $fyang2
|
||||||
|
module example-augment {
|
||||||
|
namespace "urn:example:augment";
|
||||||
|
prefix aug;
|
||||||
|
import example{
|
||||||
|
prefix ex;
|
||||||
|
}
|
||||||
|
import clixon-lib{
|
||||||
|
prefix cl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "test params: -f $cfg"
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
|
new "kill old backend"
|
||||||
|
sudo clixon_backend -z -f $cfg
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
err
|
||||||
|
fi
|
||||||
|
new "start backend -s init -f $cfg"
|
||||||
|
start_backend -s init -f $cfg
|
||||||
|
|
||||||
|
new "waiting"
|
||||||
|
wait_backend
|
||||||
|
fi
|
||||||
|
|
||||||
|
testparam()
|
||||||
|
{
|
||||||
|
|
||||||
|
# Try hidden parameter list
|
||||||
|
new "query table parameter hidden"
|
||||||
|
expectpart "$(echo "set table ?" | $clixon_cli -f $cfg 2>&1)" 0 "set table" "<cr>" --not-- "parameter"
|
||||||
|
|
||||||
|
cat <<EOF > $fin
|
||||||
|
set table parameter x
|
||||||
|
show config xml
|
||||||
|
EOF
|
||||||
|
new "set table parameter hidden"
|
||||||
|
expectpart "$(cat $fin | $clixon_cli -f $cfg 2>&1)" 0 "set table parameter x" "<table xmlns=\"urn:example:clixon\"><parameter><name>x</name></parameter></table>"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
testvalue()
|
||||||
|
{
|
||||||
|
# Try not hidden parameter list
|
||||||
|
new "query table parameter hidden"
|
||||||
|
expectpart "$(echo "set table ?" | $clixon_cli -f $cfg 2>&1)" 0 "set table" "<cr>" "parameter"
|
||||||
|
|
||||||
|
# Try hidden value
|
||||||
|
new "query table leaf"
|
||||||
|
expectpart "$(echo "set table parameter x ?" | $clixon_cli -f $cfg 2>&1)" 0 "index" "<cr>" --not-- "value"
|
||||||
|
|
||||||
|
cat <<EOF > $fin
|
||||||
|
set table parameter x value 42
|
||||||
|
show config xml
|
||||||
|
EOF
|
||||||
|
new "set table parameter hidden leaf"
|
||||||
|
expectpart "$(cat $fin | $clixon_cli -f $cfg 2>&1)" 0 "<table xmlns=\"urn:example:clixon\"><parameter><name>x</name><value>42</value></parameter></table>"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# INLINE MODE
|
||||||
|
|
||||||
|
new "Test hidden parameter in table/param inline"
|
||||||
|
testparam
|
||||||
|
|
||||||
|
# Second annotate /table/parameter/value
|
||||||
|
cat <<EOF > $fyang
|
||||||
|
module example {
|
||||||
|
namespace "urn:example:clixon";
|
||||||
|
prefix ex;
|
||||||
|
import clixon-lib{
|
||||||
|
prefix cl;
|
||||||
|
}
|
||||||
|
container table{
|
||||||
|
list parameter{
|
||||||
|
key name;
|
||||||
|
leaf name{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf value{
|
||||||
|
cl:autocli-op hide; /* Here is the example */
|
||||||
|
description "a value";
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
list index{
|
||||||
|
key i;
|
||||||
|
leaf i{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf iv{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "Test hidden parameter in table/param/value inline"
|
||||||
|
testvalue
|
||||||
|
|
||||||
|
# AUGMENT MODE
|
||||||
|
# Here use a new yang module that augments, keep original example intact
|
||||||
|
cat <<EOF > $fyang
|
||||||
|
module example {
|
||||||
|
namespace "urn:example:clixon";
|
||||||
|
prefix ex;
|
||||||
|
container table{
|
||||||
|
list parameter{
|
||||||
|
key name;
|
||||||
|
leaf name{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf value{
|
||||||
|
description "a value";
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
list index{
|
||||||
|
key i;
|
||||||
|
leaf i{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf iv{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# First annotate /table/parameter
|
||||||
|
cat <<EOF > $fyang2
|
||||||
|
module example-augment {
|
||||||
|
namespace "urn:example:augment";
|
||||||
|
prefix aug;
|
||||||
|
import example{
|
||||||
|
prefix ex;
|
||||||
|
}
|
||||||
|
import clixon-lib{
|
||||||
|
prefix cl;
|
||||||
|
}
|
||||||
|
augment "/ex:table/ex:parameter" {
|
||||||
|
cl:autocli-op hide;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
new "Test hidden parameter in table/param augment"
|
||||||
|
testparam
|
||||||
|
|
||||||
|
# Try hidden specific parameter key (note only cli yang)
|
||||||
|
# Second annotate /table/parameter/value
|
||||||
|
cat <<EOF > $fyang2
|
||||||
|
module example-augment {
|
||||||
|
namespace "urn:example:augment";
|
||||||
|
prefix aug;
|
||||||
|
import example{
|
||||||
|
prefix ex;
|
||||||
|
}
|
||||||
|
import clixon-lib{
|
||||||
|
prefix cl;
|
||||||
|
}
|
||||||
|
augment "/ex:table/ex:parameter/ex:value" {
|
||||||
|
cl:autocli-op hide;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "Test hidden parameter in table/param/value augment"
|
||||||
|
testvalue
|
||||||
|
|
||||||
|
new "Kill backend"
|
||||||
|
# Check if premature kill
|
||||||
|
pid=$(pgrep -u root -f clixon_backend)
|
||||||
|
if [ -z "$pid" ]; then
|
||||||
|
err "backend already dead"
|
||||||
|
fi
|
||||||
|
# kill backend
|
||||||
|
stop_backend -f $cfg
|
||||||
|
|
||||||
|
rm -rf $dir
|
||||||
|
|
@ -81,7 +81,7 @@ enter1 <string>, cli_auto_sub_enter("datamodel", "/example:table/parameter=%s/in
|
||||||
leave, cli_auto_top("datamodel", "candidate");
|
leave, cli_auto_top("datamodel", "candidate");
|
||||||
|
|
||||||
# Autocli syntax tree operations
|
# Autocli syntax tree operations
|
||||||
edit @datamodel, cli_auto_edit("interface");
|
edit @datamodel, cli_auto_edit("datamodel");
|
||||||
up, cli_auto_up("datamodel");
|
up, cli_auto_up("datamodel");
|
||||||
top, cli_auto_top("datamodel");
|
top, cli_auto_top("datamodel");
|
||||||
set @datamodel, cli_auto_set();
|
set @datamodel, cli_auto_set();
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ testrun()
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $proto://$addr/restconf/data/ietf-yang-library:modules-state/module=ietf-interfaces,2018-02-20)" 0 'HTTP/1.1 200 OK' '{"ietf-yang-library:module":\[{"name":"ietf-interfaces","revision":"2018-02-20","namespace":"urn:ietf:params:xml:ns:yang:ietf-interfaces","conformance-type":"implement"}\]}'
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $proto://$addr/restconf/data/ietf-yang-library:modules-state/module=ietf-interfaces,2018-02-20)" 0 'HTTP/1.1 200 OK' '{"ietf-yang-library:module":\[{"name":"ietf-interfaces","revision":"2018-02-20","namespace":"urn:ietf:params:xml:ns:yang:ietf-interfaces","conformance-type":"implement"}\]}'
|
||||||
|
|
||||||
new "restconf schema resource, mod-state top-level"
|
new "restconf schema resource, mod-state top-level"
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $proto://$addr/restconf/data/ietf-yang-library:modules-state)" 0 'HTTP/1.1 200 OK' '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-example","revision":"2020-12-01","namespace":"urn:example:clixon","conformance-type":"implement"},{"name":"clixon-lib","revision":"2020-04-23","'
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $proto://$addr/restconf/data/ietf-yang-library:modules-state)" 0 'HTTP/1.1 200 OK' '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-example","revision":"2020-12-01","namespace":"urn:example:clixon","conformance-type":"implement"},{"name":"clixon-lib","revision":"2020-12-08","'
|
||||||
|
|
||||||
new "restconf options. RFC 8040 4.1"
|
new "restconf options. RFC 8040 4.1"
|
||||||
expectpart "$(curl $CURLOPTS -X OPTIONS $proto://$addr/restconf/data)" 0 "HTTP/1.1 200 OK" "Allow: OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE"
|
expectpart "$(curl $CURLOPTS -X OPTIONS $proto://$addr/restconf/data)" 0 "HTTP/1.1 200 OK" "Allow: OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE"
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPR
|
||||||
# This just catches the header and the jukebox module, the RFC has foo and bar which
|
# This just catches the header and the jukebox module, the RFC has foo and bar which
|
||||||
# seems wrong to recreate
|
# seems wrong to recreate
|
||||||
new "B.1.2. Retrieve the Server Module Information"
|
new "B.1.2. Retrieve the Server Module Information"
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/ietf-yang-library:modules-state)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-lib","revision":"2020-04-23","namespace":"http://clicon.org/lib","conformance-type":"implement"}' '{"name":"example-events","revision":"","namespace":"urn:example:events","conformance-type":"implement"}' '{"name":"example-jukebox","revision":"2016-08-15","namespace":"http://example.com/ns/example-jukebox","conformance-type":"implement"}' '{"name":"example-system","revision":"","namespace":"http://example.com/ns/example-system","conformance-type":"implement"}'
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/ietf-yang-library:modules-state)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-lib","revision":"2020-12-08","namespace":"http://clicon.org/lib","conformance-type":"implement"}' '{"name":"example-events","revision":"","namespace":"urn:example:events","conformance-type":"implement"}' '{"name":"example-jukebox","revision":"2016-08-15","namespace":"http://example.com/ns/example-jukebox","conformance-type":"implement"}' '{"name":"example-system","revision":"","namespace":"http://example.com/ns/example-system","conformance-type":"implement"}'
|
||||||
|
|
||||||
new "B.1.3. Retrieve the Server Capability Information"
|
new "B.1.3. Retrieve the Server Capability Information"
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/capabilities)" 0 "HTTP/1.1 200 OK" "Content-Type: application/yang-data+xml" 'Cache-Control: no-cache' '<capabilities xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf-monitoring"><capability>urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=explicit</capability><capability>urn:ietf:params:restconf:capability:depth</capability>
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/capabilities)" 0 "HTTP/1.1 200 OK" "Content-Type: application/yang-data+xml" 'Cache-Control: no-cache' '<capabilities xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf-monitoring"><capability>urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=explicit</capability><capability>urn:ietf:params:restconf:capability:depth</capability>
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,7 @@ cat <<EOF > $dir/startup_db
|
||||||
</config>
|
</config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
MODSTATE1='<modules-state xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library"><module-set-id>0</module-set-id><module><name>clixon-lib</name><revision>2020-04-23</revision><namespace>http://clicon.org/lib</namespace></module>'
|
MODSTATE1='<modules-state xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library"><module-set-id>0</module-set-id><module><name>clixon-lib</name><revision>2020-12-08</revision><namespace>http://clicon.org/lib</namespace></module>'
|
||||||
|
|
||||||
MODSTATE2='<module><name>interfaces</name><revision>2018-02-20</revision><namespace>urn:example:interfaces</namespace></module>'
|
MODSTATE2='<module><name>interfaces</name><revision>2018-02-20</revision><namespace>urn:example:interfaces</namespace></module>'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
#
|
#
|
||||||
# 2) The extensions results in in a node data definition.
|
# 2) The extensions results in in a node data definition.
|
||||||
# Second, the example is run without the extension enabled, then it is enabled.
|
# Second, the example is run without the extension enabled, then it is enabled.
|
||||||
|
#
|
||||||
|
# @see test_cli_auto_extension
|
||||||
|
|
||||||
# Magic line must be first in script (see README.md)
|
# Magic line must be first in script (see README.md)
|
||||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ datarootdir = @datarootdir@
|
||||||
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
||||||
|
|
||||||
YANGSPECS = clixon-config@2020-11-03.yang
|
YANGSPECS = clixon-config@2020-11-03.yang
|
||||||
YANGSPECS += clixon-lib@2020-04-23.yang
|
YANGSPECS += clixon-lib@2020-12-08.yang
|
||||||
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
||||||
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
||||||
YANGSPECS += clixon-restconf@2020-10-30.yang
|
YANGSPECS += clixon-restconf@2020-10-30.yang
|
||||||
|
|
|
||||||
126
yang/clixon/clixon-lib@2020-12-08.yang
Normal file
126
yang/clixon/clixon-lib@2020-12-08.yang
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
module clixon-lib {
|
||||||
|
yang-version 1.1;
|
||||||
|
namespace "http://clicon.org/lib";
|
||||||
|
prefix cl;
|
||||||
|
|
||||||
|
organization
|
||||||
|
"Clicon / Clixon";
|
||||||
|
|
||||||
|
contact
|
||||||
|
"Olof Hagsand <olof@hagsand.se>";
|
||||||
|
|
||||||
|
description
|
||||||
|
"Clixon Netconf extensions for communication between clients and backend.
|
||||||
|
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
Copyright (C) 2009-2019 Olof Hagsand
|
||||||
|
Copyright (C) 2020 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
||||||
|
|
||||||
|
This file is part of CLIXON
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the \"License\");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an \"AS IS\" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
Alternatively, the contents of this file may be used under the terms of
|
||||||
|
the GNU General Public License Version 3 or later (the \"GPL\"),
|
||||||
|
in which case the provisions of the GPL are applicable instead
|
||||||
|
of those above. If you wish to allow use of your version of this file only
|
||||||
|
under the terms of the GPL, and not to allow others to
|
||||||
|
use your version of this file under the terms of Apache License version 2,
|
||||||
|
indicate your decision by deleting the provisions above and replace them with
|
||||||
|
the notice and other provisions required by the GPL. If you do not delete
|
||||||
|
the provisions above, a recipient may use your version of this file under
|
||||||
|
the terms of any one of the Apache License version 2 or the GPL.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****";
|
||||||
|
|
||||||
|
revision 2020-12-08 {
|
||||||
|
description
|
||||||
|
"Added: autocli-op extension.
|
||||||
|
Released in clixon 4.9";
|
||||||
|
}
|
||||||
|
revision 2020-04-23 {
|
||||||
|
description
|
||||||
|
"Added: stats RPC for clixon XML and memory statistics.
|
||||||
|
Added: restart-plugin RPC for restarting individual plugins without restarting backend.";
|
||||||
|
}
|
||||||
|
revision 2019-08-13 {
|
||||||
|
description
|
||||||
|
"No changes (reverted change)";
|
||||||
|
}
|
||||||
|
revision 2019-06-05 {
|
||||||
|
description
|
||||||
|
"ping rpc added for liveness";
|
||||||
|
}
|
||||||
|
revision 2019-01-02 {
|
||||||
|
description
|
||||||
|
"Released in Clixon 3.9";
|
||||||
|
}
|
||||||
|
extension autocli-op {
|
||||||
|
description
|
||||||
|
"Takes an argument an operation defing how to modify the clispec at
|
||||||
|
this point in the YANG tree for the automated generated CLI.
|
||||||
|
Note that this extension is only used in clixon_cli.
|
||||||
|
Operations is expected to be extended, but the following operations are defined:
|
||||||
|
- hide This command is active but not shown by ? or TAB";
|
||||||
|
argument cliop;
|
||||||
|
}
|
||||||
|
rpc debug {
|
||||||
|
description "Set debug level of backend.";
|
||||||
|
input {
|
||||||
|
leaf level {
|
||||||
|
type uint32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rpc ping {
|
||||||
|
description "Check aliveness of backend daemon.";
|
||||||
|
}
|
||||||
|
rpc stats {
|
||||||
|
description "Clixon XML statistics.";
|
||||||
|
output {
|
||||||
|
container global{
|
||||||
|
description "Clixon global statistics";
|
||||||
|
leaf xmlnr{
|
||||||
|
description "Number of XML objects: number of residing xml/json objects
|
||||||
|
in the internal 'cxobj' representation.";
|
||||||
|
type uint64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list datastore{
|
||||||
|
description "Datastore statistics";
|
||||||
|
key "name";
|
||||||
|
leaf name{
|
||||||
|
description "name of datastore (eg running).";
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf nr{
|
||||||
|
description "Number of XML objects. That is number of residing xml/json objects
|
||||||
|
in the internal 'cxobj' representation.";
|
||||||
|
type uint64;
|
||||||
|
}
|
||||||
|
leaf size{
|
||||||
|
description "Size in bytes of internal datastore cache of datastore tree.";
|
||||||
|
type uint64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rpc restart-plugin {
|
||||||
|
description "Restart specific backend plugins.";
|
||||||
|
input {
|
||||||
|
leaf-list plugin {
|
||||||
|
description "Name of plugin to restart";
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue