Removed list-pagination-partial-state extension
Refactored pagination code Reverted clixon-lib.yang to 2024-04-01 revision
This commit is contained in:
parent
b9ff2d083a
commit
f87ff859a6
19 changed files with 286 additions and 799 deletions
|
|
@ -38,8 +38,6 @@ Expected: October 2024
|
||||||
* New `clixon-config@2024-08-01.yang` revision
|
* New `clixon-config@2024-08-01.yang` revision
|
||||||
* Added: `CLICON_YANG_DOMAIN_DIR`
|
* Added: `CLICON_YANG_DOMAIN_DIR`
|
||||||
* Added: `CLICON_YANG_USE_ORIGINAL`
|
* Added: `CLICON_YANG_USE_ORIGINAL`
|
||||||
* New `clixon-lib@2024-08-01.yang` revision
|
|
||||||
- Added: list-pagination-partial-state extension
|
|
||||||
|
|
||||||
### API changes on existing protocol/config features
|
### API changes on existing protocol/config features
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
***** BEGIN LICENSE BLOCK *****
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||||
Copyright (C) 2017-2019 Olof Hagsand
|
Copyright (C) 2017-2019 Olof Hagsand
|
||||||
Copyright (C) 2020-2022 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
Copyright (C) 2020-2022 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
in which case the provisions of the GPL are applicable instead
|
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
|
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
|
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,
|
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
|
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 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 provisions above, a recipient may use your version of this file under
|
||||||
|
|
@ -93,7 +93,7 @@ restconf_client_get_capabilities(clixon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xrstate = NULL; /* xml restconf-state node */
|
cxobj *xrstate = NULL; /* xml restconf-state node */
|
||||||
cbuf *cb = NULL;
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if ((xrstate = xpath_first(*xret, NULL, "restconf-state")) == NULL){
|
if ((xrstate = xpath_first(*xret, NULL, "restconf-state")) == NULL){
|
||||||
clixon_err(OE_YANG, ENOENT, "restconf-state not found in config node");
|
clixon_err(OE_YANG, ENOENT, "restconf-state not found in config node");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -206,7 +206,7 @@ get_statedata(clixon_handle h,
|
||||||
int ret;
|
int ret;
|
||||||
cbuf *cb = NULL;
|
cbuf *cb = NULL;
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
|
|
||||||
clixon_debug(CLIXON_DBG_BACKEND, "");
|
clixon_debug(CLIXON_DBG_BACKEND, "");
|
||||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
||||||
clixon_err(OE_YANG, ENOENT, "No yang spec");
|
clixon_err(OE_YANG, ENOENT, "No yang spec");
|
||||||
|
|
@ -271,7 +271,7 @@ get_statedata(clixon_handle h,
|
||||||
xerr = NULL;
|
xerr = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* Some state, client state, is avaliable in backend only, not in lib
|
/* Some state, client state, is avaliable in backend only, not in lib
|
||||||
* Needs merge since same subtree as previous lib state
|
* Needs merge since same subtree as previous lib state
|
||||||
*/
|
*/
|
||||||
if ((ret = backend_monitoring_state_get(h, yspec, xpath, nsc, &x1, &xerr)) < 0)
|
if ((ret = backend_monitoring_state_get(h, yspec, xpath, nsc, &x1, &xerr)) < 0)
|
||||||
|
|
@ -325,16 +325,16 @@ get_statedata(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Help function to filter out anything that is outside of xpath
|
/*! Help function to filter out anything that is outside of xpath
|
||||||
*
|
*
|
||||||
* Code complex to filter out anything that is outside of xpath
|
* Code complex to filter out anything that is outside of xpath
|
||||||
* Actually this is a safety catch, should really be done in plugins
|
* Actually this is a safety catch, should really be done in plugins
|
||||||
* and modules_state functions.
|
* and modules_state functions.
|
||||||
* But it is problematic, because defaults, at least of config data, is in place
|
* But it is problematic, because defaults, at least of config data, is in place
|
||||||
* and we need to re-add it.
|
* and we need to re-add it.
|
||||||
* Note original xpath
|
* Note original xpath
|
||||||
*
|
*
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] yspec Yang spec
|
* @param[in] yspec Yang spec
|
||||||
* @param[in] xret Result XML tree
|
* @param[in] xret Result XML tree
|
||||||
* @param[in] xvec xpath lookup result on xret
|
* @param[in] xvec xpath lookup result on xret
|
||||||
|
|
@ -382,7 +382,7 @@ filter_xpath_again(clixon_handle h,
|
||||||
|
|
||||||
/*! Help function for NACM access and return message
|
/*! Help function for NACM access and return message
|
||||||
*
|
*
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] xret Result XML tree
|
* @param[in] xret Result XML tree
|
||||||
* @param[in] xvec xpath lookup result on xret
|
* @param[in] xvec xpath lookup result on xret
|
||||||
* @param[in] xlen length of xvec
|
* @param[in] xlen length of xvec
|
||||||
|
|
@ -391,7 +391,7 @@ filter_xpath_again(clixon_handle h,
|
||||||
* @param[in] username User name for NACM access
|
* @param[in] username User name for NACM access
|
||||||
* @param[in] depth Nr of levels to print, -1 is all, 0 is none
|
* @param[in] depth Nr of levels to print, -1 is all, 0 is none
|
||||||
* @param[in] wdef With-defaults parameter
|
* @param[in] wdef With-defaults parameter
|
||||||
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
|
|
@ -414,7 +414,7 @@ get_nacm_and_reply(clixon_handle h,
|
||||||
xnacm = clicon_nacm_cache(h);
|
xnacm = clicon_nacm_cache(h);
|
||||||
if (xnacm != NULL){ /* Do NACM validation */
|
if (xnacm != NULL){ /* Do NACM validation */
|
||||||
/* NACM datanode/module read validation */
|
/* NACM datanode/module read validation */
|
||||||
if (nacm_datanode_read(h, xret, xvec, xlen, username, xnacm) < 0)
|
if (nacm_datanode_read(h, xret, xvec, xlen, username, xnacm) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
cprintf(cbret, "<rpc-reply xmlns=\"%s\">", NETCONF_BASE_NAMESPACE); /* OK */
|
cprintf(cbret, "<rpc-reply xmlns=\"%s\">", NETCONF_BASE_NAMESPACE); /* OK */
|
||||||
|
|
@ -456,7 +456,7 @@ element2value(clixon_handle h,
|
||||||
{
|
{
|
||||||
char *valstr;
|
char *valstr;
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
|
|
||||||
*value = 0;
|
*value = 0;
|
||||||
if ((x = xml_find_type(xe, NULL, name, CX_ELMNT)) != NULL &&
|
if ((x = xml_find_type(xe, NULL, name, CX_ELMNT)) != NULL &&
|
||||||
(valstr = xml_body(x)) != NULL){
|
(valstr = xml_body(x)) != NULL){
|
||||||
|
|
@ -467,11 +467,11 @@ element2value(clixon_handle h,
|
||||||
|
|
||||||
/*! Extract offset and limit from get/list-pagination
|
/*! Extract offset and limit from get/list-pagination
|
||||||
*
|
*
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] xe Request: <rpc><xn></rpc>
|
* @param[in] xe Request: <rpc><xn></rpc>
|
||||||
* @param[out] offset Number of entries in the working result-set that should be skipped
|
* @param[out] offset Number of entries in the working result-set that should be skipped
|
||||||
* @param[out] limit Limits the number of entries returned from the working result-set
|
* @param[out] limit Limits the number of entries returned from the working result-set
|
||||||
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
* @retval 0 Invalid, netconf bad-element error cbret set
|
* @retval 0 Invalid, netconf bad-element error cbret set
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
|
@ -484,7 +484,7 @@ list_pagination_hdr(clixon_handle h,
|
||||||
cbuf *cbret)
|
cbuf *cbret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
||||||
/* offset */
|
/* offset */
|
||||||
if ((retval = element2value(h, xe, "offset", "none", cbret, offset)) < 0)
|
if ((retval = element2value(h, xe, "offset", "none", cbret, offset)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -497,58 +497,72 @@ list_pagination_hdr(clixon_handle h,
|
||||||
|
|
||||||
/*! Special handling of state data for partial reading
|
/*! Special handling of state data for partial reading
|
||||||
*
|
*
|
||||||
* Only if extension list-pagination-partial-state is enabled on the list
|
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] ce Client entry, for locking
|
* @param[in] ce Client entry, for locking
|
||||||
* @param[in] yspec (Top-level) yang spec
|
* @param[in] yspec (Top-level) yang spec
|
||||||
* @param[in] xpath XPath point to object to get
|
* @param[in] xpath XPath point to object to get
|
||||||
* @param[in] offset Start of pagination interval
|
* @param[in] where
|
||||||
* @param[in] limit Number of elements (limit)
|
* @param[in] sort_by
|
||||||
* @param[out] xret Returned xml state tree
|
* @param[in] direction NULL means forward
|
||||||
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
* @param[in] offset Start of pagination interval
|
||||||
* @retval 1 OK
|
* @param[in] limit Number of elements (limit)
|
||||||
* @retval 0 Fail, cbret contains error message
|
* @param[out] xret Returned xml state tree
|
||||||
* @retval -1 Error
|
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
||||||
|
* @retval 1 OK
|
||||||
|
* @retval 0 Fail, cbret contains error message
|
||||||
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
get_pagination_partial(clixon_handle h,
|
get_pagination_state_partial(clixon_handle h,
|
||||||
struct client_entry *ce,
|
struct client_entry *ce,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
uint32_t offset,
|
char *where,
|
||||||
uint32_t limit,
|
char *sort_by,
|
||||||
cxobj *xret,
|
char *direction,
|
||||||
cbuf *cbret)
|
uint32_t offset,
|
||||||
|
uint32_t limit,
|
||||||
|
cxobj *xret,
|
||||||
|
cbuf *cbret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int locked;
|
int locked;
|
||||||
cbuf *cberr = NULL;
|
cbuf *cberr = NULL;
|
||||||
uint32_t iddb; /* DBs lock, if any */
|
uint32_t iddb; /* DBs lock, if any */
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
int ret;
|
pagination_data_t pd = {0,};
|
||||||
|
dispatcher_entry_t *htable = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
clixon_debug(CLIXON_DBG_BACKEND | CLIXON_DBG_DETAIL, "");
|
||||||
if ((iddb = xmldb_islocked(h, "running")) != 0 &&
|
if ((iddb = xmldb_islocked(h, "running")) != 0 &&
|
||||||
iddb == ce->ce_id)
|
iddb == ce->ce_id)
|
||||||
locked = 1;
|
locked = 1;
|
||||||
else
|
else
|
||||||
locked = 0;
|
locked = 0;
|
||||||
if ((ret = clixon_pagination_cb_call(h, xpath, locked,
|
pd.pd_where = where;
|
||||||
offset, limit,
|
pd.pd_sort_by = sort_by;
|
||||||
xret)) < 0)
|
pd.pd_direction = direction;
|
||||||
goto done;
|
pd.pd_offset = offset;
|
||||||
if (ret == 0){
|
pd.pd_limit = limit;
|
||||||
if ((cberr = cbuf_new()) == NULL){
|
pd.pd_locked = locked;
|
||||||
clixon_err(OE_UNIX, errno, "cbuf_new");
|
pd.pd_xstate = xret;
|
||||||
goto done;
|
clicon_ptr_get(h, "pagination-entries", (void**)&htable);
|
||||||
|
if (htable){
|
||||||
|
if (dispatcher_call_handlers(htable, h, xpath, &pd) < 0){
|
||||||
|
if ((cberr = cbuf_new()) == NULL){
|
||||||
|
clixon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* error reason should be in clixon_err_reason */
|
||||||
|
cprintf(cberr, "Internal error, pagination state callback invalid return : %s",
|
||||||
|
clixon_err_reason());
|
||||||
|
if (netconf_operation_failed_xml(&xerr, "application", cbuf_get(cberr)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (clixon_xml2cbuf(cbret, xerr, 0, 0, NULL, -1, 0) < 0)
|
||||||
|
goto done;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
/* error reason should be in clixon_err_reason */
|
|
||||||
cprintf(cberr, "Internal error, pagination state callback invalid return : %s",
|
|
||||||
clixon_err_reason());
|
|
||||||
if (netconf_operation_failed_xml(&xerr, "application", cbuf_get(cberr)) < 0)
|
|
||||||
goto done;
|
|
||||||
if (clixon_xml2cbuf(cbret, xerr, 0, 0, NULL, -1, 0) < 0)
|
|
||||||
goto done;
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* System makes the binding */
|
/* System makes the binding */
|
||||||
|
|
@ -580,9 +594,9 @@ get_pagination_partial(clixon_handle h,
|
||||||
*
|
*
|
||||||
* It is specialized enough to have its own function. Specifically, extra attributes as well
|
* It is specialized enough to have its own function. Specifically, extra attributes as well
|
||||||
* as the list-paginaiton API
|
* as the list-paginaiton API
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] ce Client entry, for locking
|
* @param[in] ce Client entry, for locking
|
||||||
* @param[in] xe Request: <rpc><xn></rpc>
|
* @param[in] xe Request: <rpc><xn></rpc>
|
||||||
* @param[in] content Get config/state/both
|
* @param[in] content Get config/state/both
|
||||||
* @param[in] db Database name
|
* @param[in] db Database name
|
||||||
* @param[in] depth Depth attribute
|
* @param[in] depth Depth attribute
|
||||||
|
|
@ -591,10 +605,10 @@ get_pagination_partial(clixon_handle h,
|
||||||
* @param[in] nsc Namespace context of xpath
|
* @param[in] nsc Namespace context of xpath
|
||||||
* @param[in] username
|
* @param[in] username
|
||||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
* @param[in] wdef With-defaults parameter, see RFC 6243
|
||||||
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @note pagination uses appending xpath with predicate, eg [position()<limit], this may not work
|
* @note pagination uses appending xpath with predicate, eg [position()<limit], this may not work
|
||||||
* if there is an existing predicate
|
* if there is an existing predicate
|
||||||
* XXX Reuse code with get_common
|
* XXX Reuse code with get_common
|
||||||
* From draft-ietf-netconf-list-pagination-04.txt 3.1:
|
* From draft-ietf-netconf-list-pagination-04.txt 3.1:
|
||||||
|
|
@ -637,16 +651,18 @@ get_list_pagination(clixon_handle h,
|
||||||
char *sort_by = NULL;
|
char *sort_by = NULL;
|
||||||
char *direction = NULL;
|
char *direction = NULL;
|
||||||
char *where = NULL;
|
char *where = NULL;
|
||||||
int extflag = 0;
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
int ret;
|
int ret;
|
||||||
|
dispatcher_entry_t *htable = NULL;
|
||||||
|
// int extflag = 0;
|
||||||
#ifdef LIST_PAGINATION_REMAINING
|
#ifdef LIST_PAGINATION_REMAINING
|
||||||
cxobj *xcache;
|
cxobj *xcache;
|
||||||
uint32_t total;
|
uint32_t total;
|
||||||
uint32_t remaining = 0;
|
uint32_t remaining = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
clixon_debug(CLIXON_DBG_BACKEND | CLIXON_DBG_DETAIL, "");
|
||||||
if (cbret == NULL){
|
if (cbret == NULL){
|
||||||
clixon_err(OE_PLUGIN, EINVAL, "cbret is NULL");
|
clixon_err(OE_PLUGIN, EINVAL, "cbret is NULL");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -685,13 +701,14 @@ get_list_pagination(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
if (yang_extension_value(ylist, "list-pagination-partial-state", CLIXON_LIB_NS, &extflag, NULL) < 0)
|
clicon_ptr_get(h, "pagination-entries", (void**)&htable);
|
||||||
goto done;
|
if (htable) {
|
||||||
if (extflag){ /* pagination_cb / partial state API */
|
if ((ret = dispatcher_match_exact(htable, xpath)) < 0)
|
||||||
partial_pagination_cb = 1;
|
goto done;
|
||||||
|
if (ret > 0)
|
||||||
|
partial_pagination_cb = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first processes the "where" parameter (see Section 3.1.1) */
|
/* first processes the "where" parameter (see Section 3.1.1) */
|
||||||
if ((x = xml_find_type(xe, NULL, "where", CX_ELMNT)) != NULL &&
|
if ((x = xml_find_type(xe, NULL, "where", CX_ELMNT)) != NULL &&
|
||||||
(where = xml_body(x)) != NULL){
|
(where = xml_body(x)) != NULL){
|
||||||
|
|
@ -749,35 +766,32 @@ get_list_pagination(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
}/* switch content */
|
}/* switch content */
|
||||||
switch (content){ /* Read state */
|
|
||||||
case CONTENT_CONFIG: /* config data only */
|
|
||||||
break;
|
|
||||||
case CONTENT_ALL: /* both config and state */
|
|
||||||
case CONTENT_NONCONFIG: /* state data only */
|
|
||||||
if (partial_pagination_cb) /* Partial reads, special handling */
|
|
||||||
break;
|
|
||||||
if ((ret = get_statedata(h, xpath?xpath:"/", nsc, &xret)) < 0)
|
|
||||||
goto done;
|
|
||||||
if (ret == 0){ /* Error from callback (error in xret) */
|
|
||||||
if (clixon_xml2cbuf(cbret, xret, 0, 0, NULL, -1, 0) < 0)
|
|
||||||
goto done;
|
|
||||||
goto ok;
|
|
||||||
}
|
|
||||||
/* Add defaults to state data. This consumes some cycles */
|
|
||||||
/* Ensure all state-data is report-all */
|
|
||||||
if (xml_global_defaults(h, xret, nsc, xpath, yspec, 1) < 0)
|
|
||||||
goto done;
|
|
||||||
/* Apply default values */
|
|
||||||
if (xml_default_recurse(xret, 1, 0) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (partial_pagination_cb) {
|
if (partial_pagination_cb) {
|
||||||
if ((ret = get_pagination_partial(h, ce, yspec, xpath, offset, limit, xret, cbret)) < 0)
|
if ((ret = get_pagination_state_partial(h, ce, yspec, xpath,
|
||||||
|
where, sort_by, direction,
|
||||||
|
offset, limit,
|
||||||
|
xret, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (content != CONTENT_CONFIG){
|
||||||
|
if ((ret = get_statedata(h, xpath?xpath:"/", nsc, &xret)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 0){ /* Error from callback (error in xret) */
|
||||||
|
if (clixon_xml2cbuf(cbret, xret, 0, 0, NULL, -1, 0) < 0)
|
||||||
|
goto done;
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
/* Add defaults to state data. This consumes some cycles */
|
||||||
|
/* Ensure all state-data is report-all */
|
||||||
|
if (xml_global_defaults(h, xret, nsc, xpath, yspec, 1) < 0)
|
||||||
|
goto done;
|
||||||
|
/* Apply default values */
|
||||||
|
if (xml_default_recurse(xret, 1, 0) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
/* first processes the "where" parameter (see Section 3.1.1) */
|
/* first processes the "where" parameter (see Section 3.1.1) */
|
||||||
if (where){
|
if (where){
|
||||||
if (xpath_vec(xret, nsc, "%s[%s]", &xvec, &xlen, xpath?xpath:"/", where) < 0)
|
if (xpath_vec(xret, nsc, "%s[%s]", &xvec, &xlen, xpath?xpath:"/", where) < 0)
|
||||||
|
|
@ -864,10 +878,10 @@ get_list_pagination(clixon_handle h,
|
||||||
if (filter_xpath_again(h, yspec, xret, xvec, xlen, xpath, nsc) < 0)
|
if (filter_xpath_again(h, yspec, xret, xvec, xlen, xpath, nsc) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
#ifdef LIST_PAGINATION_REMAINING
|
#ifdef LIST_PAGINATION_REMAINING
|
||||||
/* Add remaining attribute Sec 3.1.5:
|
/* Add remaining attribute Sec 3.1.5:
|
||||||
Any list or leaf-list that is limited includes, on the first element in the result set,
|
Any list or leaf-list that is limited includes, on the first element in the result set,
|
||||||
a metadata value [RFC7952] called "remaining"*/
|
a metadata value [RFC7952] called "remaining"*/
|
||||||
if (limit && x1){
|
if (limit && x1){
|
||||||
cxobj *xa;
|
cxobj *xa;
|
||||||
cbuf *cba = NULL;
|
cbuf *cba = NULL;
|
||||||
|
|
||||||
|
|
@ -901,16 +915,16 @@ get_list_pagination(clixon_handle h,
|
||||||
|
|
||||||
/*! Common get/get-config code for retrieving configuration and state information.
|
/*! Common get/get-config code for retrieving configuration and state information.
|
||||||
*
|
*
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] ce Client entry, for locking
|
* @param[in] ce Client entry, for locking
|
||||||
* @param[in] xe Request: <rpc><xn></rpc>
|
* @param[in] xe Request: <rpc><xn></rpc>
|
||||||
* @param[in] content Get config/state/both
|
* @param[in] content Get config/state/both
|
||||||
* @param[in] db Database name
|
* @param[in] db Database name
|
||||||
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @see from_client_get
|
* @see from_client_get
|
||||||
* @see from_client_get_config
|
* @see from_client_get_config
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
get_common(clixon_handle h,
|
get_common(clixon_handle h,
|
||||||
|
|
@ -986,7 +1000,7 @@ get_common(clixon_handle h,
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((wdefstr = xml_find_body(xe, "with-defaults")) != NULL)
|
if ((wdefstr = xml_find_body(xe, "with-defaults")) != NULL)
|
||||||
wdef = withdefaults_str2int(wdefstr);
|
wdef = withdefaults_str2int(wdefstr);
|
||||||
/* How to check if list-pagination?
|
/* How to check if list-pagination?
|
||||||
* Problem is clixon expands messages on entry and pagination default values + non-presence cont
|
* Problem is clixon expands messages on entry and pagination default values + non-presence cont
|
||||||
|
|
@ -1073,7 +1087,7 @@ get_common(clixon_handle h,
|
||||||
break;
|
break;
|
||||||
}/* switch content */
|
}/* switch content */
|
||||||
/* If not only config,
|
/* If not only config,
|
||||||
* get state data from plugins as defined by plugin_statedata(), if any
|
* get state data from plugins as defined by plugin_statedata(), if any
|
||||||
*/
|
*/
|
||||||
/* Read state */
|
/* Read state */
|
||||||
switch (content){
|
switch (content){
|
||||||
|
|
@ -1099,11 +1113,11 @@ get_common(clixon_handle h,
|
||||||
}
|
}
|
||||||
if (content != CONTENT_CONFIG &&
|
if (content != CONTENT_CONFIG &&
|
||||||
clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
|
clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
|
||||||
/* Check XML by validating it. return internal error with error cause
|
/* Check XML by validating it. return internal error with error cause
|
||||||
* Primarily intended for user-supplied state-data.
|
* Primarily intended for user-supplied state-data.
|
||||||
* The whole config tree must be present in case the state data references config data
|
* The whole config tree must be present in case the state data references config data
|
||||||
*/
|
*/
|
||||||
if ((ret = xml_yang_validate_all_top(h, xret, &xerr)) < 0)
|
if ((ret = xml_yang_validate_all_top(h, xret, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret > 0 &&
|
if (ret > 0 &&
|
||||||
(ret = xml_yang_validate_add(h, xret, &xerr)) < 0)
|
(ret = xml_yang_validate_add(h, xret, &xerr)) < 0)
|
||||||
|
|
@ -1197,8 +1211,8 @@ from_client_get_config(clixon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Retrieve running configuration and device state information.
|
/*! Retrieve running configuration and device state
|
||||||
*
|
*
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] xe Request: <rpc><xn></rpc>
|
* @param[in] xe Request: <rpc><xn></rpc>
|
||||||
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
||||||
|
|
@ -1207,7 +1221,7 @@ from_client_get_config(clixon_handle h,
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
*
|
*
|
||||||
* @see from_client_get_config
|
* @see from_client_get_config
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
from_client_get(clixon_handle h,
|
from_client_get(clixon_handle h,
|
||||||
|
|
|
||||||
|
|
@ -485,42 +485,6 @@ clixon_plugin_lockdb_all(clixon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Traverse state data callbacks for partial pagination state callbacks
|
|
||||||
*
|
|
||||||
* Only if list-pagination-partial-state extension is set
|
|
||||||
* @param[in] h Clixon handle
|
|
||||||
* @param[in] xpath Registered XPath using canonical prefixes
|
|
||||||
* @param[in] locked Running datastore is locked by this caller
|
|
||||||
* @param[in] offset Start of pagination interval
|
|
||||||
* @param[in] limit Number of elements (limit)
|
|
||||||
* @param[out] xstate Returned xml state tree
|
|
||||||
* @retval 1 OK
|
|
||||||
* @retval -1 Error
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
clixon_pagination_cb_call(clixon_handle h,
|
|
||||||
char *xpath,
|
|
||||||
int locked,
|
|
||||||
uint32_t offset,
|
|
||||||
uint32_t limit,
|
|
||||||
cxobj *xstate)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
pagination_data_t pd;
|
|
||||||
dispatcher_entry_t *htable = NULL;
|
|
||||||
|
|
||||||
pd.pd_offset = offset;
|
|
||||||
pd.pd_limit = limit;
|
|
||||||
pd.pd_locked = locked;
|
|
||||||
pd.pd_xstate = xstate;
|
|
||||||
clicon_ptr_get(h, "pagination-entries", (void**)&htable);
|
|
||||||
if (htable && dispatcher_call_handlers(htable, h, xpath, &pd) < 0)
|
|
||||||
goto done;
|
|
||||||
retval = 1; // XXX 0?
|
|
||||||
done:
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Register a state data callback
|
/*! Register a state data callback
|
||||||
*
|
*
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,9 @@ typedef struct {
|
||||||
* @see pagination_offset() and other accessor functions
|
* @see pagination_offset() and other accessor functions
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
char *pd_where;
|
||||||
|
char *pd_sort_by;
|
||||||
|
char *pd_direction;
|
||||||
uint32_t pd_offset; /* Start of pagination interval */
|
uint32_t pd_offset; /* Start of pagination interval */
|
||||||
uint32_t pd_limit; /* Number of elements (limit) */
|
uint32_t pd_limit; /* Number of elements (limit) */
|
||||||
int pd_locked; /* Running datastore is locked by this caller */
|
int pd_locked; /* Running datastore is locked by this caller */
|
||||||
|
|
@ -104,9 +107,6 @@ int clixon_plugin_statedata_all(clixon_handle h, yang_stmt *yspec, cvec *nsc, ch
|
||||||
int clixon_plugin_lockdb_all(clixon_handle h, char *db, int lock, int id);
|
int clixon_plugin_lockdb_all(clixon_handle h, char *db, int lock, int id);
|
||||||
|
|
||||||
int clixon_pagination_cb_register(clixon_handle h, handler_function fn, char *path, void *arg);
|
int clixon_pagination_cb_register(clixon_handle h, handler_function fn, char *path, void *arg);
|
||||||
int clixon_pagination_cb_call(clixon_handle h, char *xpath, int locked,
|
|
||||||
uint32_t offset, uint32_t limit,
|
|
||||||
cxobj *xstate);
|
|
||||||
int clixon_pagination_free(clixon_handle h);
|
int clixon_pagination_free(clixon_handle h);
|
||||||
|
|
||||||
transaction_data_t * transaction_new(void);
|
transaction_data_t * transaction_new(void);
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ enum restconf_media{
|
||||||
YANG_DATA_XML, /* "application/yang-data+xml" */
|
YANG_DATA_XML, /* "application/yang-data+xml" */
|
||||||
YANG_PATCH_JSON, /* "application/yang-patch+json" */
|
YANG_PATCH_JSON, /* "application/yang-patch+json" */
|
||||||
YANG_PATCH_XML, /* "application/yang-patch+xml" */
|
YANG_PATCH_XML, /* "application/yang-patch+xml" */
|
||||||
YANG_PAGINATION_XML, /* draft-wwlh-netconf-list-pagination-rc-02.txt */
|
YANG_PAGINATION_XML, /* draft-netconf-list-pagination-04.txt */
|
||||||
HTTP_DATA_TEXT_HTML /* For http_data */
|
HTTP_DATA_TEXT_HTML /* For http_data */
|
||||||
/* For JSON, the existing "application/yang-data+json" media type is
|
/* For JSON, the existing "application/yang-data+json" media type is
|
||||||
sufficient, as the JSON format has built-in support for encoding
|
sufficient, as the JSON format has built-in support for encoding
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ static const map_str2int http_media_map[] = {
|
||||||
{"application/yang-data+json", YANG_DATA_JSON},
|
{"application/yang-data+json", YANG_DATA_JSON},
|
||||||
{"application/yang-patch+xml", YANG_PATCH_XML},
|
{"application/yang-patch+xml", YANG_PATCH_XML},
|
||||||
{"application/yang-patch+json", YANG_PATCH_JSON},
|
{"application/yang-patch+json", YANG_PATCH_JSON},
|
||||||
{"application/yang-data+xml-list", YANG_PAGINATION_XML}, /* draft-wwlh-netconf-list-pagination-rc-02 */
|
{"application/yang-data+xml-list", YANG_PAGINATION_XML}, /* sdraft-netconf-list-pagination-04.txt */
|
||||||
{"text/html", HTTP_DATA_TEXT_HTML}, /* for http_data */
|
{"text/html", HTTP_DATA_TEXT_HTML}, /* for http_data */
|
||||||
{NULL, -1}
|
{NULL, -1}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ enum restconf_media{
|
||||||
YANG_DATA_XML, /* "application/yang-data+xml" */
|
YANG_DATA_XML, /* "application/yang-data+xml" */
|
||||||
YANG_PATCH_JSON, /* "application/yang-patch+json" */
|
YANG_PATCH_JSON, /* "application/yang-patch+json" */
|
||||||
YANG_PATCH_XML, /* "application/yang-patch+xml" */
|
YANG_PATCH_XML, /* "application/yang-patch+xml" */
|
||||||
YANG_PAGINATION_XML, /* draft-wwlh-netconf-list-pagination-rc-02.txt */
|
YANG_PAGINATION_XML, /* draft-netconf-list-pagination-04.txt */
|
||||||
HTTP_DATA_TEXT_HTML /* For http_data */
|
HTTP_DATA_TEXT_HTML /* For http_data */
|
||||||
};
|
};
|
||||||
typedef enum restconf_media restconf_media;
|
typedef enum restconf_media restconf_media;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
***** BEGIN LICENSE BLOCK *****
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
Copyright (C) 2021 Rubicon Communications, LLC(Netgate)
|
Copyright (C) 2021 Rubicon Communications, LLC(Netgate)
|
||||||
|
|
||||||
This file is part of CLIXON.
|
This file is part of CLIXON.
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
in which case the provisions of the GPL are applicable instead
|
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
|
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
|
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,
|
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
|
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 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 provisions above, a recipient may use your version of this file under
|
||||||
|
|
@ -45,6 +45,8 @@
|
||||||
* @param[in] xpath Registered XPath using canonical prefixes
|
* @param[in] xpath Registered XPath using canonical prefixes
|
||||||
* @param[in] userargs Per-call user arguments
|
* @param[in] userargs Per-call user arguments
|
||||||
* @param[in] arg Per-path user argument
|
* @param[in] arg Per-path user argument
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
typedef int (*handler_function)(void *handle, char *path, void *userargs, void *arg);
|
typedef int (*handler_function)(void *handle, char *path, void *userargs, void *arg);
|
||||||
|
|
||||||
|
|
@ -68,36 +70,36 @@ struct _dispatcher_entry {
|
||||||
/*
|
/*
|
||||||
* the name of this node, NOT the complete path
|
* the name of this node, NOT the complete path
|
||||||
*/
|
*/
|
||||||
char *node_name;
|
char *de_node_name;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* peer points at peer to the right of this one
|
* peer points at peer to the right of this one
|
||||||
* if NULL then this is the rightmost and last on list
|
* if NULL then this is the rightmost and last on list
|
||||||
*/
|
*/
|
||||||
dispatcher_entry_t *peer;
|
dispatcher_entry_t *de_peer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* peer_head points at leftmost peer at this level
|
* peer_head points at leftmost peer at this level
|
||||||
* if NULL, then this is the leftmost and first on the list
|
* if NULL, then this is the leftmost and first on the list
|
||||||
* XXX: it seems it points to itself if it is first on the list?
|
* XXX: it seems it points to itself if it is first on the list?
|
||||||
*/
|
*/
|
||||||
dispatcher_entry_t *peer_head;
|
dispatcher_entry_t *de_peer_head;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* points at peer_head of children list
|
* points at peer_head of children list
|
||||||
* if NULL, then no children
|
* if NULL, then no children
|
||||||
*/
|
*/
|
||||||
dispatcher_entry_t *children;
|
dispatcher_entry_t *de_children;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pointer to handler function for this node
|
* pointer to handler function for this node
|
||||||
*/
|
*/
|
||||||
handler_function handler;
|
handler_function de_handler;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* End-user argument
|
* End-user argument
|
||||||
*/
|
*/
|
||||||
void *arg;
|
void *de_arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -105,6 +107,7 @@ struct _dispatcher_entry {
|
||||||
*/
|
*/
|
||||||
int dispatcher_register_handler(dispatcher_entry_t **root, dispatcher_definition *x);
|
int dispatcher_register_handler(dispatcher_entry_t **root, dispatcher_definition *x);
|
||||||
int dispatcher_call_handlers(dispatcher_entry_t *root, void *handle, char *path, void *user_args);
|
int dispatcher_call_handlers(dispatcher_entry_t *root, void *handle, char *path, void *user_args);
|
||||||
|
int dispatcher_match_exact(dispatcher_entry_t *root, char *path);
|
||||||
int dispatcher_free(dispatcher_entry_t *root);
|
int dispatcher_free(dispatcher_entry_t *root);
|
||||||
int dispatcher_print(FILE *f, int level, dispatcher_entry_t *root);
|
int dispatcher_print(FILE *f, int level, dispatcher_entry_t *root);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
***** BEGIN LICENSE BLOCK *****
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
Copyright (C) 2021 Rubicon Communications, LLC(Netgate)
|
Copyright (C) 2021 Rubicon Communications, LLC(Netgate)
|
||||||
|
|
||||||
This file is part of CLIXON.
|
This file is part of CLIXON.
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
in which case the provisions of the GPL are applicable instead
|
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
|
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
|
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,
|
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
|
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 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 provisions above, a recipient may use your version of this file under
|
||||||
|
|
@ -196,13 +196,13 @@ find_peer(dispatcher_entry_t *node, char *node_name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
i = node->peer_head;
|
i = node->de_peer_head;
|
||||||
|
|
||||||
while (i != NULL) {
|
while (i != NULL) {
|
||||||
if (strcmp(node_name, i->node_name) == 0) {
|
if (strcmp(node_name, i->de_node_name) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i = i->peer;
|
i = i->de_peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
|
@ -228,10 +228,10 @@ add_peer_node(dispatcher_entry_t *node,
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
/* this is a new node */
|
/* this is a new node */
|
||||||
|
|
||||||
new_node->node_name = strdup(name);
|
new_node->de_node_name = strdup(name);
|
||||||
new_node->peer = NULL;
|
new_node->de_peer = NULL;
|
||||||
new_node->children = NULL;
|
new_node->de_children = NULL;
|
||||||
new_node->peer_head = new_node;
|
new_node->de_peer_head = new_node;
|
||||||
|
|
||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
@ -239,27 +239,27 @@ add_peer_node(dispatcher_entry_t *node,
|
||||||
/* possibly adding to the list */
|
/* possibly adding to the list */
|
||||||
|
|
||||||
/* search for existing, or get tail end of list */
|
/* search for existing, or get tail end of list */
|
||||||
eptr = node->peer_head;
|
eptr = node->de_peer_head;
|
||||||
while (eptr->peer != NULL) {
|
while (eptr->de_peer != NULL) {
|
||||||
if (strcmp(eptr->node_name, name) == 0) {
|
if (strcmp(eptr->de_node_name, name) == 0) {
|
||||||
free(new_node);
|
free(new_node);
|
||||||
return eptr;
|
return eptr;
|
||||||
}
|
}
|
||||||
eptr = eptr->peer;
|
eptr = eptr->de_peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if eptr->node_name == name, we done
|
// if eptr->de_node_name == name, we done
|
||||||
if (strcmp(eptr->node_name, name) == 0) {
|
if (strcmp(eptr->de_node_name, name) == 0) {
|
||||||
free(new_node);
|
free(new_node);
|
||||||
return eptr;
|
return eptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_node->node_name = strdup(name);
|
new_node->de_node_name = strdup(name);
|
||||||
new_node->peer = NULL;
|
new_node->de_peer = NULL;
|
||||||
new_node->children = NULL;
|
new_node->de_children = NULL;
|
||||||
new_node->peer_head = node->peer_head;
|
new_node->de_peer_head = node->de_peer_head;
|
||||||
|
|
||||||
eptr->peer = new_node;
|
eptr->de_peer = new_node;
|
||||||
|
|
||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
@ -282,19 +282,19 @@ add_child_node(dispatcher_entry_t *node,
|
||||||
{
|
{
|
||||||
dispatcher_entry_t *child_ptr;
|
dispatcher_entry_t *child_ptr;
|
||||||
|
|
||||||
if ((child_ptr = add_peer_node(node->children, name)) == NULL)
|
if ((child_ptr = add_peer_node(node->de_children, name)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
node->children = child_ptr->peer_head;
|
node->de_children = child_ptr->de_peer_head;
|
||||||
|
|
||||||
return child_ptr;
|
return child_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
*
|
*
|
||||||
* @param root
|
* @param[in] root
|
||||||
* @param path
|
* @param[in] path
|
||||||
* @retval
|
* @retval entry
|
||||||
* @retval NULL Error
|
* @retval NULL Error
|
||||||
*/
|
*/
|
||||||
static dispatcher_entry_t *
|
static dispatcher_entry_t *
|
||||||
get_entry(dispatcher_entry_t *root,
|
get_entry(dispatcher_entry_t *root,
|
||||||
|
|
@ -317,20 +317,19 @@ get_entry(dispatcher_entry_t *root,
|
||||||
|
|
||||||
/* search down the tree */
|
/* search down the tree */
|
||||||
for (int i = 0; i < split_path_len; i++) {
|
for (int i = 0; i < split_path_len; i++) {
|
||||||
|
|
||||||
char *query = split_path_list[i];
|
char *query = split_path_list[i];
|
||||||
if ((ptr = find_peer(ptr, query)) == NULL) {
|
if ((ptr = find_peer(ptr, query)) == NULL) {
|
||||||
split_path_free(split_path_list, split_path_len);
|
split_path_free(split_path_list, split_path_len);
|
||||||
/* we ran out of matches, use last found handler */
|
/* we ran out of matches, use last found handler */
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
if (ptr->handler != NULL) {
|
if (ptr->de_handler != NULL) {
|
||||||
/* if handler is defined, save it */
|
/* if handler is defined, save it */
|
||||||
best = ptr;
|
best = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* skip to next element */
|
/* skip to next element */
|
||||||
ptr = ptr->children;
|
ptr = ptr->de_children;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean up */
|
/* clean up */
|
||||||
|
|
@ -338,13 +337,14 @@ get_entry(dispatcher_entry_t *root,
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*! Given a pointer to an entry, call the handler and all descendant and peer handlers.
|
||||||
* given a pointer to an entry, call the handler and all
|
|
||||||
* descendant and peer handlers.
|
|
||||||
*
|
*
|
||||||
* @param entry
|
* @param[in] entry
|
||||||
* @param path
|
* @param[in] handle
|
||||||
* @retval
|
* @param[in] path
|
||||||
|
* @param[in] user_args
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
call_handler_helper(dispatcher_entry_t *entry,
|
call_handler_helper(dispatcher_entry_t *entry,
|
||||||
|
|
@ -352,17 +352,23 @@ call_handler_helper(dispatcher_entry_t *entry,
|
||||||
char *path,
|
char *path,
|
||||||
void *user_args)
|
void *user_args)
|
||||||
{
|
{
|
||||||
if (entry->children != NULL) {
|
int retval = -1;
|
||||||
call_handler_helper(entry->children, handle, path, user_args);
|
|
||||||
}
|
|
||||||
if (entry->peer != NULL) {
|
|
||||||
call_handler_helper(entry->peer, handle, path, user_args);
|
|
||||||
}
|
|
||||||
if (entry->handler != NULL) {
|
|
||||||
(entry->handler)(handle, path, user_args, entry->arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
if (entry->de_children != NULL) {
|
||||||
|
if (call_handler_helper(entry->de_children, handle, path, user_args) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (entry->de_peer != NULL) {
|
||||||
|
if (call_handler_helper(entry->de_peer, handle, path, user_args) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (entry->de_handler != NULL) {
|
||||||
|
if ((entry->de_handler)(handle, path, user_args, entry->de_arg) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -416,8 +422,8 @@ dispatcher_register_handler(dispatcher_entry_t **root,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* when we get here, ptr points at last entry added */
|
/* when we get here, ptr points at last entry added */
|
||||||
ptr->handler = x->dd_handler;
|
ptr->de_handler = x->dd_handler;
|
||||||
ptr->arg = x->dd_arg;
|
ptr->de_arg = x->dd_arg;
|
||||||
|
|
||||||
/* clean up */
|
/* clean up */
|
||||||
split_path_free(split_path_list, split_path_len);
|
split_path_free(split_path_list, split_path_len);
|
||||||
|
|
@ -436,8 +442,7 @@ dispatcher_register_handler(dispatcher_entry_t **root,
|
||||||
* @param[in] handle
|
* @param[in] handle
|
||||||
* @param[in] root
|
* @param[in] root
|
||||||
* @param[in] path Note must be on the form: /a/b (no keys)
|
* @param[in] path Note must be on the form: /a/b (no keys)
|
||||||
* @retval 1 OK
|
* @retval 0 OK
|
||||||
* @retval 0 Invalid
|
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -446,20 +451,67 @@ dispatcher_call_handlers(dispatcher_entry_t *root,
|
||||||
char *path,
|
char *path,
|
||||||
void *user_args)
|
void *user_args)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int retval = -1;
|
||||||
dispatcher_entry_t *best;
|
dispatcher_entry_t *best;
|
||||||
|
|
||||||
if ((best = get_entry(root, path)) == NULL){
|
if ((best = get_entry(root, path)) == NULL){
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return -1;
|
goto done;
|
||||||
}
|
}
|
||||||
if (best->children != NULL) {
|
if (best->de_children != NULL) {
|
||||||
call_handler_helper(best->children, handle, path, user_args);
|
if (call_handler_helper(best->de_children, handle, path, user_args) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
if (best->handler != NULL) {
|
if (best->de_handler != NULL) {
|
||||||
ret = (*best->handler)(handle, path, user_args, best->arg);
|
if ((*best->de_handler)(handle, path, user_args, best->de_arg) < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
return ret;
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Check if any handler is registered for the path
|
||||||
|
* @param[in] root
|
||||||
|
* @param[in] path Note must be on the form: /a/b (no keys)
|
||||||
|
* @retval 1 Yes, at least one handler
|
||||||
|
* @retval 0 No handler
|
||||||
|
* @retval -1 Error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
dispatcher_match_exact(dispatcher_entry_t *root,
|
||||||
|
char *path)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
dispatcher_entry_t *ptr;
|
||||||
|
dispatcher_entry_t *ptr1 = NULL;
|
||||||
|
char **split_path_list = NULL;
|
||||||
|
size_t split_path_len = 0;
|
||||||
|
char *str;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* cut the path up into individual elements */
|
||||||
|
if (split_path(path, &split_path_list, &split_path_len) < 0)
|
||||||
|
goto done;
|
||||||
|
ptr = root;
|
||||||
|
/* search down the tree */
|
||||||
|
for (i = 0; i < split_path_len; i++) {
|
||||||
|
str = split_path_list[i];
|
||||||
|
strsep(&str, "=[]");
|
||||||
|
str = split_path_list[i];
|
||||||
|
if ((ptr1 = find_peer(ptr, str)) == NULL)
|
||||||
|
break;
|
||||||
|
ptr = ptr1->de_children;
|
||||||
|
}
|
||||||
|
if (i == split_path_len && ptr1 && ptr1->de_handler)
|
||||||
|
retval = 1;
|
||||||
|
else
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
/* clean up */
|
||||||
|
if (split_path_list)
|
||||||
|
split_path_free(split_path_list, split_path_len);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Free a dispatcher tree
|
/*! Free a dispatcher tree
|
||||||
|
|
@ -469,12 +521,12 @@ dispatcher_free(dispatcher_entry_t *root)
|
||||||
{
|
{
|
||||||
if (root == NULL)
|
if (root == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
if (root->children)
|
if (root->de_children)
|
||||||
dispatcher_free(root->children);
|
dispatcher_free(root->de_children);
|
||||||
if (root->peer)
|
if (root->de_peer)
|
||||||
dispatcher_free(root->peer);
|
dispatcher_free(root->de_peer);
|
||||||
if (root->node_name)
|
if (root->de_node_name)
|
||||||
free(root->node_name);
|
free(root->de_node_name);
|
||||||
free(root);
|
free(root);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -487,15 +539,15 @@ dispatcher_print(FILE *f,
|
||||||
int level,
|
int level,
|
||||||
dispatcher_entry_t *de)
|
dispatcher_entry_t *de)
|
||||||
{
|
{
|
||||||
fprintf(f, "%*s%s", level*INDENT, "", de->node_name);
|
fprintf(f, "%*s%s", level*INDENT, "", de->de_node_name);
|
||||||
if (de->handler)
|
if (de->de_handler)
|
||||||
fprintf(f, " %p", de->handler);
|
fprintf(f, " %p", de->de_handler);
|
||||||
if (de->arg)
|
if (de->de_arg)
|
||||||
fprintf(f, " (%p)", de->arg);
|
fprintf(f, " (%p)", de->de_arg);
|
||||||
fprintf(f, "\n");
|
fprintf(f, "\n");
|
||||||
if (de->children)
|
if (de->de_children)
|
||||||
dispatcher_print(f, level+1, de->children);
|
dispatcher_print(f, level+1, de->de_children);
|
||||||
if (de->peer)
|
if (de->de_peer)
|
||||||
dispatcher_print(f, level, de->peer);
|
dispatcher_print(f, level, de->de_peer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ DATASTORE_TOP="config"
|
||||||
|
|
||||||
# clixon yang revisions occuring in tests (see eg yang/clixon/Makefile.in)
|
# clixon yang revisions occuring in tests (see eg yang/clixon/Makefile.in)
|
||||||
CLIXON_AUTOCLI_REV="2024-08-01"
|
CLIXON_AUTOCLI_REV="2024-08-01"
|
||||||
CLIXON_LIB_REV="2024-08-01"
|
CLIXON_LIB_REV="2024-04-01"
|
||||||
CLIXON_CONFIG_REV="2024-08-01"
|
CLIXON_CONFIG_REV="2024-08-01"
|
||||||
CLIXON_RESTCONF_REV="2022-08-01"
|
CLIXON_RESTCONF_REV="2022-08-01"
|
||||||
CLIXON_EXAMPLE_REV="2022-11-01"
|
CLIXON_EXAMPLE_REV="2022-11-01"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Example-social from draft-netconf-list-pagination-00.txt appendix A.1
|
# Example-social from draft-netconf-list-pagination-04.txt appendix A.1
|
||||||
# Assumes variable fexample is set to name of yang file
|
# Assumes variable fexample is set to name of yang file
|
||||||
# Also: leaf-list member/state/numbers is added
|
# Also: leaf-list member/state/numbers is added
|
||||||
# Mark deviation from original with "Clixon"
|
# Mark deviation from original with "Clixon"
|
||||||
|
|
@ -265,7 +265,6 @@ cat <<EOF > $fexample
|
||||||
list audit-log {
|
list audit-log {
|
||||||
description
|
description
|
||||||
"List of audit logs.";
|
"List of audit logs.";
|
||||||
cl:list-pagination-partial-state; // Clixon
|
|
||||||
leaf timestamp {
|
leaf timestamp {
|
||||||
type yang:date-and-time;
|
type yang:date-and-time;
|
||||||
mandatory true;
|
mandatory true;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# List pagination tests loosely based on draft-wwlh-netconf-list-pagination-00
|
# List pagination tests loosely based on draft-ietf-netconf-list-pagination-04
|
||||||
# The example-social yang file is used
|
# The example-social yang file is used
|
||||||
# This tests contains a large config list: members/member/favorites/uint8-numbers
|
# This tests contains a large config list: members/member/favorites/uint8-numbers
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ cat <<EOF > $cfg
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Based on draft-wwlh-netconf-list-pagination-00 A.2 but bob has a generated uint8-numbers list
|
# Based on draft-netconf-list-pagination-04.txt A.2 but bob has a generated uint8-numbers list
|
||||||
# start file
|
# start file
|
||||||
cat <<'EOF' > $dir/startup_db
|
cat <<'EOF' > $dir/startup_db
|
||||||
<config>
|
<config>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# List pagination tests according to draft-wwlh-netconf-list-pagination-00
|
# List pagination tests according to draft-ietf-netconf-list-pagination-04
|
||||||
# Follow the example-social example in the draft and the tests in Appendix A.2 + A.3.1/A.3.2
|
# Follow the example-social example in the draft and the tests in Appendix A.2 + A.3.1/A.3.2
|
||||||
# Basically only offset and limit supported
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|
@ -49,7 +48,7 @@ cat <<EOF > $cfg
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# See draft-wwlh-netconf-list-pagination-00 A.2 (except stats and audit-log)
|
# See draft-netconf-list-pagination-04.txt A.2 (except stats and audit-log)
|
||||||
# XXX: "config" without
|
# XXX: "config" without
|
||||||
cat <<'EOF' > $dir/startup_db
|
cat <<'EOF' > $dir/startup_db
|
||||||
{"config":
|
{"config":
|
||||||
|
|
@ -167,7 +166,7 @@ cat <<'EOF' > $dir/startup_db
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# See draft-wwlh-netconf-list-pagination-00 A.2 (only stats and audit-log)
|
# See draft-netconf-list-pagination-04.txt A.2 (only stats and audit-log)
|
||||||
cat<<EOF > $fstate
|
cat<<EOF > $fstate
|
||||||
<members xmlns="https://example.com/ns/example-social">
|
<members xmlns="https://example.com/ns/example-social">
|
||||||
<member>
|
<member>
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ cat <<EOF > $cfg
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# See draft-wwlh-netconf-list-pagination-00 A.2 (except stats and audit-log)
|
# See draft-netconf-list-pagination-04.txt A.2 (except stats and audit-log)
|
||||||
cat <<'EOF' > $dir/startup_db
|
cat <<'EOF' > $dir/startup_db
|
||||||
{"config":
|
{"config":
|
||||||
{
|
{
|
||||||
|
|
@ -155,7 +155,7 @@ cat <<'EOF' > $dir/startup_db
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# See draft-wwlh-netconf-list-pagination-00 A.2 (only stats and audit-log)
|
# See draft-netconf-list-pagination-04.txt A.2 (only stats and audit-log)
|
||||||
cat<<EOF > $fstate
|
cat<<EOF > $fstate
|
||||||
<members xmlns="https://example.com/ns/example-social">
|
<members xmlns="https://example.com/ns/example-social">
|
||||||
<member>
|
<member>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# List pagination tests loosely based on draft-wwlh-netconf-list-pagination-00
|
# List pagination tests loosely based on draft-ietf-netconf-list-pagination-04
|
||||||
# The example-social yang file is used
|
# The example-social yang file is used
|
||||||
# Three tests to get state pagination data:
|
# Three tests to get state pagination data:
|
||||||
# 1. NETCONF get a specific list (alice->numbers)
|
# 1. NETCONF get a specific list (alice->numbers)
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
# 3. CLI get audit logs (only interactive)
|
# 3. CLI get audit logs (only interactive)
|
||||||
# This tests contains a large state list: audit-logs from the example
|
# This tests contains a large state list: audit-logs from the example
|
||||||
# Only CLI is used
|
# Only CLI is used
|
||||||
# Test also of list-pagination-partial-state 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
|
||||||
|
|
@ -52,7 +51,7 @@ cat <<EOF > $cfg
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# See draft-wwlh-netconf-list-pagination-00 A.2 (only stats and audit-log)
|
# See draft-netconf-list-pagination-04.txt A.2 (only stats and audit-log)
|
||||||
cat<<EOF > $fstate
|
cat<<EOF > $fstate
|
||||||
<members xmlns="https://example.com/ns/example-social">
|
<members xmlns="https://example.com/ns/example-social">
|
||||||
<member>
|
<member>
|
||||||
|
|
@ -135,6 +134,7 @@ function testrun_stop()
|
||||||
|
|
||||||
xpath0="/es:members/es:member[es:member-id='alice']/es:stats"
|
xpath0="/es:members/es:member[es:member-id='alice']/es:stats"
|
||||||
xpath="$xpath0/es:numbers"
|
xpath="$xpath0/es:numbers"
|
||||||
|
|
||||||
testrun_start $xpath
|
testrun_start $xpath
|
||||||
|
|
||||||
new "NETCONF get leaf-list member/numbers 0-10 alice"
|
new "NETCONF get leaf-list member/numbers 0-10 alice"
|
||||||
|
|
|
||||||
|
|
@ -368,7 +368,7 @@ module pattern{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
leaf p47 {
|
leaf p47 {
|
||||||
description "draft-wwlh-netconf-list-pagination-00 module example-social";
|
description "draft-netconf-list-pagination-04 module example-social";
|
||||||
type string {
|
type string {
|
||||||
length "1..80";
|
length "1..80";
|
||||||
pattern '.*[\n].*' {
|
pattern '.*[\n].*' {
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
||||||
|
|
||||||
# Note: mirror these to test/config.sh.in
|
# Note: mirror these to test/config.sh.in
|
||||||
YANGSPECS = clixon-config@2024-08-01.yang # 7.2
|
YANGSPECS = clixon-config@2024-08-01.yang # 7.2
|
||||||
YANGSPECS += clixon-lib@2024-08-01.yang # 7.2
|
YANGSPECS += clixon-lib@2024-04-01.yang # 7.1
|
||||||
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@2022-08-01.yang # 5.9
|
YANGSPECS += clixon-restconf@2022-08-01.yang # 5.9
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ module clixon-lib {
|
||||||
"***** BEGIN LICENSE BLOCK *****
|
"***** BEGIN LICENSE BLOCK *****
|
||||||
Copyright (C) 2009-2019 Olof Hagsand
|
Copyright (C) 2009-2019 Olof Hagsand
|
||||||
Copyright (C) 2020-2022 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
Copyright (C) 2020-2022 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
||||||
|
|
||||||
This file is part of CLIXON
|
This file is part of CLIXON
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the \"License\");
|
Licensed under the Apache License, Version 2.0 (the \"License\");
|
||||||
|
|
@ -40,7 +40,7 @@ module clixon-lib {
|
||||||
in which case the provisions of the GPL are applicable instead
|
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
|
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
|
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,
|
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
|
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 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 provisions above, a recipient may use your version of this file under
|
||||||
|
|
@ -50,7 +50,7 @@ module clixon-lib {
|
||||||
|
|
||||||
Clixon Netconf extensions for communication between clients and backend.
|
Clixon Netconf extensions for communication between clients and backend.
|
||||||
This scheme adds:
|
This scheme adds:
|
||||||
- Added values of RFC6022 transport identityref
|
- Added values of RFC6022 transport identityref
|
||||||
- RPCs for debug, stats and process-control
|
- RPCs for debug, stats and process-control
|
||||||
- Informal description of attributes
|
- Informal description of attributes
|
||||||
|
|
||||||
|
|
@ -68,7 +68,6 @@ module clixon-lib {
|
||||||
- objectexisted
|
- objectexisted
|
||||||
- link # For split multiple XML files
|
- link # For split multiple XML files
|
||||||
";
|
";
|
||||||
|
|
||||||
revision 2024-04-01 {
|
revision 2024-04-01 {
|
||||||
description
|
description
|
||||||
"Added: debug bits type
|
"Added: debug bits type
|
||||||
|
|
@ -100,7 +99,7 @@ module clixon-lib {
|
||||||
}
|
}
|
||||||
revision 2022-12-01 {
|
revision 2022-12-01 {
|
||||||
description
|
description
|
||||||
"Added values of RFC6022 transport identityref
|
"Added values of RFC6022 transport identityref
|
||||||
Added description of internal netconf attributes";
|
Added description of internal netconf attributes";
|
||||||
}
|
}
|
||||||
revision 2021-12-05 {
|
revision 2021-12-05 {
|
||||||
|
|
@ -302,7 +301,7 @@ module clixon-lib {
|
||||||
}
|
}
|
||||||
identity netconf {
|
identity netconf {
|
||||||
description
|
description
|
||||||
"Just NETCONF without specific underlying transport,
|
"Just NETCONF without specific underlying transport,
|
||||||
Clixon uses stdio for its netconf client and therefore does not know whether it is
|
Clixon uses stdio for its netconf client and therefore does not know whether it is
|
||||||
invoked in a script, by a NETCONF/SSH subsystem, etc";
|
invoked in a script, by a NETCONF/SSH subsystem, etc";
|
||||||
base ncm:transport;
|
base ncm:transport;
|
||||||
|
|
@ -328,7 +327,7 @@ module clixon-lib {
|
||||||
description
|
description
|
||||||
"When split configuration stores are used, ie CLICON_XMLDB_MULTI is set,
|
"When split configuration stores are used, ie CLICON_XMLDB_MULTI is set,
|
||||||
This extension marks where in the configuration tree, one file terminates
|
This extension marks where in the configuration tree, one file terminates
|
||||||
and a new sub-file is written.
|
and a new sub-file is written.
|
||||||
A designer adds the 'xmldb-split' extension to a YANG node which should be split.
|
A designer adds the 'xmldb-split' extension to a YANG node which should be split.
|
||||||
For example, a split could be made at mountpoints.
|
For example, a split could be made at mountpoints.
|
||||||
See also the 'link 'attribute.
|
See also the 'link 'attribute.
|
||||||
|
|
@ -341,7 +340,7 @@ module clixon-lib {
|
||||||
One application is the clixon controller where multiple services can
|
One application is the clixon controller where multiple services can
|
||||||
create the same object. When such a service is deleted (or changed) one needs to keep
|
create the same object. When such a service is deleted (or changed) one needs to keep
|
||||||
track of which service created what.
|
track of which service created what.
|
||||||
Limitations: only objects that are actually added or deleted.
|
Limitations: only objects that are actually added or deleted.
|
||||||
A sub-object will not be noted";
|
A sub-object will not be noted";
|
||||||
}
|
}
|
||||||
rpc debug {
|
rpc debug {
|
||||||
|
|
@ -369,7 +368,7 @@ module clixon-lib {
|
||||||
output {
|
output {
|
||||||
container global{
|
container global{
|
||||||
description
|
description
|
||||||
"Clixon global statistics.
|
"Clixon global statistics.
|
||||||
These are global counters incremented by new() and decreased by free() calls.
|
These are global counters incremented by new() and decreased by free() calls.
|
||||||
This number is higher than the sum of all datastore/module residing objects, since
|
This number is higher than the sum of all datastore/module residing objects, since
|
||||||
objects may be used for other purposes than datastore/modules";
|
objects may be used for other purposes than datastore/modules";
|
||||||
|
|
@ -406,10 +405,10 @@ module clixon-lib {
|
||||||
}
|
}
|
||||||
container module-sets{
|
container module-sets{
|
||||||
list module-set{
|
list module-set{
|
||||||
description "Statistics per group of module, eg top-level and mount-points";
|
description "Statistics per domain, eg top-level and mount-points";
|
||||||
key "name";
|
key "name";
|
||||||
leaf name{
|
leaf name{
|
||||||
description "Name of YANG module.";
|
description "Name of YANG domain.";
|
||||||
type string;
|
type string;
|
||||||
}
|
}
|
||||||
leaf nr{
|
leaf nr{
|
||||||
|
|
@ -456,7 +455,7 @@ module clixon-lib {
|
||||||
rpc process-control {
|
rpc process-control {
|
||||||
description
|
description
|
||||||
"Control a specific process or daemon: start/stop, etc.
|
"Control a specific process or daemon: start/stop, etc.
|
||||||
This is for direct managing of a process by the backend.
|
This is for direct managing of a process by the backend.
|
||||||
Alternatively one can manage a daemon via systemd, containerd, kubernetes, etc.";
|
Alternatively one can manage a daemon via systemd, containerd, kubernetes, etc.";
|
||||||
input {
|
input {
|
||||||
leaf name {
|
leaf name {
|
||||||
|
|
@ -478,7 +477,7 @@ module clixon-lib {
|
||||||
"Output from status rpc";
|
"Output from status rpc";
|
||||||
leaf active {
|
leaf active {
|
||||||
description
|
description
|
||||||
"True if process is running, false if not.
|
"True if process is running, false if not.
|
||||||
More specifically, there is a process-id and it exists (in Linux: kill(pid,0).
|
More specifically, there is a process-id and it exists (in Linux: kill(pid,0).
|
||||||
Note that this is actual state and status is administrative state,
|
Note that this is actual state and status is administrative state,
|
||||||
which means that changing the administrative state, eg stopped->running
|
which means that changing the administrative state, eg stopped->running
|
||||||
|
|
|
||||||
|
|
@ -1,541 +0,0 @@
|
||||||
module clixon-lib {
|
|
||||||
yang-version 1.1;
|
|
||||||
namespace "http://clicon.org/lib";
|
|
||||||
prefix cl;
|
|
||||||
|
|
||||||
import ietf-yang-types {
|
|
||||||
prefix yang;
|
|
||||||
}
|
|
||||||
import ietf-netconf-monitoring {
|
|
||||||
prefix ncm;
|
|
||||||
}
|
|
||||||
import ietf-yang-metadata {
|
|
||||||
prefix "md";
|
|
||||||
}
|
|
||||||
organization
|
|
||||||
"Clicon / Clixon";
|
|
||||||
|
|
||||||
contact
|
|
||||||
"Olof Hagsand <olof@hagsand.se>";
|
|
||||||
|
|
||||||
description
|
|
||||||
"***** BEGIN LICENSE BLOCK *****
|
|
||||||
Copyright (C) 2009-2019 Olof Hagsand
|
|
||||||
Copyright (C) 2020-2022 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 *****
|
|
||||||
|
|
||||||
Clixon Netconf extensions for communication between clients and backend.
|
|
||||||
This scheme adds:
|
|
||||||
- Added values of RFC6022 transport identityref
|
|
||||||
- RPCs for debug, stats and process-control
|
|
||||||
- Informal description of attributes
|
|
||||||
|
|
||||||
Clixon also extends NETCONF for internal use with some internal attributes. These
|
|
||||||
are not visible for external usage bit belongs to the namespace of this YANG.
|
|
||||||
The internal attributes are:
|
|
||||||
- content (also RESTCONF)
|
|
||||||
- depth (also RESTCONF)
|
|
||||||
- username
|
|
||||||
- autocommit
|
|
||||||
- copystartup
|
|
||||||
- transport (see RFC6022)
|
|
||||||
- source-host (see RFC6022)
|
|
||||||
- objectcreate
|
|
||||||
- objectexisted
|
|
||||||
- link # For split multiple XML files
|
|
||||||
";
|
|
||||||
|
|
||||||
revision 2024-08-01 {
|
|
||||||
description
|
|
||||||
"Added: list-pagination-partial-state
|
|
||||||
Released in Clixon 7.2";
|
|
||||||
}
|
|
||||||
revision 2024-04-01 {
|
|
||||||
description
|
|
||||||
"Added: debug bits type
|
|
||||||
Added: xmldb-split extension
|
|
||||||
Added: Default format
|
|
||||||
Released in Clixon 7.1";
|
|
||||||
}
|
|
||||||
revision 2024-01-01 {
|
|
||||||
description
|
|
||||||
"Removed container creators from 6.5
|
|
||||||
Released in 7.0";
|
|
||||||
}
|
|
||||||
revision 2023-11-01 {
|
|
||||||
description
|
|
||||||
"Added ignore-compare extension
|
|
||||||
Added creator meta configuration
|
|
||||||
Removed obsolete extension autocli-op
|
|
||||||
Released in 6.5.0";
|
|
||||||
}
|
|
||||||
revision 2023-05-01 {
|
|
||||||
description
|
|
||||||
"Restructured and extended stats rpc to schema mountpoints
|
|
||||||
Moved datastore-format typedef from clixon-config
|
|
||||||
";
|
|
||||||
}
|
|
||||||
revision 2023-03-01 {
|
|
||||||
description
|
|
||||||
"Added creator meta-object";
|
|
||||||
}
|
|
||||||
revision 2022-12-01 {
|
|
||||||
description
|
|
||||||
"Added values of RFC6022 transport identityref
|
|
||||||
Added description of internal netconf attributes";
|
|
||||||
}
|
|
||||||
revision 2021-12-05 {
|
|
||||||
description
|
|
||||||
"Obsoleted: extension autocli-op";
|
|
||||||
}
|
|
||||||
revision 2021-11-11 {
|
|
||||||
description
|
|
||||||
"Changed: RPC stats extended with YANG stats";
|
|
||||||
}
|
|
||||||
revision 2021-03-08 {
|
|
||||||
description
|
|
||||||
"Changed: RPC process-control output to choice dependent on operation";
|
|
||||||
}
|
|
||||||
revision 2020-12-30 {
|
|
||||||
description
|
|
||||||
"Changed: RPC process-control output parameter status to pid";
|
|
||||||
}
|
|
||||||
revision 2020-12-08 {
|
|
||||||
description
|
|
||||||
"Added: autocli-op extension.
|
|
||||||
rpc process-control for process/daemon management
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
typedef service-operation {
|
|
||||||
type enumeration {
|
|
||||||
enum start {
|
|
||||||
description
|
|
||||||
"Start if not already running";
|
|
||||||
}
|
|
||||||
enum stop {
|
|
||||||
description
|
|
||||||
"Stop if running";
|
|
||||||
}
|
|
||||||
enum restart {
|
|
||||||
description
|
|
||||||
"Stop if running, then start";
|
|
||||||
}
|
|
||||||
enum status {
|
|
||||||
description
|
|
||||||
"Check status";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
description
|
|
||||||
"Common operations that can be performed on a service";
|
|
||||||
}
|
|
||||||
typedef datastore_format{
|
|
||||||
description
|
|
||||||
"Datastore format (only xml and json implemented in actual data.";
|
|
||||||
type enumeration{
|
|
||||||
enum xml{
|
|
||||||
description
|
|
||||||
"Save and load xmldb as XML
|
|
||||||
More specifically, such a file looks like: <config>...</config> provided
|
|
||||||
DATASTORE_TOP_SYMBOL is 'config'";
|
|
||||||
}
|
|
||||||
enum json{
|
|
||||||
description "Save and load xmldb as JSON";
|
|
||||||
}
|
|
||||||
enum text{
|
|
||||||
description "'Curly' C-like text format";
|
|
||||||
}
|
|
||||||
enum cli{
|
|
||||||
description "CLI format";
|
|
||||||
}
|
|
||||||
enum default{
|
|
||||||
description "Default format";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
typedef clixon_debug_t {
|
|
||||||
description
|
|
||||||
"Debug flags.
|
|
||||||
Flags are seperated into subject areas and detail
|
|
||||||
Can also be given directly as -D <flag> to clixon commands
|
|
||||||
Note there are also constants in the code that need to be in sync with these values";
|
|
||||||
type bits {
|
|
||||||
/* Subjects: */
|
|
||||||
bit default {
|
|
||||||
description "Default logs";
|
|
||||||
position 0;
|
|
||||||
}
|
|
||||||
bit msg {
|
|
||||||
description "In/out messages";
|
|
||||||
position 1;
|
|
||||||
}
|
|
||||||
bit init {
|
|
||||||
description "Initialization";
|
|
||||||
position 2;
|
|
||||||
}
|
|
||||||
bit xml {
|
|
||||||
description "XML processing";
|
|
||||||
position 3;
|
|
||||||
}
|
|
||||||
bit xpath {
|
|
||||||
description "XPath processing";
|
|
||||||
position 4;
|
|
||||||
}
|
|
||||||
bit yang {
|
|
||||||
description "YANG processing";
|
|
||||||
position 5;
|
|
||||||
}
|
|
||||||
bit backend {
|
|
||||||
description "Backend-specific";
|
|
||||||
position 6;
|
|
||||||
}
|
|
||||||
bit cli {
|
|
||||||
description "CLI frontend";
|
|
||||||
position 7;
|
|
||||||
}
|
|
||||||
bit netconf {
|
|
||||||
description "NETCONF frontend";
|
|
||||||
position 8;
|
|
||||||
}
|
|
||||||
bit restconf {
|
|
||||||
description "RESTCONF frontend";
|
|
||||||
position 9;
|
|
||||||
}
|
|
||||||
bit snmp {
|
|
||||||
description "SNMP frontend";
|
|
||||||
position 10;
|
|
||||||
}
|
|
||||||
bit nacm {
|
|
||||||
description "NACM processing";
|
|
||||||
position 11;
|
|
||||||
}
|
|
||||||
bit proc {
|
|
||||||
description "Process handling";
|
|
||||||
position 12;
|
|
||||||
}
|
|
||||||
bit datastore {
|
|
||||||
description "Datastore xmldb management";
|
|
||||||
position 13;
|
|
||||||
}
|
|
||||||
bit event {
|
|
||||||
description "Event processing";
|
|
||||||
position 14;
|
|
||||||
}
|
|
||||||
bit rpc {
|
|
||||||
description "RPC handling";
|
|
||||||
position 15;
|
|
||||||
}
|
|
||||||
bit stream {
|
|
||||||
description "Notification streams";
|
|
||||||
position 16;
|
|
||||||
}
|
|
||||||
bit parse {
|
|
||||||
description "Parser: XML,YANG, etc";
|
|
||||||
position 17;
|
|
||||||
}
|
|
||||||
bit app {
|
|
||||||
description "External applications";
|
|
||||||
position 20;
|
|
||||||
}
|
|
||||||
bit app2 {
|
|
||||||
description "External application";
|
|
||||||
position 21;
|
|
||||||
}
|
|
||||||
bit app3 {
|
|
||||||
description "External application 2";
|
|
||||||
position 22;
|
|
||||||
}
|
|
||||||
/* Detail level: */
|
|
||||||
bit detail {
|
|
||||||
description "Details: traces, parse trees, etc";
|
|
||||||
position 24;
|
|
||||||
}
|
|
||||||
bit detail2 {
|
|
||||||
description "Extra details";
|
|
||||||
position 25;
|
|
||||||
}
|
|
||||||
bit detail3 {
|
|
||||||
description "Probably more detail than you want";
|
|
||||||
position 26;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
identity snmp {
|
|
||||||
description
|
|
||||||
"SNMP";
|
|
||||||
base ncm:transport;
|
|
||||||
}
|
|
||||||
identity netconf {
|
|
||||||
description
|
|
||||||
"Just NETCONF without specific underlying transport,
|
|
||||||
Clixon uses stdio for its netconf client and therefore does not know whether it is
|
|
||||||
invoked in a script, by a NETCONF/SSH subsystem, etc";
|
|
||||||
base ncm:transport;
|
|
||||||
}
|
|
||||||
identity restconf {
|
|
||||||
description
|
|
||||||
"RESTCONF either as HTTP/1 or /2, TLS or not, reverse proxy (eg fcgi/nginx) or native";
|
|
||||||
base ncm:transport;
|
|
||||||
}
|
|
||||||
identity cli {
|
|
||||||
description
|
|
||||||
"A CLI session";
|
|
||||||
base ncm:transport;
|
|
||||||
}
|
|
||||||
extension list-pagination-partial-state {
|
|
||||||
description
|
|
||||||
"List should be partially read according to the clixon_pagination_cb_register API.
|
|
||||||
This is a performance enhancement of pagination state data.
|
|
||||||
This means that a special callback is used for retreiving list state which is aware of
|
|
||||||
offset/limit attributes.
|
|
||||||
In this way the non-config data can be partially read by the server, instead of reading
|
|
||||||
the whole state on every pagination request.
|
|
||||||
It affects only the server/backend-side
|
|
||||||
It only handles the offset and limit attributes, all other attributes,
|
|
||||||
such as where, sort-by, direction, etc, are ignored";
|
|
||||||
}
|
|
||||||
extension ignore-compare {
|
|
||||||
description
|
|
||||||
"The object should be ignored when comparing device configs for equality.
|
|
||||||
The object should never be added, modified, or deleted on target.
|
|
||||||
Essentially a read-only object
|
|
||||||
One example is auto-created objects by the controller, such as uid.";
|
|
||||||
}
|
|
||||||
extension xmldb-split {
|
|
||||||
description
|
|
||||||
"When split configuration stores are used, ie CLICON_XMLDB_MULTI is set,
|
|
||||||
This extension marks where in the configuration tree, one file terminates
|
|
||||||
and a new sub-file is written.
|
|
||||||
A designer adds the 'xmldb-split' extension to a YANG node which should be split.
|
|
||||||
For example, a split could be made at mountpoints.
|
|
||||||
See also the 'link 'attribute.
|
|
||||||
";
|
|
||||||
}
|
|
||||||
md:annotation creator {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"This annotation contains the name of a creator of an object.
|
|
||||||
One application is the clixon controller where multiple services can
|
|
||||||
create the same object. When such a service is deleted (or changed) one needs to keep
|
|
||||||
track of which service created what.
|
|
||||||
Limitations: only objects that are actually added or deleted.
|
|
||||||
A sub-object will not be noted";
|
|
||||||
}
|
|
||||||
rpc debug {
|
|
||||||
description
|
|
||||||
"Set debug flags of backend.
|
|
||||||
Note only numerical values";
|
|
||||||
input {
|
|
||||||
leaf level {
|
|
||||||
type uint32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rpc ping {
|
|
||||||
description "Check aliveness of backend daemon.";
|
|
||||||
}
|
|
||||||
rpc stats { /* Could be moved to state */
|
|
||||||
description "Clixon yang and datastore statistics.";
|
|
||||||
input {
|
|
||||||
leaf modules {
|
|
||||||
description "If enabled include per-module statistics";
|
|
||||||
type boolean;
|
|
||||||
mandatory false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output {
|
|
||||||
container global{
|
|
||||||
description
|
|
||||||
"Clixon global statistics.
|
|
||||||
These are global counters incremented by new() and decreased by free() calls.
|
|
||||||
This number is higher than the sum of all datastore/module residing objects, since
|
|
||||||
objects may be used for other purposes than datastore/modules";
|
|
||||||
leaf xmlnr{
|
|
||||||
description
|
|
||||||
"Number of existing XML objects: number of residing xml/json objects
|
|
||||||
in the internal 'cxobj' representation.";
|
|
||||||
type uint64;
|
|
||||||
}
|
|
||||||
leaf yangnr{
|
|
||||||
description
|
|
||||||
"Number of resident YANG objects. ";
|
|
||||||
type uint64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container datastores{
|
|
||||||
list datastore{
|
|
||||||
description "Per datastore statistics for cxobj";
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container module-sets{
|
|
||||||
list module-set{
|
|
||||||
description "Statistics per domain, eg top-level and mount-points";
|
|
||||||
key "name";
|
|
||||||
leaf name{
|
|
||||||
description "Name of YANG domain.";
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
leaf nr{
|
|
||||||
description
|
|
||||||
"Total number of YANG objects in set";
|
|
||||||
type uint64;
|
|
||||||
}
|
|
||||||
leaf size{
|
|
||||||
description
|
|
||||||
"Total size in bytes of internal YANG object representation for module set";
|
|
||||||
type uint64;
|
|
||||||
}
|
|
||||||
list module{
|
|
||||||
description "Statistics per module (if modules set in input)";
|
|
||||||
key "name";
|
|
||||||
leaf name{
|
|
||||||
description "Name of YANG module.";
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
leaf nr{
|
|
||||||
description
|
|
||||||
"Number of YANG objects. That is number of residing YANG objects";
|
|
||||||
type uint64;
|
|
||||||
}
|
|
||||||
leaf size{
|
|
||||||
description
|
|
||||||
"Size in bytes of internal YANG object representation.";
|
|
||||||
type uint64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rpc restart-plugin {
|
|
||||||
description "Restart specific backend plugins.";
|
|
||||||
input {
|
|
||||||
leaf-list plugin {
|
|
||||||
description "Name of plugin to restart";
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rpc process-control {
|
|
||||||
description
|
|
||||||
"Control a specific process or daemon: start/stop, etc.
|
|
||||||
This is for direct managing of a process by the backend.
|
|
||||||
Alternatively one can manage a daemon via systemd, containerd, kubernetes, etc.";
|
|
||||||
input {
|
|
||||||
leaf name {
|
|
||||||
description "Name of process";
|
|
||||||
type string;
|
|
||||||
mandatory true;
|
|
||||||
}
|
|
||||||
leaf operation {
|
|
||||||
type service-operation;
|
|
||||||
mandatory true;
|
|
||||||
description
|
|
||||||
"One of the strings 'start', 'stop', 'restart', or 'status'.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output {
|
|
||||||
choice result {
|
|
||||||
case status {
|
|
||||||
description
|
|
||||||
"Output from status rpc";
|
|
||||||
leaf active {
|
|
||||||
description
|
|
||||||
"True if process is running, false if not.
|
|
||||||
More specifically, there is a process-id and it exists (in Linux: kill(pid,0).
|
|
||||||
Note that this is actual state and status is administrative state,
|
|
||||||
which means that changing the administrative state, eg stopped->running
|
|
||||||
may not immediately switch active to true.";
|
|
||||||
type boolean;
|
|
||||||
}
|
|
||||||
leaf description {
|
|
||||||
type string;
|
|
||||||
description "Description of process. This is a static string";
|
|
||||||
}
|
|
||||||
leaf command {
|
|
||||||
type string;
|
|
||||||
description "Start command with arguments";
|
|
||||||
}
|
|
||||||
leaf status {
|
|
||||||
description
|
|
||||||
"Administrative status (except on external kill where it enters stopped
|
|
||||||
directly from running):
|
|
||||||
stopped: pid=0, No process running
|
|
||||||
running: pid set, Process started and believed to be running
|
|
||||||
exiting: pid set, Process is killed by parent but not waited for";
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
leaf starttime {
|
|
||||||
description "Time of starting process UTC";
|
|
||||||
type yang:date-and-time;
|
|
||||||
}
|
|
||||||
leaf pid {
|
|
||||||
description "Process-id of main running process (if active)";
|
|
||||||
type uint32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case other {
|
|
||||||
description
|
|
||||||
"Output from start/stop/restart rpc";
|
|
||||||
leaf ok {
|
|
||||||
type empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue