Creator attribute changes: added as xmldb metadata
clixon-config.yang: New revision and Added `CLICON_NETCONF_CREATOR_ATTR` option clixon-lib.yang: Added creator meta Changed return value of xml_add_attr
This commit is contained in:
parent
be3001acf5
commit
bbcb4a7b03
20 changed files with 474 additions and 93 deletions
|
|
@ -55,9 +55,11 @@ Users may have to change how they access the system
|
|||
### C/CLI-API changes on existing features
|
||||
Developers may need to change their code
|
||||
|
||||
* Changed return value of `xml_add_attr` from 0/-1 to xa/NULL
|
||||
* You need to change eg `if (xml_add_attr < 0)` to if (xml_add_attr == NULL)`
|
||||
* Changed signature of `clicon_netconf_error()` and `netconf_err2cb()`
|
||||
* You need to add the clixon handle as first parameter:
|
||||
* `clicon_netconf_error(...)` --> `clicon_netconf_error(h, ...)`
|
||||
* `clicon_netconf_error(...)` --> `clixon_netconf_error(h, ...)`
|
||||
* `netconf_err2cb(...)` --> `netconf_err2cb(h, ...)`
|
||||
* Changed function name for `clicon_debug` functions. You need to rename as follows:
|
||||
* clicon_debug() -> clixon_debug()
|
||||
|
|
@ -71,8 +73,11 @@ Developers may need to change their code
|
|||
* New feature: [Customized NETCONF error message](https://github.com/clicon/clixon/issues/454)
|
||||
* Added new callback `.ca_errmsg`
|
||||
* See https://clixon-docs.readthedocs.io/en/latest/errors.html#customized-errors for more info
|
||||
* New `clixon-config@2023-11-01.yang` revision
|
||||
* Added `CLICON_NETCONF_CREATOR_ATTR` option
|
||||
* New `clixon-lib@2023-11-01.yang` revision
|
||||
* Added ignore-compare extension
|
||||
* Added creator meta configuration
|
||||
|
||||
### Corrected Bugs
|
||||
|
||||
|
|
|
|||
|
|
@ -798,7 +798,7 @@ get_list_pagination(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
cprintf(cba, "%u", remaining);
|
||||
if (xml_add_attr(x1, "remaining", cbuf_get(cba), "cp", "http://clicon.org/clixon-netconf-list-pagination") < 0)
|
||||
if (xml_add_attr(x1, "remaining", cbuf_get(cba), "cp", "http://clicon.org/clixon-netconf-list-pagination") == NULL)
|
||||
goto done;
|
||||
if (cba)
|
||||
cbuf_free(cba);
|
||||
|
|
|
|||
|
|
@ -473,7 +473,7 @@ cli_dbxml(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
}
|
||||
if (xml_add_attr(xbot, "operation", xml_operation2str(op), NETCONF_BASE_PREFIX, NULL) < 0)
|
||||
if (xml_add_attr(xbot, "operation", xml_operation2str(op), NETCONF_BASE_PREFIX, NULL) == NULL)
|
||||
goto done;
|
||||
/* Add body last in case of leaf */
|
||||
if (cvec_len(cvv) > 1 &&
|
||||
|
|
|
|||
|
|
@ -712,7 +712,7 @@ netconf_rpc_dispatch(clicon_handle h,
|
|||
* It may even be wrong if something else is done with the incoming message?
|
||||
*/
|
||||
if ((username = clicon_username_get(h)) != NULL){
|
||||
if (xml_add_attr(xn, "username", username, CLIXON_LIB_PREFIX, CLIXON_LIB_NS) < 0)
|
||||
if (xml_add_attr(xn, "username", username, CLIXON_LIB_PREFIX, CLIXON_LIB_NS) == NULL)
|
||||
goto done;
|
||||
}
|
||||
/* Many of these calls are now calling generic clicon_rpc_netconf_xml
|
||||
|
|
|
|||
|
|
@ -427,7 +427,7 @@ restconf_insert_attributes(cxobj *xdata,
|
|||
/* First add xmlns:yang attribute */
|
||||
if (xmlns_set(xdata, "yang", YANG_XML_NAMESPACE) < 0)
|
||||
goto done;
|
||||
if (xml_add_attr(xdata, "insert", instr, "yang", NULL) < 0)
|
||||
if (xml_add_attr(xdata, "insert", instr, "yang", NULL) == NULL)
|
||||
goto done;
|
||||
}
|
||||
if ((pstr = cvec_find_str(qvec, "point")) != NULL){
|
||||
|
|
@ -467,7 +467,7 @@ restconf_insert_attributes(cxobj *xdata,
|
|||
p++;
|
||||
cprintf(cb, "%s", p);
|
||||
}
|
||||
if (xml_add_attr(xdata, attrname, cbuf_get(cb), "yang", NULL) < 0)
|
||||
if (xml_add_attr(xdata, attrname, cbuf_get(cb), "yang", NULL) == NULL)
|
||||
goto done;
|
||||
}
|
||||
/* Add prefix/namespaces used in attributes */
|
||||
|
|
|
|||
|
|
@ -390,11 +390,11 @@ api_data_write(clicon_handle h,
|
|||
/* Add operation create as attribute. If that fails with Conflict, then
|
||||
* try "replace" (see comment in function header)
|
||||
*/
|
||||
if (xml_add_attr(xdata, "operation", xml_operation2str(op), NETCONF_BASE_PREFIX, NULL) < 0)
|
||||
if (xml_add_attr(xdata, "operation", xml_operation2str(op), NETCONF_BASE_PREFIX, NULL) == NULL)
|
||||
goto done;
|
||||
if (xml_add_attr(xdata, "objectcreate",
|
||||
plain_patch?"false":"true",
|
||||
CLIXON_LIB_PREFIX, CLIXON_LIB_NS) < 0)
|
||||
CLIXON_LIB_PREFIX, CLIXON_LIB_NS) == NULL)
|
||||
goto done;
|
||||
/* Top-of tree, no api-path
|
||||
* Replace xparent with x, ie bottom of api-path with data
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@ int xml_creator_add(cxobj *xn, char *name);
|
|||
int xml_creator_rm(cxobj *xn, char *name);
|
||||
int xml_creator_find(cxobj *xn, char *name);
|
||||
size_t xml_creator_len(cxobj *xn);
|
||||
cvec *xml_creator_get(cxobj *xn);
|
||||
int xml_creator_copy_one(cxobj *x0, cxobj *x1);
|
||||
int xml_creator_copy_all(cxobj *x0, cxobj *x1);
|
||||
int xml_creator_print(FILE *f, cxobj *xn);
|
||||
|
|
@ -304,7 +305,7 @@ cxobj *xml_root(cxobj *xn);
|
|||
int xml_operation(char *opstr, enum operation_type *op);
|
||||
char *xml_operation2str(enum operation_type op);
|
||||
int xml_attr_insert2val(char *instr, enum insert_type *ins);
|
||||
int xml_add_attr(cxobj *xn, char *name, char *value, char *prefix, char *ns);
|
||||
cxobj *xml_add_attr(cxobj *xn, char *name, char *value, char *prefix, char *ns);
|
||||
int clicon_log_xml(int level, cxobj *x, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
int clixon_debug_xml(int dbglevel, cxobj *x, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
|
||||
|
|
|
|||
|
|
@ -442,6 +442,56 @@ disable_nacm_on_empty(cxobj *xt,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Read creator data from meta-data and add to xml internal annotation
|
||||
*
|
||||
* Iterate creator meta-data using xpaths and create internal creator annotations
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] xt XML top node
|
||||
* @param[in] xn XML creators node
|
||||
* On the form:
|
||||
* <creator>
|
||||
* <name>testA[name='foo']</name>
|
||||
* <xpath>...</xpath>
|
||||
* ...
|
||||
* </creator>
|
||||
* @see xml_creator_metadata_write
|
||||
*/
|
||||
static int
|
||||
xml_creator_metadata_read(clicon_handle h,
|
||||
cxobj *xn)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xt;
|
||||
cxobj *xc;
|
||||
cxobj *xp;
|
||||
cxobj *x;
|
||||
char *name;
|
||||
char *xpath;
|
||||
|
||||
xt = xml_root(xn);
|
||||
xc = NULL;
|
||||
while ((xc = xml_child_each(xn, xc, CX_ELMNT)) != NULL) {
|
||||
if (strcmp(xml_name(xc), "creator"))
|
||||
continue;
|
||||
if ((name = xml_find_body(xc, "name")) == NULL)
|
||||
continue;
|
||||
xp = NULL;
|
||||
while ((xp = xml_child_each(xc, xp, CX_ELMNT)) != NULL) {
|
||||
if (strcmp(xml_name(xp), "path"))
|
||||
continue;
|
||||
if ((xpath = xml_body(xp)) == NULL)
|
||||
continue;
|
||||
if ((x = xpath_first(xt, NULL, "%s", xpath)) == NULL)
|
||||
continue;
|
||||
if (xml_creator_add(x, name) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Common read function that reads an XML tree from file
|
||||
*
|
||||
* @param[in] th Datastore text handle
|
||||
|
|
@ -543,7 +593,19 @@ xmldb_readfile(clicon_handle h,
|
|||
xml_flag_set(x0, XML_FLAG_TOP);
|
||||
if (xml_child_nr(x0) == 0 && de)
|
||||
de->de_empty = 1;
|
||||
|
||||
/* Check if creator attributes are supported*/
|
||||
if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR")){
|
||||
if ((x = xpath_first(x0, NULL, "creators")) != NULL){
|
||||
ns = NULL;
|
||||
if (xml2ns(x, NULL, &ns) < 0)
|
||||
goto done;
|
||||
if (strcmp(ns, CLIXON_LIB_NS) == 0){
|
||||
if (xml_creator_metadata_read(h, x) < 0)
|
||||
goto done;
|
||||
xml_purge(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check if we support modstate */
|
||||
if (clicon_option_bool(h, "CLICON_XMLDB_MODSTATE"))
|
||||
if ((msdiff = modstate_diff_new()) == NULL)
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@
|
|||
* An attribute may have a prefix(or NULL). The routine finds the associated
|
||||
* xmlns binding to find the namespace: <namespace>:<name>.
|
||||
* If such an attribute is not found, failure is returned with cbret set,
|
||||
* If such an attribute its found, its string value is returned.
|
||||
* If such an attribute is found, its string value is returned and removed from XML
|
||||
* @param[in] x XML node (where to look for attribute)
|
||||
* @param[in] name Attribute name
|
||||
* @param[in] ns (Expected) Namespace of attribute
|
||||
|
|
@ -98,6 +98,7 @@
|
|||
* @retval 1 OK
|
||||
* @retval 0 Failed (cbret set)
|
||||
* @retval -1 Error
|
||||
* @note as a side.effect the attribute is removed
|
||||
*/
|
||||
static int
|
||||
attr_ns_value(cxobj *x,
|
||||
|
|
@ -142,6 +143,70 @@ attr_ns_value(cxobj *x,
|
|||
goto done;
|
||||
}
|
||||
|
||||
/*! Add creator data to metadata xml object on the form name:xpath*
|
||||
*
|
||||
* Callback function type for xml_apply
|
||||
* @param[in] x XML node
|
||||
* @param[in] arg General-purpose argument
|
||||
* @retval -1 Error, aborted at first error encounter, return -1 to end user
|
||||
* @retval 0 OK, continue
|
||||
* @retval 1 Abort, dont continue with others, return 1 to end user
|
||||
* @retval 2 Locally abort this subtree, continue with others
|
||||
* On the form:
|
||||
* <creator>
|
||||
* <name>testA[name='foo']</name>
|
||||
* <xpath>...</xpath>
|
||||
* ...
|
||||
* </creator>
|
||||
* @see xml_creator_metadata_read
|
||||
*/
|
||||
static int
|
||||
xml_creator_metadata_write(cxobj *x,
|
||||
void *arg)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xmeta = (cxobj*)arg;
|
||||
cxobj *xmc;
|
||||
cvec *cvv;
|
||||
cg_var *cv;
|
||||
char *val;
|
||||
cvec *nsc = NULL;
|
||||
char *xpath = NULL;
|
||||
|
||||
if ((cvv = xml_creator_get(x)) == NULL){
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
/* Note this requires x to have YANG spec */
|
||||
if (xml2xpath(x, nsc, 0, 0, &xpath) < 0)
|
||||
goto done;
|
||||
cv = NULL;
|
||||
while ((cv = cvec_each(cvv, cv)) != NULL){
|
||||
val = cv_name_get(cv);
|
||||
/* Find existing entry where name is val */
|
||||
xmc = NULL;
|
||||
while ((xmc = xml_child_each(xmeta, xmc, CX_ELMNT)) != NULL){
|
||||
if (strcmp(xml_find_body(xmc, "name"), val) == 0)
|
||||
break;
|
||||
}
|
||||
if (xmc != NULL){
|
||||
if (clixon_xml_parse_va(YB_NONE, NULL, &xmc, NULL, "<path>%s</path>", xpath) < 0)
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
if (clixon_xml_parse_va(YB_NONE, NULL, &xmeta, NULL,
|
||||
"<creator><name>%s</name><path>%s</path></creator>",
|
||||
val, xpath) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
retval = 2;
|
||||
done:
|
||||
if (xpath)
|
||||
free(xpath);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! When new body is added, some needs type lookup is made and namespace checked
|
||||
*
|
||||
* This includes identityrefs, paths
|
||||
|
|
@ -209,11 +274,11 @@ check_body_namespace(cxobj *x0,
|
|||
goto done;
|
||||
/* Create xmlns attribute to x0 XXX same code ^*/
|
||||
if (prefix){
|
||||
if (xml_add_attr(x, prefix, ns0, "xmlns", NULL) < 0)
|
||||
if (xml_add_attr(x, prefix, ns0, "xmlns", NULL) == NULL)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
if (xml_add_attr(x, "xmlns", ns0, NULL, NULL) < 0)
|
||||
if (xml_add_attr(x, "xmlns", ns0, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
xml_sort(x); /* Ensure attr is first / XXX xml_insert? */
|
||||
}
|
||||
|
|
@ -231,7 +296,7 @@ check_body_namespace(cxobj *x0,
|
|||
;
|
||||
}
|
||||
else{ /* Add it according to the kludge,... */
|
||||
if (xml_add_attr(x0, prefix, ns0, "xmlns", NULL) < 0)
|
||||
if (xml_add_attr(x0, prefix, ns0, "xmlns", NULL) == NULL)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
|
@ -513,7 +578,6 @@ text_modify(clicon_handle h,
|
|||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
|
||||
if (createstr != NULL &&
|
||||
(op == OP_REPLACE || op == OP_MERGE || op == OP_CREATE)){
|
||||
if (x0 == NULL || xml_defaults_nopresence(x0, 0)){ /* does not exist or is default */
|
||||
|
|
@ -532,11 +596,13 @@ text_modify(clicon_handle h,
|
|||
clicon_data_set(h, "objectexisted", "true");
|
||||
}
|
||||
}
|
||||
/* Special clixon-lib attribute for keeping track of creator of objects */
|
||||
if ((ret = attr_ns_value(x1, "creator", CLIXON_LIB_NS, cbret, &creator)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR")){
|
||||
/* Special clixon-lib attribute for keeping track of creator of objects */
|
||||
if ((ret = attr_ns_value(x1, "creator", CLIXON_LIB_NS, cbret, &creator)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
}
|
||||
x1name = xml_name(x1);
|
||||
|
||||
if (yang_keyword_get(y0) == Y_LEAF_LIST ||
|
||||
|
|
@ -798,12 +864,13 @@ text_modify(clicon_handle h,
|
|||
}
|
||||
/* XXX: Note, if there is an error in adding the object later, the
|
||||
* original object is not reverted.
|
||||
* XXX: Here creator attributes in x0 are destroyed
|
||||
*/
|
||||
if (x0){
|
||||
/* Recursively copy creator attributes from existing tree */
|
||||
if (xml_creator_copy_all(x0, x1) < 0)
|
||||
goto done;
|
||||
if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR")){
|
||||
/* Recursively copy creator attributes from existing tree */
|
||||
if (xml_creator_copy_all(x0, x1) < 0)
|
||||
goto done;
|
||||
}
|
||||
xml_purge(x0);
|
||||
x0 = NULL;
|
||||
}
|
||||
|
|
@ -854,8 +921,10 @@ text_modify(clicon_handle h,
|
|||
#ifdef XML_PARENT_CANDIDATE
|
||||
xml_parent_candidate_set(x0, x0p);
|
||||
#endif
|
||||
if (xml_creator_copy_one(x1, x0) < 0)
|
||||
goto done;
|
||||
if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR")){
|
||||
if (xml_creator_copy_one(x1, x0) < 0)
|
||||
goto done;
|
||||
}
|
||||
changed++;
|
||||
/* Get namespace from x1
|
||||
* Check if namespace exists in x0 parent
|
||||
|
|
@ -1229,6 +1298,7 @@ xmldb_put(clicon_handle h,
|
|||
int firsttime = 0;
|
||||
int pretty;
|
||||
cxobj *xerr = NULL;
|
||||
cxobj *xmeta = NULL;
|
||||
|
||||
if (cbret == NULL){
|
||||
clicon_err(OE_XML, EINVAL, "cbret is NULL");
|
||||
|
|
@ -1262,6 +1332,16 @@ xmldb_put(clicon_handle h,
|
|||
xml_name(x0), DATASTORE_TOP_SYMBOL);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* XXX Ad-hoc:
|
||||
* In yang mounts yang specs may not be available
|
||||
* in initial parsing, but may be at a later stage.
|
||||
* But it should be possible to find a more precise triggering
|
||||
*/
|
||||
if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){
|
||||
if ((ret = xml_bind_yang(h, x0, YB_MODULE, yspec, NULL)) < 0)
|
||||
goto done;
|
||||
}
|
||||
/* Here x0 looks like: <config>...</config> */
|
||||
#if 0 /* debug */
|
||||
if (xml_apply0(x1, -1, xml_sort_verify, NULL) < 0)
|
||||
|
|
@ -1301,7 +1381,6 @@ xmldb_put(clicon_handle h,
|
|||
if (xml_apply0(x0, -1, xml_sort_verify, NULL) < 0)
|
||||
clicon_log(LOG_NOTICE, "%s: verify failed #3", __FUNCTION__);
|
||||
#endif
|
||||
|
||||
/* Write back to datastore cache if first time */
|
||||
if (clicon_datastore_cache(h) != DATASTORE_NOCACHE){
|
||||
db_elmnt de0 = {0,};
|
||||
|
|
@ -1336,6 +1415,19 @@ xmldb_put(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
pretty = clicon_option_bool(h, "CLICON_XMLDB_PRETTY");
|
||||
/* Add creator attribute */
|
||||
if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR")){
|
||||
if ((xmeta = xml_new("creators", x0, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
if (xmlns_set(xmeta, NULL, CLIXON_LIB_NS) < 0)
|
||||
goto done;
|
||||
if (xml_apply(x0, CX_ELMNT, xml_creator_metadata_write, xmeta) < 0)
|
||||
goto done;
|
||||
if (xml_child_nr_type(xmeta, CX_ELMNT) == 0){
|
||||
xml_purge(xmeta);
|
||||
xmeta = NULL;
|
||||
}
|
||||
}
|
||||
if (strcmp(format,"json")==0){
|
||||
if (clixon_json2file(f, x0, pretty, fprintf, 0, 0) < 0)
|
||||
goto done;
|
||||
|
|
@ -1346,6 +1438,10 @@ xmldb_put(clicon_handle h,
|
|||
*/
|
||||
if (xmodst && xml_purge(xmodst) < 0)
|
||||
goto done;
|
||||
if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR") && xmeta){
|
||||
if (xml_purge(xmeta) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 1;
|
||||
done:
|
||||
if (f != NULL)
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ json2xml_decode_identityref(cxobj *x,
|
|||
if (prefix2 == NULL)
|
||||
prefix2 = yang_find_myprefix(ymod);
|
||||
/* Add "xmlns:prefix2=namespace" */
|
||||
if (xml_add_attr(x, prefix2, ns, "xmlns", NULL) < 0)
|
||||
if (xml_add_attr(x, prefix2, ns, "xmlns", NULL) == NULL)
|
||||
goto done;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ netconf_invalid_value_xml(cxobj **xret,
|
|||
}
|
||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||
goto done;
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
|
|
@ -302,7 +302,7 @@ netconf_missing_attribute_xml(cxobj **xret,
|
|||
}
|
||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||
goto done;
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
|
|
@ -418,7 +418,7 @@ netconf_bad_attribute_xml(cxobj **xret,
|
|||
}
|
||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||
goto done;
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
|
|
@ -514,7 +514,7 @@ netconf_common_xml(cxobj **xret,
|
|||
if (*xret == NULL){
|
||||
if ((*xret = xml_new("rpc-reply", NULL, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
}
|
||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||
|
|
@ -789,7 +789,7 @@ netconf_access_denied_xml(cxobj **xret,
|
|||
}
|
||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||
goto done;
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
|
|
@ -1034,7 +1034,7 @@ netconf_data_missing_xml(cxobj **xret,
|
|||
}
|
||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||
goto done;
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
|
|
@ -1093,7 +1093,7 @@ netconf_missing_choice_xml(cxobj **xret,
|
|||
}
|
||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||
goto done;
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
|
|
@ -1167,7 +1167,7 @@ netconf_operation_not_supported_xml(cxobj **xret,
|
|||
}
|
||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||
goto done;
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
|
|
@ -1285,7 +1285,7 @@ netconf_operation_failed_xml(cxobj **xret,
|
|||
}
|
||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||
goto done;
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
|
|
@ -1374,7 +1374,7 @@ netconf_malformed_message_xml(cxobj **xret,
|
|||
}
|
||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||
goto done;
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
|
|
@ -1460,7 +1460,7 @@ netconf_data_not_unique_xml(cxobj **xret,
|
|||
}
|
||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||
goto done;
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
|
|
@ -1531,7 +1531,7 @@ netconf_minmax_elements_xml(cxobj **xret,
|
|||
}
|
||||
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||
goto done;
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) < 0)
|
||||
if (xml_add_attr(*xret, "xmlns", NETCONF_BASE_NAMESPACE, NULL, NULL) == NULL)
|
||||
goto done;
|
||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -185,7 +185,8 @@ struct xml{
|
|||
yang_stmt *x_spec; /* Pointer to specification, eg yang,
|
||||
by reference, dont free */
|
||||
cg_var *x_cv; /* Cached value as cligen variable (set by xml_cmp) */
|
||||
cvec *x_creators; /* Support clixon-lib creator annotation */
|
||||
cvec *x_creators; /* Support clixon-lib creator annotation.
|
||||
Only if CLICON_NETCONF_CREATOR_ATTR = true */
|
||||
#ifdef XML_EXPLICIT_INDEX
|
||||
struct search_index *x_search_index; /* explicit search index vectors */
|
||||
#endif
|
||||
|
|
@ -653,7 +654,7 @@ xml_creator_add(cxobj *xn,
|
|||
cg_var *cv;
|
||||
|
||||
if (!is_element(xn))
|
||||
return 0;
|
||||
goto ok;
|
||||
if (xn->x_creators == NULL){
|
||||
if ((xn->x_creators = cvec_new(0)) == NULL){
|
||||
clicon_err(OE_XML, errno, "cvec_new");
|
||||
|
|
@ -662,6 +663,7 @@ xml_creator_add(cxobj *xn,
|
|||
}
|
||||
if ((cv = cvec_find(xn->x_creators, name)) == NULL)
|
||||
cvec_add_string(xn->x_creators, name, NULL);
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
|
|
@ -723,6 +725,16 @@ xml_creator_len(cxobj *xn)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Get all creator attributes
|
||||
*/
|
||||
cvec*
|
||||
xml_creator_get(cxobj *xn)
|
||||
{
|
||||
if (!is_element(xn))
|
||||
return 0;
|
||||
return xn->x_creators;
|
||||
}
|
||||
|
||||
/*! Copy creator info from x0 to x1 single object
|
||||
*
|
||||
* @param[in] x0 Source XML node
|
||||
|
|
@ -830,7 +842,7 @@ creator_print_fn(cxobj *x,
|
|||
return 2; /* Locally abort this subtree, continue with others */
|
||||
}
|
||||
|
||||
/*! Print XML and creator tags where they exists, for debugging
|
||||
/*! Print XML and creator tags where they exists recursively, for debugging
|
||||
*
|
||||
* @param[in] xn XML tree
|
||||
* @retval see xml_apply
|
||||
|
|
@ -1355,7 +1367,7 @@ clixon_child_xvec_append(cxobj *xn,
|
|||
* xml_free(x);
|
||||
* @endcode
|
||||
* @note Differentiates between body/attribute vs element to reduce mem allocation
|
||||
* @see xml_sort_insert
|
||||
* @see xml_insert
|
||||
*/
|
||||
cxobj *
|
||||
xml_new(char *name,
|
||||
|
|
@ -2021,10 +2033,10 @@ xml_find_type_value(cxobj *xt,
|
|||
* @see xml_find_value where a body can be found as well
|
||||
*/
|
||||
cxobj *
|
||||
xml_find_type(cxobj *xt,
|
||||
const char *prefix,
|
||||
const char *name,
|
||||
enum cxobj_type type)
|
||||
xml_find_type(cxobj *xt,
|
||||
const char *prefix,
|
||||
const char *name,
|
||||
enum cxobj_type type)
|
||||
{
|
||||
cxobj *x = NULL;
|
||||
int pmatch; /* prefix match */
|
||||
|
|
@ -2649,18 +2661,17 @@ xml_attr_insert2val(char *instr,
|
|||
* @param[in] value Attribute value
|
||||
* @param[in] prefix Attribute prefix, or NULL
|
||||
* @param[in] namespace Attribute prefix, if NULL do not add namespace mapping
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* @retval xa Created attribute object
|
||||
* @retval NULL Error
|
||||
*/
|
||||
int
|
||||
cxobj *
|
||||
xml_add_attr(cxobj *xn,
|
||||
char *name,
|
||||
char *value,
|
||||
char *prefix,
|
||||
char *namespace)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xa;
|
||||
cxobj *xa = NULL;
|
||||
char *ns = NULL;
|
||||
|
||||
if ((xa = xml_new(name, xn, CX_ATTR)) == NULL)
|
||||
|
|
@ -2675,9 +2686,16 @@ xml_add_attr(cxobj *xn,
|
|||
if (ns == NULL && xmlns_set(xn, prefix, namespace) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
if (xml_sort(xn) < 0)
|
||||
goto done;
|
||||
ret:
|
||||
return xa;
|
||||
done:
|
||||
return retval;
|
||||
if (xa){
|
||||
xml_free(xa);
|
||||
xa = NULL;
|
||||
}
|
||||
goto ret;
|
||||
}
|
||||
|
||||
/*! Specialization of clicon_log with xml tree
|
||||
|
|
|
|||
|
|
@ -227,8 +227,13 @@ populate_self_parent(cxobj *xt,
|
|||
}
|
||||
/* Assign spec only if namespaces match */
|
||||
if (strcmp(ns, nsy) != 0){
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cb, "Namespace mismatch: %s in XML does not match %s in yang", ns, nsy);
|
||||
if (xerr &&
|
||||
netconf_bad_element_xml(xerr, "application", name, "Namespace mismatch") < 0)
|
||||
netconf_bad_element_xml(xerr, "application", name, cbuf_get(cb)) < 0)
|
||||
goto done;
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -615,7 +615,7 @@ xml_add_default_tag(cxobj *x,
|
|||
|
||||
if (xml_flag(x, flags)) {
|
||||
/* set default attribute */
|
||||
if (xml_add_attr(x, "default", "true", IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, NULL) < 0)
|
||||
if (xml_add_attr(x, "default", "true", IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, NULL) == NULL)
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
|
|
|
|||
|
|
@ -358,12 +358,14 @@ xml_parse_attr(clixon_xml_yacc *xy,
|
|||
int retval = -1;
|
||||
cxobj *xa = NULL;
|
||||
|
||||
/* XXX: here duplicates of same attributes are removed
|
||||
* This is probably not according standard?
|
||||
*/
|
||||
if ((xa = xml_find_type(xy->xy_xelement, prefix, name, CX_ATTR)) == NULL){
|
||||
if ((xa = xml_new(name, xy->xy_xelement, CX_ATTR)) == NULL)
|
||||
goto done;
|
||||
if (xml_prefix_set(xa, prefix) < 0)
|
||||
goto done;
|
||||
|
||||
}
|
||||
if (xml_value_set(xa, attval) < 0)
|
||||
goto done;
|
||||
|
|
@ -484,12 +486,14 @@ pi : BQMARK NAME EQMARK {_PARSE_DEBUG("pi -> <? NAME ?>"); free($2); }
|
|||
;
|
||||
|
||||
|
||||
attrs : attrs attr
|
||||
|
|
||||
attrs : attrs attr { _PARSE_DEBUG("attrs -> attrs attr"); }
|
||||
| { _PARSE_DEBUG("attrs ->"); }
|
||||
;
|
||||
|
||||
attr : NAME '=' attvalue { if (xml_parse_attr(_XY, NULL, $1, $3) < 0) YYABORT; }
|
||||
| NAME ':' NAME '=' attvalue { if (xml_parse_attr(_XY, $1, $3, $5) < 0) YYABORT; }
|
||||
attr : NAME '=' attvalue { if (xml_parse_attr(_XY, NULL, $1, $3) < 0) YYABORT;
|
||||
_PARSE_DEBUG("attr -> NAME = attvalue"); }
|
||||
| NAME ':' NAME '=' attvalue { if (xml_parse_attr(_XY, $1, $3, $5) < 0) YYABORT;
|
||||
_PARSE_DEBUG("attr -> NAME : NAME = attvalue"); }
|
||||
;
|
||||
|
||||
attvalue : '\"' STRING '\"' { $$=$2; /* $2 must be consumed */}
|
||||
|
|
|
|||
|
|
@ -1057,7 +1057,7 @@ xml_insert2(cxobj *xp,
|
|||
/*! Insert xc as child to xp in sorted place. Remove xc from previous parent.
|
||||
*
|
||||
* @param[in] xp Parent xml node. If NULL just remove from old parent.
|
||||
* @param[in] x Child xml node to insert under xp
|
||||
* @param[in] xi Child xml node to insert under xp
|
||||
* @param[in] ins Insert operation (if ordered-by user)
|
||||
* @param[in] key_val Key if x is LIST and ins is before/after, val if LEAF_LIST
|
||||
* @param[in] nsc_key Network namespace for key
|
||||
|
|
|
|||
139
test/test_datastore_creator.sh
Executable file
139
test/test_datastore_creator.sh
Executable file
|
|
@ -0,0 +1,139 @@
|
|||
#!/usr/bin/env bash
|
||||
# test for data creator attribute: add same object from sessions s1 and s2
|
||||
# Restart and ensure attributes remain
|
||||
|
||||
# Magic line must be first in script (see README.md)
|
||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||
|
||||
cfg=$dir/conf.xml
|
||||
fyang=$dir/clixon-example.yang
|
||||
|
||||
: ${clixon_util_xpath:=clixon_util_xpath}
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>${YANG_INSTALLDIR}</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MAIN_FILE>$fyang</CLICON_YANG_MAIN_FILE>
|
||||
<CLICON_CLISPEC_DIR>$clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||
<CLICON_CLI_MODE>example</CLICON_CLI_MODE>
|
||||
<CLICON_SOCK>/usr/local/var/run/$APPNAME.sock</CLICON_SOCK>
|
||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/run/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
|
||||
<CLICON_NETCONF_CREATOR_ATTR>true</CLICON_NETCONF_CREATOR_ATTR>
|
||||
</clixon-config>
|
||||
EOF
|
||||
|
||||
cat <<EOF > $fyang
|
||||
module clixon-example{
|
||||
yang-version 1.1;
|
||||
namespace "urn:example:clixon";
|
||||
prefix ex;
|
||||
|
||||
container table {
|
||||
list parameter{
|
||||
key name;
|
||||
leaf name{
|
||||
type string;
|
||||
}
|
||||
leaf value{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
new "test params: -f $cfg"
|
||||
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "kill old backend"
|
||||
sudo clixon_backend -zf $cfg
|
||||
if [ $? -ne 0 ]; then
|
||||
err
|
||||
fi
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
fi
|
||||
|
||||
new "wait backend 1"
|
||||
wait_backend
|
||||
|
||||
conf="-d candidate -b $dir -y $fyang"
|
||||
|
||||
new "s1 add x"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><default-operation>none</default-operation><target><candidate/></target><config><table xmlns=\"urn:example:clixon\"><parameter nc:operation=\"create\" xmlns:nc=\"${BASENS}\" cl:creator=\"s1\" xmlns:cl=\"http://clicon.org/lib\"><name>x</name><value>foo</value></parameter></table></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "datastore get"
|
||||
expectpart "$(sudo $clixon_util_xpath -f $dir/candidate_db -p /config/creators)" 0 "<creators xmlns=\"http://clicon.org/lib\"><creator><name>s1</name><path>/table/parameter\[name=\"x\"\]</path></creator></creators>"
|
||||
|
||||
new "rpc get-config"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><get-config><source><candidate/></source></get-config></rpc>" "<table xmlns=\"urn:example:clixon\"><parameter><name>x</name><value>foo</value></parameter></table>" ""
|
||||
|
||||
# duplicate
|
||||
new "s1 merge x"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><default-operation>none</default-operation><target><candidate/></target><config><table xmlns=\"urn:example:clixon\"><parameter nc:operation=\"merge\" xmlns:nc=\"${BASENS}\" cl:creator=\"s1\" xmlns:cl=\"http://clicon.org/lib\"><name>x</name><value>foo</value></parameter></table></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "datastore get"
|
||||
expectpart "$(sudo $clixon_util_xpath -f $dir/candidate_db -p /config/creators)" 0 "<creators xmlns=\"http://clicon.org/lib\"><creator><name>s1</name><path>/table/parameter\[name=\"x\"\]</path></creator></creators>"
|
||||
|
||||
# New service
|
||||
new "s2 merge x"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><default-operation>none</default-operation><target><candidate/></target><config><table xmlns=\"urn:example:clixon\"><parameter nc:operation=\"merge\" xmlns:nc=\"${BASENS}\" cl:creator=\"s2\" xmlns:cl=\"http://clicon.org/lib\"><name>x</name><value>foo</value></parameter></table></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "datastore get"
|
||||
expectpart "$(sudo $clixon_util_xpath -f $dir/candidate_db -p /config/creators)" 0 "<creators xmlns=\"http://clicon.org/lib\"><creator><name>s1</name><path>/table/parameter\[name=\"x\"\]</path></creator><creator><name>s2</name><path>/table/parameter\[name=\"x\"\]</path></creator></creators>"
|
||||
|
||||
# New entry
|
||||
new "s1 create y=bar"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><default-operation>none</default-operation><target><candidate/></target><config><table xmlns=\"urn:example:clixon\"><parameter nc:operation=\"create\" xmlns:nc=\"${BASENS}\" cl:creator=\"s1\" xmlns:cl=\"http://clicon.org/lib\"><name>y</name><value>bar</value></parameter></table></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "datastore get"
|
||||
expectpart "$(sudo $clixon_util_xpath -f $dir/candidate_db -p /config/creators)" 0 "<creators xmlns=\"http://clicon.org/lib\"><creator><name>s1</name><path>/table/parameter\[name=\"x\"\]</path><path>/table/parameter\[name=\"y\"\]</path></creator><creator><name>s2</name><path>/table/parameter\[name=\"x\"\]</path></creator></creators>"
|
||||
|
||||
# To running
|
||||
new "commit to running"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><commit/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "datastore get running"
|
||||
expectpart "$(sudo $clixon_util_xpath -f $dir/running_db -p /config/creators)" 0 "<creators xmlns=\"http://clicon.org/lib\"><creator><name>s1</name><path>/table/parameter\[name=\"x\"\]</path><path>/table/parameter\[name=\"y\"\]</path></creator><creator><name>s2</name><path>/table/parameter\[name=\"x\"\]</path></creator></creators>"
|
||||
|
||||
new "rpc get-config"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><get-config><source><running/></source></get-config></rpc>" "<table xmlns=\"urn:example:clixon\"><parameter><name>x</name><value>foo</value></parameter><parameter><name>y</name><value>bar</value></parameter></table>" ""
|
||||
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "kill old backend"
|
||||
sudo clixon_backend -zf $cfg
|
||||
if [ $? -ne 0 ]; then
|
||||
err
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "start backend -s running -f $cfg"
|
||||
start_backend -s running -f $cfg
|
||||
fi
|
||||
|
||||
new "wait backend 2"
|
||||
wait_backend
|
||||
|
||||
new "datastore get running"
|
||||
expectpart "$(sudo $clixon_util_xpath -f $dir/running_db -p /config/creators)" 0 "<creators xmlns=\"http://clicon.org/lib\"><creator><name>s1</name><path>/table/parameter\[name=\"x\"\]</path><path>/table/parameter\[name=\"y\"\]</path></creator><creator><name>s2</name><path>/table/parameter\[name=\"x\"\]</path></creator></creators>"
|
||||
|
||||
new "rpc get-config"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><get-config><source><running/></source></get-config></rpc>" "<table xmlns=\"urn:example:clixon\"><parameter><name>x</name><value>foo</value></parameter><parameter><name>y</name><value>bar</value></parameter></table>" ""
|
||||
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "kill old backend"
|
||||
sudo clixon_backend -zf $cfg
|
||||
if [ $? -ne 0 ]; then
|
||||
err
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -rf $dir
|
||||
|
||||
new "endtest"
|
||||
endtest
|
||||
|
|
@ -42,7 +42,7 @@ datarootdir = @datarootdir@
|
|||
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
||||
|
||||
# Note: mirror these to test/config.sh.in
|
||||
YANGSPECS = clixon-config@2023-05-01.yang # 6.3
|
||||
YANGSPECS = clixon-config@2023-11-01.yang # 6.5
|
||||
YANGSPECS += clixon-lib@2023-11-01.yang # 6.5
|
||||
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
||||
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ module clixon-config {
|
|||
}
|
||||
import clixon-autocli {
|
||||
prefix autocli;
|
||||
}
|
||||
}
|
||||
import clixon-lib {
|
||||
prefix cl;
|
||||
}
|
||||
organization
|
||||
"Clicon / Clixon";
|
||||
|
||||
|
|
@ -46,6 +49,20 @@ module clixon-config {
|
|||
|
||||
***** END LICENSE BLOCK *****";
|
||||
|
||||
revision 2023-11-01 {
|
||||
description
|
||||
"Added options:
|
||||
CLICON_CREATOR_ATTR
|
||||
Released in Clixon 6.5";
|
||||
}
|
||||
revision 2023-05-01 {
|
||||
description
|
||||
"Added options:
|
||||
CLICON_CONFIG_EXTEND
|
||||
CLICON_PLUGIN_DLOPEN_GLOBAL
|
||||
Moved datastore-format datatype to clixon-lib
|
||||
Released in Clixon 6.3";
|
||||
}
|
||||
revision 2023-03-01 {
|
||||
description
|
||||
"Added options:
|
||||
|
|
@ -225,7 +242,7 @@ module clixon-config {
|
|||
Renamed CLICON_XMLDB_CACHE to CLICON_DATASTORE_CACHE (changed type)
|
||||
Deleted: CLICON_XMLDB_PLUGIN, CLICON_USE_STARTUP_CONFIG";
|
||||
}
|
||||
revision 2019-03-05{
|
||||
revision 2019-03-05{
|
||||
description
|
||||
"Changed URN. Changed top-level symbol to clixon-config.
|
||||
Released in Clixon 3.10";
|
||||
|
|
@ -274,27 +291,6 @@ module clixon-config {
|
|||
}
|
||||
}
|
||||
}
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
||||
typedef datastore_cache{
|
||||
description
|
||||
"XML configuration, ie running/candididate/ datastore cache behaviour.";
|
||||
|
|
@ -461,6 +457,15 @@ module clixon-config {
|
|||
You can override file setting with -E <dir> command-line option.
|
||||
Note that due to bootstraping this value is only meaningful in the main config file";
|
||||
}
|
||||
leaf CLICON_CONFIG_EXTEND {
|
||||
type string;
|
||||
description
|
||||
"If specified load an application-specific configuration YANG that overrides
|
||||
this config.
|
||||
Normally, that YANG imports clixon-config.
|
||||
This field is a 'bootstrap' field.
|
||||
";
|
||||
}
|
||||
leaf CLICON_YANG_MAIN_FILE {
|
||||
type string;
|
||||
description
|
||||
|
|
@ -520,7 +525,13 @@ module clixon-config {
|
|||
leaf CLICON_YANG_SCHEMA_MOUNT{
|
||||
type boolean;
|
||||
description
|
||||
"YANG schema mount, RFC 8528";
|
||||
"YANG schema mount, RFC 8528.
|
||||
When enabled, mount-points as defined by the 'yangmnt:mount-point' extension can
|
||||
be populated by other YANGs than the root.
|
||||
This is controlled by the ca_yang_mount plugin callback by returning a assigning a
|
||||
yanglib module-set section that corresponds to the mounted YANGs.
|
||||
Also, schema mount statistics is added to state data
|
||||
Further, autocli syntax is added by definining a tree resolve wrapper";
|
||||
default false;
|
||||
}
|
||||
leaf CLICON_BACKEND_REGEXP {
|
||||
|
|
@ -571,6 +582,18 @@ module clixon-config {
|
|||
RFC6242 for example.
|
||||
This only applies to the external NETCONF";
|
||||
}
|
||||
leaf CLICON_NETCONF_CREATOR_ATTR {
|
||||
type boolean;
|
||||
default false;
|
||||
description
|
||||
"If set, clixon will accept the 'creator' attribute as defined by the
|
||||
creator annotation in clixon-lib.
|
||||
It can be used when several clients (such as a 'service') can create the same object.
|
||||
If one such client/service is deleted, the object is deleted only if all services
|
||||
that created the object are deleted.
|
||||
The clixon controller uses this feature, but could in principle be used by other
|
||||
applications.";
|
||||
}
|
||||
leaf CLICON_RESTCONF_API_ROOT {
|
||||
type string;
|
||||
default "/restconf";
|
||||
|
|
@ -612,7 +635,7 @@ module clixon-config {
|
|||
edit operation.
|
||||
Setting this option disables this behaviour, ie the startup configuration is NOT
|
||||
automatically updated.
|
||||
If this option is false, the startup is autoamtically updated following the RFC";
|
||||
If this option is false, the startup is automatically updated following the RFC";
|
||||
}
|
||||
leaf CLICON_RESTCONF_USER {
|
||||
type string;
|
||||
|
|
@ -675,7 +698,7 @@ module clixon-config {
|
|||
Both feature clixon-restconf:http-data and restconf/enable-http-data
|
||||
must be enabled for this match to occur.";
|
||||
}
|
||||
leaf CLICON_HTTP_DATA_ROOT{
|
||||
leaf CLICON_HTTP_DATA_ROOT{
|
||||
if-feature "clrc:http-data";
|
||||
type string;
|
||||
default "/var/www";
|
||||
|
|
@ -931,7 +954,7 @@ module clixon-config {
|
|||
Others are experimental (in Clixon 5.5)";
|
||||
}
|
||||
leaf CLICON_XMLDB_FORMAT {
|
||||
type datastore_format;
|
||||
type cl:datastore_format;
|
||||
default xml;
|
||||
description "XMLDB datastore format.";
|
||||
}
|
||||
|
|
@ -1005,6 +1028,18 @@ module clixon-config {
|
|||
as well as the CLIgen callbacks.
|
||||
See https://clixon-docs.readthedocs.io/en/latest/backend.html#plugin-callback-guidelines";
|
||||
}
|
||||
leaf CLICON_PLUGIN_DLOPEN_GLOBAL {
|
||||
type boolean;
|
||||
default false;
|
||||
description
|
||||
"Local/global flag for dlopen as described in the man page.
|
||||
This applies to the opening of all clixon plugins (backend/cli/netconf/restconf)
|
||||
when loading the shared .so file with dlopen.
|
||||
If false: Symbols defined in this shared object are not made available to resolve
|
||||
references in subsequently loaded shared objects (default).
|
||||
If true: The symbols defined by this shared object will be made available for symbol res‐
|
||||
olution of subsequently loaded shared objects.";
|
||||
}
|
||||
leaf CLICON_YANG_AUGMENT_ACCEPT_BROKEN {
|
||||
type boolean;
|
||||
default false;
|
||||
|
|
@ -1094,7 +1129,7 @@ module clixon-config {
|
|||
restconf GET.
|
||||
The module state data is on the form:
|
||||
<yang-library><module-set>...
|
||||
instead where the modile state is on the form:
|
||||
instead where the module state is on the form:
|
||||
<modules-state>...
|
||||
See also CLICON_XMLDB_MODSTATE where the module state info is used to tag datastores
|
||||
with module information.";
|
||||
|
|
@ -1131,7 +1166,7 @@ module clixon-config {
|
|||
default false;
|
||||
description
|
||||
"Enable event stream discovery as described in RFC 5277
|
||||
sections 3.2. If enabled, available streams will appear
|
||||
section 3.2. If enabled, available streams will appear
|
||||
when doing netconf get or restconf GET";
|
||||
}
|
||||
leaf CLICON_STREAM_DISCOVERY_RFC8040 {
|
||||
|
|
@ -71,6 +71,7 @@ module clixon-lib {
|
|||
revision 2023-11-01 {
|
||||
description
|
||||
"Added ignore-compare extension
|
||||
Added creator meta configuration
|
||||
Removed obsolete extension autocli-op
|
||||
Released in 6.5.0";
|
||||
}
|
||||
|
|
@ -209,6 +210,21 @@ module clixon-lib {
|
|||
Limitations: only objects that are actually added or deleted.
|
||||
A sub-object will not be noted";
|
||||
}
|
||||
container creators{
|
||||
config false;
|
||||
description "Meta-data for creator attribute.";
|
||||
list creator {
|
||||
key name;
|
||||
leaf name {
|
||||
description "Name of creator / service (instance) name";
|
||||
type string;
|
||||
}
|
||||
leaf-list path {
|
||||
description "Path to object";
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
rpc debug {
|
||||
description "Set debug level of backend.";
|
||||
input {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue