Revert and obsolete the creators attribute feature introduced in 6.2.
This commit is contained in:
parent
465a5999fe
commit
88b60daa75
10 changed files with 16 additions and 534 deletions
|
|
@ -25,6 +25,12 @@ Expected: February 2024
|
||||||
* Added reference count for shared yang-specs (schema mounts)
|
* Added reference count for shared yang-specs (schema mounts)
|
||||||
* Allowed for sharing yspec+modules between several mountpoints
|
* Allowed for sharing yspec+modules between several mountpoints
|
||||||
|
|
||||||
|
### API changes on existing protocol/config features
|
||||||
|
Users may have to change how they access the system
|
||||||
|
|
||||||
|
* Revert the creators attribute feature introduced in 6.2. It is now obsoleted.
|
||||||
|
It is replaced with a configured `creators` and user/application semantics
|
||||||
|
|
||||||
### C/CLI-API changes on existing features
|
### C/CLI-API changes on existing features
|
||||||
Developers may need to change their code
|
Developers may need to change their code
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -234,14 +234,6 @@ uint16_t xml_flag(cxobj *xn, uint16_t flag);
|
||||||
int xml_flag_set(cxobj *xn, uint16_t flag);
|
int xml_flag_set(cxobj *xn, uint16_t flag);
|
||||||
int xml_flag_reset(cxobj *xn, uint16_t flag);
|
int xml_flag_reset(cxobj *xn, uint16_t flag);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
char *xml_value(cxobj *xn);
|
char *xml_value(cxobj *xn);
|
||||||
int xml_value_set(cxobj *xn, char *val);
|
int xml_value_set(cxobj *xn, char *val);
|
||||||
int xml_value_append(cxobj *xn, char *val);
|
int xml_value_append(cxobj *xn, char *val);
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,5 @@ int xml_rpc_isaction(cxobj *xn);
|
||||||
int xml_find_action(cxobj *xn, int top, cxobj **xap);
|
int xml_find_action(cxobj *xn, int top, cxobj **xap);
|
||||||
int purge_tagged_nodes(cxobj *xn, char *ns, char *name, char *value, int keepnode);
|
int purge_tagged_nodes(cxobj *xn, char *ns, char *name, char *value, int keepnode);
|
||||||
int clixon_compare_xmls(cxobj *xc1, cxobj *xc2, enum format_enum format);
|
int clixon_compare_xmls(cxobj *xc1, cxobj *xc2, enum format_enum format);
|
||||||
int xml_creator_tree(cxobj *xt, cxobj **xcreator);
|
|
||||||
|
|
||||||
#endif /* _CLIXON_XML_MAP_H_ */
|
#endif /* _CLIXON_XML_MAP_H_ */
|
||||||
|
|
|
||||||
|
|
@ -442,56 +442,6 @@ disable_nacm_on_empty(cxobj *xt,
|
||||||
return retval;
|
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(clixon_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
|
/*! Common read function that reads an XML tree from file
|
||||||
*
|
*
|
||||||
* @param[in] th Datastore text handle
|
* @param[in] th Datastore text handle
|
||||||
|
|
@ -593,19 +543,6 @@ xmldb_readfile(clixon_handle h,
|
||||||
xml_flag_set(x0, XML_FLAG_TOP);
|
xml_flag_set(x0, XML_FLAG_TOP);
|
||||||
if (xml_child_nr(x0) == 0 && de)
|
if (xml_child_nr(x0) == 0 && de)
|
||||||
de->de_empty = 1;
|
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 */
|
/* Check if we support modstate */
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_MODSTATE"))
|
if (clicon_option_bool(h, "CLICON_XMLDB_MODSTATE"))
|
||||||
if ((msdiff = modstate_diff_new()) == NULL)
|
if ((msdiff = modstate_diff_new()) == NULL)
|
||||||
|
|
|
||||||
|
|
@ -493,7 +493,6 @@ text_modify(clixon_handle h,
|
||||||
char *restype;
|
char *restype;
|
||||||
int ismount = 0;
|
int ismount = 0;
|
||||||
yang_stmt *mount_yspec = NULL;
|
yang_stmt *mount_yspec = NULL;
|
||||||
char *creator = NULL;
|
|
||||||
|
|
||||||
if (x1 == NULL){
|
if (x1 == NULL){
|
||||||
clixon_err(OE_XML, EINVAL, "x1 is missing");
|
clixon_err(OE_XML, EINVAL, "x1 is missing");
|
||||||
|
|
@ -534,13 +533,6 @@ text_modify(clixon_handle h,
|
||||||
clicon_data_set(h, "objectexisted", "true");
|
clicon_data_set(h, "objectexisted", "true");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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);
|
x1name = xml_name(x1);
|
||||||
|
|
||||||
if (yang_keyword_get(y0) == Y_LEAF_LIST ||
|
if (yang_keyword_get(y0) == Y_LEAF_LIST ||
|
||||||
|
|
@ -703,10 +695,6 @@ text_modify(clixon_handle h,
|
||||||
xml_flag_reset(x0, XML_FLAG_DEFAULT);
|
xml_flag_reset(x0, XML_FLAG_DEFAULT);
|
||||||
}
|
}
|
||||||
} /* x1bstr */
|
} /* x1bstr */
|
||||||
if (creator){
|
|
||||||
if (xml_creator_add(x0, creator) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (changed){
|
if (changed){
|
||||||
if (xml_insert(x0p, x0, insert, valstr, NULL) < 0)
|
if (xml_insert(x0p, x0, insert, valstr, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -807,11 +795,6 @@ text_modify(clixon_handle h,
|
||||||
* original object is not reverted.
|
* original object is not reverted.
|
||||||
*/
|
*/
|
||||||
if (x0){
|
if (x0){
|
||||||
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);
|
xml_purge(x0);
|
||||||
x0 = NULL;
|
x0 = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -862,10 +845,6 @@ text_modify(clixon_handle h,
|
||||||
#ifdef XML_PARENT_CANDIDATE
|
#ifdef XML_PARENT_CANDIDATE
|
||||||
xml_parent_candidate_set(x0, x0p);
|
xml_parent_candidate_set(x0, x0p);
|
||||||
#endif
|
#endif
|
||||||
if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR")){
|
|
||||||
if (xml_creator_copy_one(x1, x0) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
changed++;
|
changed++;
|
||||||
/* Get namespace from x1
|
/* Get namespace from x1
|
||||||
* Check if namespace exists in x0 parent
|
* Check if namespace exists in x0 parent
|
||||||
|
|
@ -962,10 +941,6 @@ text_modify(clixon_handle h,
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (creator){
|
|
||||||
if (xml_creator_add(x0, creator) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (changed){
|
if (changed){
|
||||||
#ifdef XML_PARENT_CANDIDATE
|
#ifdef XML_PARENT_CANDIDATE
|
||||||
xml_parent_candidate_set(x0, NULL);
|
xml_parent_candidate_set(x0, NULL);
|
||||||
|
|
@ -1007,8 +982,6 @@ text_modify(clixon_handle h,
|
||||||
free(instr);
|
free(instr);
|
||||||
if (opstr)
|
if (opstr)
|
||||||
free(opstr);
|
free(opstr);
|
||||||
if (creator)
|
|
||||||
free(creator);
|
|
||||||
if (createstr)
|
if (createstr)
|
||||||
free(createstr);
|
free(createstr);
|
||||||
if (nscx1)
|
if (nscx1)
|
||||||
|
|
@ -1239,7 +1212,6 @@ xmldb_put(clixon_handle h,
|
||||||
int firsttime = 0;
|
int firsttime = 0;
|
||||||
int pretty;
|
int pretty;
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
cxobj *xmeta = NULL;
|
|
||||||
|
|
||||||
if (cbret == NULL){
|
if (cbret == NULL){
|
||||||
clixon_err(OE_XML, EINVAL, "cbret is NULL");
|
clixon_err(OE_XML, EINVAL, "cbret is NULL");
|
||||||
|
|
@ -1355,18 +1327,6 @@ xmldb_put(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
pretty = clicon_option_bool(h, "CLICON_XMLDB_PRETTY");
|
pretty = clicon_option_bool(h, "CLICON_XMLDB_PRETTY");
|
||||||
/* Add creator attributes to datastore */
|
|
||||||
if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR")){
|
|
||||||
/* @see xml_creator_metadata_read */
|
|
||||||
if (xml_creator_tree(x0, &xmeta) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_addsub(x0, xmeta) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_child_nr_type(xmeta, CX_ELMNT) == 0){
|
|
||||||
xml_purge(xmeta);
|
|
||||||
xmeta = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (strcmp(format,"json")==0){
|
if (strcmp(format,"json")==0){
|
||||||
if (clixon_json2file(f, x0, pretty, fprintf, 0, 0) < 0)
|
if (clixon_json2file(f, x0, pretty, fprintf, 0, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1377,10 +1337,6 @@ xmldb_put(clixon_handle h,
|
||||||
*/
|
*/
|
||||||
if (xmodst && xml_purge(xmodst) < 0)
|
if (xmodst && xml_purge(xmodst) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR") && xmeta){
|
|
||||||
if (xml_purge(xmeta) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
if (f != NULL)
|
if (f != NULL)
|
||||||
|
|
|
||||||
|
|
@ -186,8 +186,6 @@ struct xml{
|
||||||
yang_stmt *x_spec; /* Pointer to specification, eg yang,
|
yang_stmt *x_spec; /* Pointer to specification, eg yang,
|
||||||
by reference, dont free */
|
by reference, dont free */
|
||||||
cg_var *x_cv; /* Cached value as cligen variable (set by xml_cmp) */
|
cg_var *x_cv; /* Cached value as cligen variable (set by xml_cmp) */
|
||||||
cvec *x_creators; /* Support clixon-lib creator annotation.
|
|
||||||
Only if CLICON_NETCONF_CREATOR_ATTR = true */
|
|
||||||
#ifdef XML_EXPLICIT_INDEX
|
#ifdef XML_EXPLICIT_INDEX
|
||||||
struct search_index *x_search_index; /* explicit search index vectors */
|
struct search_index *x_search_index; /* explicit search index vectors */
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -640,186 +638,6 @@ xml_flag_reset(cxobj *xn,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Add a creator tag
|
|
||||||
*
|
|
||||||
* @param[in] xn XML tree
|
|
||||||
* @param[in] name Name of creator tag
|
|
||||||
* @retval 0 OK
|
|
||||||
* @retval -1 Error
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_creator_add(cxobj *xn,
|
|
||||||
char *name)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
cg_var *cv;
|
|
||||||
|
|
||||||
if (!is_element(xn))
|
|
||||||
goto ok;
|
|
||||||
if (xn->x_creators == NULL){
|
|
||||||
if ((xn->x_creators = cvec_new(0)) == NULL){
|
|
||||||
clixon_err(OE_XML, errno, "cvec_new");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((cv = cvec_find(xn->x_creators, name)) == NULL)
|
|
||||||
cvec_add_string(xn->x_creators, name, NULL);
|
|
||||||
ok:
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Remove a creator tag
|
|
||||||
*
|
|
||||||
* @param[in] xn XML tree
|
|
||||||
* @param[in] name Name of creator tag
|
|
||||||
* @retval 0 OK
|
|
||||||
* @retval -1 Error
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_creator_rm(cxobj *xn,
|
|
||||||
char *name)
|
|
||||||
{
|
|
||||||
cg_var *cv;
|
|
||||||
|
|
||||||
if (!is_element(xn))
|
|
||||||
return 0;
|
|
||||||
if ((cv = cvec_find(xn->x_creators, name)) == NULL)
|
|
||||||
return 0;
|
|
||||||
return cvec_del(xn->x_creators, cv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Find a creator string
|
|
||||||
*
|
|
||||||
* @param[in] xn XML tree
|
|
||||||
* @param[in] name Name of creator tag
|
|
||||||
* @retval 1 Yes, xn is tagged with creator tag "name"
|
|
||||||
* @retval 0 No, xn is not tagged with creator tag "name"
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_creator_find(cxobj *xn,
|
|
||||||
char *name)
|
|
||||||
{
|
|
||||||
if (!is_element(xn))
|
|
||||||
return 0;
|
|
||||||
if (xn->x_creators != NULL &&
|
|
||||||
cvec_find(xn->x_creators, name) != NULL)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Get number of creator strings
|
|
||||||
*
|
|
||||||
* @param[in] xn XML tree
|
|
||||||
* @retval len Number of creator tags assigned to xn
|
|
||||||
* @retval 0 No creator tags or non-applicable
|
|
||||||
*/
|
|
||||||
size_t
|
|
||||||
xml_creator_len(cxobj *xn)
|
|
||||||
{
|
|
||||||
if (!is_element(xn))
|
|
||||||
return 0;
|
|
||||||
if (xn->x_creators)
|
|
||||||
return cvec_len(xn->x_creators);
|
|
||||||
else
|
|
||||||
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
|
|
||||||
* @param[in] x1 Destination XML node
|
|
||||||
* @retval 0 OK
|
|
||||||
* @retval -1 Error
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_creator_copy_one(cxobj *x0,
|
|
||||||
cxobj *x1)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
if (x0->x_creators)
|
|
||||||
if ((x1->x_creators = cvec_dup(x0->x_creators)) == NULL){
|
|
||||||
clixon_err(OE_UNIX, errno, "cvec_dup");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Recursively copy creator attributes from existing tree based on equivalence algorithm
|
|
||||||
*
|
|
||||||
* @param[in] x0 Source XML node
|
|
||||||
* @param[in] x1 Destination XML node
|
|
||||||
* @retval 0 OK
|
|
||||||
* @retval -1 Error
|
|
||||||
* @see xml_tree_equal equivalence algorithm
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_creator_copy_all(cxobj *x0,
|
|
||||||
cxobj *x1)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
int eq;
|
|
||||||
cxobj *x0c; /* x0 child */
|
|
||||||
cxobj *x1c; /* x1 child */
|
|
||||||
yang_stmt *yc0;
|
|
||||||
yang_stmt *yc1;
|
|
||||||
|
|
||||||
/* Traverse x0 and x1 in lock-step */
|
|
||||||
x0c = x1c = NULL;
|
|
||||||
x0c = xml_child_each(x0, x0c, CX_ELMNT);
|
|
||||||
x1c = xml_child_each(x1, x1c, CX_ELMNT);
|
|
||||||
for (;;){
|
|
||||||
if (x0c == NULL || x1c == NULL)
|
|
||||||
goto ok;
|
|
||||||
eq = xml_cmp(x0c, x1c, 0, 0, NULL);
|
|
||||||
if (eq < 0){
|
|
||||||
x0c = xml_child_each(x0, x0c, CX_ELMNT);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (eq > 0){
|
|
||||||
x1c = xml_child_each(x1, x1c, CX_ELMNT);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else { /* equal */
|
|
||||||
/* Both x0c and x1c exists and are equal, check if they are yang-equal. */
|
|
||||||
yc0 = xml_spec(x0c);
|
|
||||||
yc1 = xml_spec(x1c);
|
|
||||||
if (yc0 && yc1 && yc0 != yc1){ /* choice */
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (x0c->x_creators){
|
|
||||||
if (xml_creator_copy_one(x0c, x1c) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else if (xml_creator_copy_all(x0c, x1c) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x0c = xml_child_each(x0, x0c, CX_ELMNT);
|
|
||||||
x1c = xml_child_each(x1, x1c, CX_ELMNT);
|
|
||||||
}
|
|
||||||
ok:
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! Get value of xnode
|
/*! Get value of xnode
|
||||||
*
|
*
|
||||||
* @param[in] xn xml node
|
* @param[in] xn xml node
|
||||||
|
|
@ -2148,8 +1966,6 @@ xml_free(cxobj *x)
|
||||||
#ifdef XML_EXPLICIT_INDEX
|
#ifdef XML_EXPLICIT_INDEX
|
||||||
xml_search_index_free(x);
|
xml_search_index_free(x);
|
||||||
#endif
|
#endif
|
||||||
if (x->x_creators)
|
|
||||||
cvec_free(x->x_creators);
|
|
||||||
break;
|
break;
|
||||||
case CX_BODY:
|
case CX_BODY:
|
||||||
case CX_ATTR:
|
case CX_ATTR:
|
||||||
|
|
@ -2192,8 +2008,6 @@ xml_copy_one(cxobj *x0,
|
||||||
switch (xml_type(x0)){
|
switch (xml_type(x0)){
|
||||||
case CX_ELMNT:
|
case CX_ELMNT:
|
||||||
xml_spec_set(x1, xml_spec(x0));
|
xml_spec_set(x1, xml_spec(x0));
|
||||||
if (xml_creator_copy_one(x0, x1) < 0)
|
|
||||||
goto done;
|
|
||||||
break;
|
break;
|
||||||
case CX_BODY:
|
case CX_BODY:
|
||||||
case CX_ATTR:
|
case CX_ATTR:
|
||||||
|
|
|
||||||
|
|
@ -2034,90 +2034,3 @@ clixon_compare_xmls(cxobj *xc1,
|
||||||
unlink(filename2);
|
unlink(filename2);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! 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 2 Locally abort this subtree, continue with others
|
|
||||||
* @retval 1 Abort, dont continue with others, return 1 to end user
|
|
||||||
* @retval 0 OK, continue
|
|
||||||
* @retval -1 Error, aborted at first error encounter, return -1 to end user
|
|
||||||
* On the form:
|
|
||||||
* <creator>
|
|
||||||
* <name>testA[name='foo']</name>
|
|
||||||
* <xpath>...</xpath>
|
|
||||||
* ...
|
|
||||||
* </creator>
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
xml_creator_one(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Create creator data tree on the form (name:xpath*)*
|
|
||||||
*
|
|
||||||
* @param[in] xt XML top-level node, where to look for creator attributes
|
|
||||||
* @param[out] xcreators Created XML tree on the form <creators><creator>...
|
|
||||||
* @retval 0 OK
|
|
||||||
* @retval -1 Error
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml_creator_tree(cxobj *xt,
|
|
||||||
cxobj **xcreators)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
if ((*xcreators = xml_new("creators", NULL, CX_ELMNT)) == NULL)
|
|
||||||
goto done;
|
|
||||||
if (xmlns_set(*xcreators, NULL, CLIXON_LIB_NS) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xml_apply(xt, CX_ELMNT, xml_creator_one, *xcreators) < 0)
|
|
||||||
goto done;
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
#!/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
|
|
||||||
|
|
@ -51,12 +51,14 @@ module clixon-config {
|
||||||
|
|
||||||
revision 2024-01-01 {
|
revision 2024-01-01 {
|
||||||
description
|
description
|
||||||
"Released in Clixon 6.6";
|
"Makred as obsolete:
|
||||||
|
CLICON_NETCONF_CREATOR_ATTR
|
||||||
|
Released in Clixon 6.6";
|
||||||
}
|
}
|
||||||
revision 2023-11-01 {
|
revision 2023-11-01 {
|
||||||
description
|
description
|
||||||
"Added options:
|
"Added options:
|
||||||
CLICON_CREATOR_ATTR
|
CLICON_NETCONF_CREATOR_ATTR
|
||||||
Released in Clixon 6.5";
|
Released in Clixon 6.5";
|
||||||
}
|
}
|
||||||
revision 2023-05-01 {
|
revision 2023-05-01 {
|
||||||
|
|
@ -596,7 +598,10 @@ module clixon-config {
|
||||||
If one such client/service is deleted, the object is deleted only if all services
|
If one such client/service is deleted, the object is deleted only if all services
|
||||||
that created the object are deleted.
|
that created the object are deleted.
|
||||||
The clixon controller uses this feature, but could in principle be used by other
|
The clixon controller uses this feature, but could in principle be used by other
|
||||||
applications.";
|
applications.
|
||||||
|
Marked as obsolete in 6.6 since creators attribute replaced by clixon-lib creators
|
||||||
|
config";
|
||||||
|
status obsolete;
|
||||||
}
|
}
|
||||||
leaf CLICON_RESTCONF_API_ROOT {
|
leaf CLICON_RESTCONF_API_ROOT {
|
||||||
type string;
|
type string;
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ module clixon-lib {
|
||||||
|
|
||||||
revision 2024-01-01 {
|
revision 2024-01-01 {
|
||||||
description
|
description
|
||||||
"Moved container creators to grouping/uses
|
"Moved container creators to grouping/uses and removed config false
|
||||||
Released in 6.6.0";
|
Released in 6.6.0";
|
||||||
}
|
}
|
||||||
revision 2023-11-01 {
|
revision 2023-11-01 {
|
||||||
|
|
@ -217,8 +217,7 @@ module clixon-lib {
|
||||||
}
|
}
|
||||||
grouping clixon-creators{
|
grouping clixon-creators{
|
||||||
container creators{
|
container creators{
|
||||||
config false;
|
description "Meta-data for creation of data objects.";
|
||||||
description "Meta-data for creator attribute.";
|
|
||||||
list creator {
|
list creator {
|
||||||
key name;
|
key name;
|
||||||
leaf name {
|
leaf name {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue