diff --git a/CHANGELOG.md b/CHANGELOG.md index bd205ef9..dd2ff317 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,8 +48,10 @@ Expected: April 2023 Users may have to change how they access the system -* New `clixon-config@2022-12-01.yang` revision +* New `clixon-config@2023-03-01.yang` revision * Added options: `CLICON_RESTCONF_NOALPN_DEFAULT` +* New `clixon-lib@2023-03-01.yang` revision + * Added creator meta-object ### C/CLI-API changes on existing features Developers may need to change their code diff --git a/apps/backend/backend_get.c b/apps/backend/backend_get.c index cd1f073e..86253b42 100644 --- a/apps/backend/backend_get.c +++ b/apps/backend/backend_get.c @@ -328,8 +328,7 @@ get_statedata(clicon_handle h, /* Mark and remove nodes having schema default values */ if (xml_apply((*xret), CX_ELMNT, (xml_applyfn_t*) xml_flag_state_default_value, (void*) XML_FLAG_MARK) < 0) goto done; - if (xml_tree_prune_flags((*xret), XML_FLAG_MARK, XML_FLAG_MARK) - < 0) + if (xml_tree_prune_flags((*xret), XML_FLAG_MARK, XML_FLAG_MARK)< 0) goto done; if (xml_defaults_nopresence((*xret), 1) < 0) goto done; diff --git a/lib/clixon/clixon_xml.h b/lib/clixon/clixon_xml.h index a44060c8..d9892600 100644 --- a/lib/clixon/clixon_xml.h +++ b/lib/clixon/clixon_xml.h @@ -227,6 +227,11 @@ uint16_t xml_flag(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_creator_add(cxobj *xn, char *str); +int xml_creator_rm(cxobj *xn, char *str); +int xml_creator_find(cxobj *xn, char *str); +size_t xml_creator_len(cxobj *xn); + char *xml_value(cxobj *xn); int xml_value_set(cxobj *xn, char *val); int xml_value_append(cxobj *xn, char *val); diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index 0e132867..9cde6d39 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -92,7 +92,7 @@ * If such an attribute its found, its string value is returned. * @param[in] x XML node (where to look for attribute) * @param[in] name Attribute name - * @param[in] ns (Expected)Namespace of attribute + * @param[in] ns (Expected) Namespace of attribute * @param[out] cbret Error message (if retval=0) * @param[out] valp Malloced value (if retval=1) * @retval -1 Error @@ -489,6 +489,7 @@ text_modify(clicon_handle h, char *restype; int ismount = 0; yang_stmt *mount_yspec = NULL; + char *creator = NULL; if (x1 == NULL){ clicon_err(OE_XML, EINVAL, "x1 is missing"); @@ -511,6 +512,7 @@ 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 */ @@ -529,6 +531,11 @@ 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; x1name = xml_name(x1); if (yang_keyword_get(y0) == Y_LEAF_LIST || @@ -932,12 +939,17 @@ text_modify(clicon_handle h, if (ret == 0) goto fail; } + if (creator){ + if (xml_creator_add(x0, creator) < 0) + goto done; + } if (changed){ #ifdef XML_PARENT_CANDIDATE xml_parent_candidate_set(x0, NULL); #endif if (xml_insert(x0p, x0, insert, keystr, nscx1) < 0) goto done; + } break; case OP_DELETE: @@ -972,6 +984,8 @@ text_modify(clicon_handle h, free(instr); if (opstr) free(opstr); + if (creator) + free(creator); if (createstr) free(createstr); if (nscx1) diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c index 3caff658..8f78100c 100644 --- a/lib/src/clixon_xml.c +++ b/lib/src/clixon_xml.c @@ -180,11 +180,11 @@ struct xml{ int x_childvec_len;/* Number of children */ int x_childvec_max;/* Length of allocated vector */ - cvec *x_ns_cache; /* Cached vector of namespaces (set by bind-yang) */ 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 */ #ifdef XML_EXPLICIT_INDEX struct search_index *x_search_index; /* explicit search index vectors */ #endif @@ -617,6 +617,72 @@ xml_flag_reset(cxobj *xn, return 0; } +/*! Add a creator string + */ +int +xml_creator_add(cxobj *xn, + char *str) +{ + int retval = -1; + cg_var *cv; + + if (!is_element(xn)) + return 0; + if (xn->x_creators == NULL){ + if ((xn->x_creators = cvec_new(0)) == NULL){ + clicon_err(OE_XML, errno, "cvec_new"); + goto done; + } + } + if ((cv = cvec_find(xn->x_creators, str)) == NULL) + cvec_add_string(xn->x_creators, str, NULL); + retval = 0; + done: + return retval; +} + +/*! Remove a creator string + */ +int +xml_creator_rm(cxobj *xn, + char *str) +{ + cg_var *cv; + + if (!is_element(xn)) + return 0; + if ((cv = cvec_find(xn->x_creators, str)) == NULL) + return 0; + return cvec_del(xn->x_creators, cv); +} + +/*! Find a creator string + */ +int +xml_creator_find(cxobj *xn, + char *str) +{ + if (!is_element(xn)) + return 0; + if (xn->x_creators != NULL && + cvec_find(xn->x_creators, str) != NULL) + return 1; + return 0; +} + +/*! Get number of creator strings + */ +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 value of xnode * @param[in] xn xml node * @retval value of xml node @@ -1874,6 +1940,8 @@ xml_free(cxobj *x) #ifdef XML_EXPLICIT_INDEX xml_search_index_free(x); #endif + if (x->x_creators) + cvec_free(x->x_creators); break; case CX_BODY: case CX_ATTR: @@ -1915,6 +1983,11 @@ xml_copy_one(cxobj *x0, switch (xml_type(x0)){ case CX_ELMNT: xml_spec_set(x1, xml_spec(x0)); + if (x0->x_creators) + if ((x1->x_creators = cvec_dup(x0->x_creators)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_dup"); + goto done; + } break; case CX_BODY: case CX_ATTR: @@ -2069,6 +2142,7 @@ cxvec_prepend(cxobj *x, /*! Apply a function call recursively on all xml node children recursively + * * Recursively traverse all xml nodes in a parse-tree and apply fn(arg) for * each object found. The function is called with the xml node and an * argument as args. diff --git a/yang/clixon/Makefile.in b/yang/clixon/Makefile.in index 0d5fb336..964a6526 100644 --- a/yang/clixon/Makefile.in +++ b/yang/clixon/Makefile.in @@ -43,7 +43,7 @@ YANG_INSTALLDIR = @YANG_INSTALLDIR@ # Note: mirror these to test/config.sh.in YANGSPECS = clixon-config@2023-03-01.yang # 6.2 -YANGSPECS += clixon-lib@2022-12-01.yang # 6.1 +YANGSPECS += clixon-lib@2023-03-01.yang # 6.2 YANGSPECS += clixon-rfc5277@2008-07-01.yang YANGSPECS += clixon-xml-changelog@2019-03-21.yang YANGSPECS += clixon-restconf@2022-08-01.yang # 5.9 diff --git a/yang/clixon/clixon-lib@2021-12-05.yang b/yang/clixon/clixon-lib@2023-03-01.yang similarity index 81% rename from yang/clixon/clixon-lib@2021-12-05.yang rename to yang/clixon/clixon-lib@2023-03-01.yang index 67d702d6..c5e722f6 100644 --- a/yang/clixon/clixon-lib@2021-12-05.yang +++ b/yang/clixon/clixon-lib@2023-03-01.yang @@ -6,6 +6,12 @@ module clixon-lib { import ietf-yang-types { prefix yang; } + import ietf-netconf-monitoring { + prefix ncm; + } + import ietf-yang-metadata { + prefix "md"; + } organization "Clicon / Clixon"; @@ -13,22 +19,7 @@ module clixon-lib { "Olof Hagsand "; description - "Clixon Netconf extensions for communication between clients and backend. - - Clixon 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 - - ***** BEGIN LICENSE BLOCK ***** + "***** BEGIN LICENSE BLOCK ***** Copyright (C) 2009-2019 Olof Hagsand Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate) @@ -55,8 +46,37 @@ module clixon-lib { 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 *****"; + ***** 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 + "; + + 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"; @@ -100,15 +120,15 @@ module clixon-lib { type enumeration { enum start { description - "Start if not already running"; + "Start if not already running"; } enum stop { description - "Stop if running"; + "Stop if running"; } enum restart { description - "Stop if running, then start"; + "Stop if running, then start"; } enum status { description @@ -118,9 +138,31 @@ module clixon-lib { description "Common operations that can be performed on a service"; } + 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, reverese proxy (eg fcgi/nginx) or native"; + base ncm:transport; + } + identity cli { + description + "A CLI session"; + base ncm:transport; + } extension autocli-op { - description - "Takes an argument an operation defing how to modify the clispec at + description + "Takes an argument an operation defing how to modify the clispec at this point in the YANG tree for the automated generated CLI. Note that this extension is only used in clixon_cli. Operations is expected to be extended, but the following operations are defined: @@ -128,10 +170,21 @@ module clixon-lib { - hide-database This command hides the database - hide-database-auto-completion This command hides the database and the auto completion (meaning, this command acts as both commands above) Obsolete: use clixon-autocli:hide and clixon-autocli:hide-show instead"; - argument cliop; - status obsolete; - } - rpc debug { + argument cliop; + status obsolete; + } + + 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 wil not be noted"; + } + rpc debug { description "Set debug level of backend."; input { leaf level {