diff --git a/CHANGELOG.md b/CHANGELOG.md
index efd55f84..7526106f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -43,11 +43,14 @@ Expected: beginning of 2023
### New features
-* YANG schema mount RFC 8528 (work in progress)
+* YANG schema mount RFC 8528
+ * Experimental
* Restrictions:
- * only schema-ref=inline, not shared-schema
+ * Only schema-ref=inline, not shared-schema
+ * Only presence containers can be mount-points
+ * New plugin callback: `ca_yang_mount`
* Standards: RFC 8528
- * Enable `YANG_SCHEMA_MOUNT`
+ * To enable: define `YANG_SCHEMA_MOUNT`
* Netconf monitoring RFC 6022 , part 2
* Datastores and sessions
* Added clixon-specific transport identities: cli, snmp, netconf, restconf
diff --git a/README.md b/README.md
index c1e6f8f4..94ae57f7 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,6 @@ General Public License Version 2; you choose, see [LICENSE.md](LICENSE.md).
Clixon has a master branch continuously tested with CI, but releases are made ca every second month. Latest 6.0.0 release is from November 2022. Next is planned for January 2023. See [CHANGELOG.md](CHANGELOG.md) release history.
Clixon interaction is best done posting issues, pull requests, or joining the
-Matrix channels: https://matrix.to/#/#clixondev:matrix.org for general info and discussion, and
-https://matrix.to/#/#clixontech:matrix.org for technical details and issues.
+Matrix clixon forum https://matrix.to/#/#clixonforum:matrix.org.
Clixon is sponsored by [Rubicon Communications LLC(Netgate)](https://www.netgate.com/) and [Akamai Technologies, Inc.](https://www.akamai.com).
diff --git a/apps/backend/backend_get.c b/apps/backend/backend_get.c
index 413d875f..0ad46550 100644
--- a/apps/backend/backend_get.c
+++ b/apps/backend/backend_get.c
@@ -298,7 +298,7 @@ get_statedata(clicon_handle h,
goto fail;
}
#ifdef YANG_SCHEMA_MOUNT
- if ((ret = schema_mounts_state_get(h, yspec, xpath, nsc, xret, &xerr)) < 0)
+ if ((ret = yang_schema_mount_statedata(h, yspec, xpath, nsc, xret, &xerr)) < 0)
goto done;
if (ret == 0){
if (clixon_netconf_internal_error(xerr, " . Internal error, schema_mounts_state_get returned invalid XML", NULL) < 0)
diff --git a/example/main/example_backend.c b/example/main/example_backend.c
index 1e540305..1e728857 100644
--- a/example/main/example_backend.c
+++ b/example/main/example_backend.c
@@ -880,6 +880,50 @@ example_upgrade(clicon_handle h,
return retval;
}
+/*! Example YANG schema mount
+ *
+ * Given an XML mount-point xt, return XML yang-lib modules-set
+ * @param[in] h Clixon handle
+ * @param[in] xt XML mount-point in XML tree
+ * @param[out] yanglib XML yang-lib module-set tree
+ * @retval 0 OK
+ * @retval -1 Error
+ * XXX hardcoded to clixon-example@2022-11-01.yang regardless of xt
+ * @see RFC 8528
+ */
+int
+main_yang_mount(clicon_handle h,
+ cxobj *xt,
+ cxobj **yanglib)
+{
+ int retval = -1;
+ cbuf *cb = NULL;
+
+ if ((cb = cbuf_new()) == NULL){
+ clicon_err(OE_UNIX, errno, "cbuf_new");
+ goto done;
+ }
+ cprintf(cb, "");
+ cprintf(cb, "");
+ cprintf(cb, "mount");
+ cprintf(cb, "");
+ cprintf(cb, "clixon-example");
+ cprintf(cb, "2022-11-01");
+ cprintf(cb, "urn:example:urn");
+ cprintf(cb, "");
+ cprintf(cb, "");
+ cprintf(cb, "");
+ if (clixon_xml_parse_string(cbuf_get(cb), YB_NONE, NULL, yanglib, NULL) < 0)
+ goto done;
+ if (xml_rootchild(*yanglib, 0, yanglib) < 0)
+ goto done;
+ retval = 0;
+ done:
+ if (cb)
+ cbuf_free(cb);
+ return retval;
+}
+
/*! Testcase module-specific upgrade function moving interfaces-state to interfaces
* @param[in] h Clicon handle
* @param[in] xn XML tree to be updated
@@ -1302,6 +1346,7 @@ static clixon_plugin_api api = {
.ca_trans_end=main_end, /* trans end */
.ca_trans_abort=main_abort, /* trans abort */
.ca_datastore_upgrade=example_upgrade, /* general-purpose upgrade. */
+ .ca_yang_mount=main_yang_mount /* RFC 8528 schema mount */
};
/*! Backend plugin initialization
diff --git a/include/clixon_custom.h b/include/clixon_custom.h
index 3d539fc2..ce4e5f27 100644
--- a/include/clixon_custom.h
+++ b/include/clixon_custom.h
@@ -192,8 +192,8 @@
*/
#undef NETCONF_DEFAULT_RETRIEVAL_REPORT_ALL
-/*! Development option for RFC 8528 YANG schema mount
- * Work-in-progress
+/*! RFC 8528 YANG schema mount
+ * Experimental
* See also test/test_yang_schema_mount.sh
*/
#undef YANG_SCHEMA_MOUNT
diff --git a/lib/clixon/clixon_plugin.h b/lib/clixon/clixon_plugin.h
index 6babbfd8..7f25161a 100644
--- a/lib/clixon/clixon_plugin.h
+++ b/lib/clixon/clixon_plugin.h
@@ -269,6 +269,26 @@ typedef char *(cli_prompthook_t)(clicon_handle, char *mode);
*/
typedef int (datastore_upgrade_t)(clicon_handle h, const char *db, cxobj *xt, modstate_diff_t *msd);
+/*! YANG schema mount
+ *
+ * Given an XML mount-point xt, return XML yang-lib modules-set
+ * Return yanglib as XML tree on the RFC8525 form:
+ *
+ *
+ * ...
+ * ...
+ *
+ *
+ * No need to YANG bind.
+ * @param[in] h Clixon handle
+ * @param[in] xt XML mount-point in XML tree
+ * @param[out] yanglib XML yang-lib module-set tree. Freed by caller.
+ * @retval 0 OK
+ * @retval -1 Error
+ * @see RFC 8528 (schema-mount) and RFC 8525 (yang-lib)
+ */
+typedef int (yang_mount_t)(clicon_handle h, cxobj *xt, cxobj **yanglib);
+
/*! Startup status for use in startup-callback
* Note that for STARTUP_ERR and STARTUP_INVALID, running runs in failsafe mode
* and startup contains the erroneous or invalid database.
@@ -322,6 +342,7 @@ struct clixon_plugin_api{
trans_cb_t *cb_trans_end; /* Transaction completed */
trans_cb_t *cb_trans_abort; /* Transaction aborted */
datastore_upgrade_t *cb_datastore_upgrade; /* General-purpose datastore upgrade */
+ yang_mount_t *cb_yang_mount; /* RFC 8528 schema mount */
} cau_backend;
} u;
};
@@ -344,6 +365,7 @@ struct clixon_plugin_api{
#define ca_trans_end u.cau_backend.cb_trans_end
#define ca_trans_abort u.cau_backend.cb_trans_abort
#define ca_datastore_upgrade u.cau_backend.cb_datastore_upgrade
+#define ca_yang_mount u.cau_backend.cb_yang_mount
/*
* Macros
@@ -419,6 +441,9 @@ int clixon_plugin_extension_all(clicon_handle h, yang_stmt *yext, yang_stmt *ys)
int clixon_plugin_datastore_upgrade_one(clixon_plugin_t *cp, clicon_handle h, const char *db, cxobj *xt, modstate_diff_t *msd);
int clixon_plugin_datastore_upgrade_all(clicon_handle h, const char *db, cxobj *xt, modstate_diff_t *msd);
+int clixon_plugin_yang_mount_one(clixon_plugin_t *cp, clicon_handle h, cxobj *xt, cxobj **yanglib);
+int clixon_plugin_yang_mount_all(clicon_handle h, cxobj *xt, cxobj **yanglib);
+
/* rpc callback API */
int rpc_callback_register(clicon_handle h, clicon_rpc_cb cb, void *arg, const char *ns, const char *name);
int rpc_callback_call(clicon_handle h, cxobj *xe, void *arg, int *nrp, cbuf *cbret);
diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h
index 0e3e0342..35a8dd3c 100644
--- a/lib/clixon/clixon_yang.h
+++ b/lib/clixon/clixon_yang.h
@@ -214,6 +214,7 @@ cg_var *yang_cv_get(yang_stmt *ys);
int yang_cv_set(yang_stmt *ys, cg_var *cv);
cvec *yang_cvec_get(yang_stmt *ys);
int yang_cvec_set(yang_stmt *ys, cvec *cvv);
+cg_var *yang_cvec_add(yang_stmt *ys, enum cv_type type, char *name);
uint16_t yang_flag_get(yang_stmt *ys, uint16_t flag);
int yang_flag_set(yang_stmt *ys, uint16_t flag);
int yang_flag_reset(yang_stmt *ys, uint16_t flag);
diff --git a/lib/clixon/clixon_yang_module.h b/lib/clixon/clixon_yang_module.h
index 121c4ab1..a8686615 100644
--- a/lib/clixon/clixon_yang_module.h
+++ b/lib/clixon/clixon_yang_module.h
@@ -78,5 +78,6 @@ yang_stmt *yang_find_module_by_name_revision(yang_stmt *yspec, const char *name,
yang_stmt *yang_find_module_by_name(yang_stmt *yspec, char *name);
int yang_metadata_annotation_check(cxobj *x, yang_stmt *ymod, int *ismeta);
int yang_metadata_init(clicon_handle h);
+int yang_lib2yspec(clicon_handle h, cxobj *yanglib,yang_stmt *yspec);
#endif /* _CLIXON_YANG_MODULE_H_ */
diff --git a/lib/clixon/clixon_yang_parse_lib.h b/lib/clixon/clixon_yang_parse_lib.h
index e51b8c9f..fe3efb05 100644
--- a/lib/clixon/clixon_yang_parse_lib.h
+++ b/lib/clixon/clixon_yang_parse_lib.h
@@ -52,6 +52,7 @@
* Prototypes
*/
yang_stmt *yang_parse_file(FILE *fp, const char *name, yang_stmt *ysp);
+int yang_file_find_match(clicon_handle h, const char *module, const char *revision, cbuf *fbuf);
yang_stmt *yang_parse_filename(const char *filename, yang_stmt *ysp);
int yang_parse_post(clicon_handle h, yang_stmt *yspec, int modmin);
int yang_spec_parse_module(clicon_handle h, const char *module,
diff --git a/lib/clixon/clixon_yang_schema_mount.h b/lib/clixon/clixon_yang_schema_mount.h
index 412c5a58..01be5f47 100644
--- a/lib/clixon/clixon_yang_schema_mount.h
+++ b/lib/clixon/clixon_yang_schema_mount.h
@@ -44,12 +44,26 @@
*/
#define YANG_SCHEMA_MOUNT_NAMESPACE "urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount"
+/* Limitations/deviations from RFC 8528 */
+/*! Only support YANG presende containers as mount-points
+ * This is a limitation of othe current implementation
+ */
+#define YANG_SCHEMA_MOUNT_ONLY_PRESENCE_CONTAINERS
+
+/*! Force add ietf-yang-library@2019-01-04 on all mount-points
+ * This is a limitation of othe current implementation
+ */
+#define YANG_SCHEMA_MOUNT_YANG_LIB_FORCE
+
/*
* Prototypes
*/
int yang_schema_mount_point(yang_stmt *y);
-
-int schema_mounts_state_get(clicon_handle h, yang_stmt *yspec, char *xpath, cvec *nsc, cxobj **xret, cxobj **xerr);
-int yang_schema_unknown(clicon_handle h, yang_stmt *yext, yang_stmt *ys);
+int xml_yang_mount_get(cxobj *x, yang_stmt **yspec);
+int xml_yang_mount_set(cxobj *x, yang_stmt *yspec);
+int xml_yang_mount_freeall(cvec *cvv);
+int yang_schema_mount_statedata(clicon_handle h, yang_stmt *yspec, char *xpath, cvec *nsc, cxobj **xret, cxobj **xerr);
+int yang_schema_yanglib_parse_mount(clicon_handle h, cxobj *xt);
+int yang_schema_get_child(clicon_handle h, cxobj *x1, cxobj *x1c, yang_stmt **yc);
#endif /* _CLIXON_YANG_SCHEMA_MOUNT_H_ */
diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c
index 1c1cb30c..defc8343 100644
--- a/lib/src/clixon_datastore_write.c
+++ b/lib/src/clixon_datastore_write.c
@@ -75,6 +75,7 @@
#include "clixon_netconf_lib.h"
#include "clixon_yang_type.h"
#include "clixon_yang_module.h"
+#include "clixon_yang_schema_mount.h"
#include "clixon_xml_nsctx.h"
#include "clixon_xml_io.h"
#include "clixon_xml_default.h"
@@ -854,21 +855,25 @@ text_modify(clicon_handle h,
while ((x1c = xml_child_each(x1, x1c, CX_ELMNT)) != NULL) {
x1cname = xml_name(x1c);
/* Get yang spec of the child by child matching */
- yc = yang_find_datanode(y0, x1cname);
- if (yc == NULL){
- if (clicon_option_bool(h, "CLICON_YANG_UNKNOWN_ANYDATA") == 1){
- /* Add dummy Y_ANYDATA yang stmt, see ysp_add */
- if ((yc = yang_anydata_add(y0, x1cname)) < 0)
- goto done;
- xml_spec_set(x1c, yc);
- clicon_log(LOG_WARNING,
- "%s: %d: No YANG spec for %s, anydata used",
- __FUNCTION__, __LINE__, x1cname);
- }
- else{
- if (netconf_unknown_element(cbret, "application", x1cname, "Unassigned yang spec") < 0)
- goto done;
- goto fail;
+ if ((yc = yang_find_datanode(y0, x1cname)) == NULL){
+#ifdef YANG_SCHEMA_MOUNT
+ yc = xml_spec(x1c);
+#endif
+ if (yc == NULL){
+ if (clicon_option_bool(h, "CLICON_YANG_UNKNOWN_ANYDATA") == 1){
+ /* Add dummy Y_ANYDATA yang stmt, see ysp_add */
+ if ((yc = yang_anydata_add(y0, x1cname)) < 0)
+ goto done;
+ xml_spec_set(x1c, yc);
+ clicon_log(LOG_WARNING,
+ "%s: %d: No YANG spec for %s, anydata used",
+ __FUNCTION__, __LINE__, x1cname);
+ }
+ else{
+ if (netconf_unknown_element(cbret, "application", x1cname, "Unassigned yang spec") < 0)
+ goto done;
+ goto fail;
+ }
}
}
/* There is a cornercase (eg augment) of multi-namespace trees where
@@ -898,8 +903,11 @@ text_modify(clicon_handle h,
while ((x1c = xml_child_each(x1, x1c, CX_ELMNT)) != NULL) {
x0c = x0vec[i++];
x1cname = xml_name(x1c);
-
- yc = yang_find_datanode(y0, x1cname);
+ if ((yc = yang_find_datanode(y0, x1cname)) == NULL){
+#ifdef YANG_SCHEMA_MOUNT
+ yc = xml_spec(x1c);
+#endif
+ }
if ((ret = text_modify(h, x0c, x0, x0t, x1c, x1t,
yc, op,
username, xnacm, permit, cbret)) < 0)
diff --git a/lib/src/clixon_plugin.c b/lib/src/clixon_plugin.c
index 0d9d3daa..a585c680 100644
--- a/lib/src/clixon_plugin.c
+++ b/lib/src/clixon_plugin.c
@@ -547,9 +547,9 @@ plugin_context_get(void)
* @param[in,out] wh Either: NULL for init, will be assigned, OR previous handle (will be freed)
* @param[in] name Name of plugin for logging. Can be other name, context dependent
* @param[in] fn Typically name of callback, or caller function
- * @retval -1 Error
- * @retval 0 Fail, log on syslog using LOG_WARNING
* @retval 1 OK
+ * @retval 0 Fail, log on syslog using LOG_WARNING
+ * @retval -1 Error
* @note Only logs error, does not generate error
* @note name and fn are context dependent, since the env of callback calls are very different
* @see plugin_context_get
@@ -786,9 +786,9 @@ clixon_plugin_exit_all(clicon_handle h)
* @param[out] authp NULL: Credentials failed, no user set (401 returned).
* String: Credentials OK, the associated user, must be mallloc:ed
* Parameter signtificant only if retval is 1/OK
- * @retval -1 Fatal error
- * @retval 0 Ignore, undecided, not handled, same as no callback
* @retval 1 OK, see authp parameter on result.
+ * @retval 0 Ignore, undecided, not handled, same as no callback
+ * @retval -1 Fatal error
* @note If authenticated either a callback was called and clicon_username_set()
* Or no callback was found.
*/
@@ -833,9 +833,9 @@ clixon_plugin_auth_one(clixon_plugin_t *cp,
* @param[out] authp NULL: Credentials failed, no user set (401 returned).
* String: Credentials OK, the associated user, must be mallloc:ed
* Parameter signtificant only if retval is 1/OK
- * @retval -1 Fatal error
- * @retval 0 Ignore, undecided, not handled, same as no callback
* @retval 1 OK, see authp parameter for result.
+ * @retval 0 Ignore, undecided, not handled, same as no callback
+ * @retval -1 Fatal error
* @note If authp returns string, it should be malloced
*/
int
@@ -981,8 +981,8 @@ clixon_plugin_datastore_upgrade_one(clixon_plugin_t *cp,
* @param[in] db Name of datastore, eg "running", "startup" or "tmp"
* @param[in] xt XML tree. Upgrade this "in place"
* @param[in] msd Module-state diff, info on datastore module-state
- * @retval -1 Error
* @retval 0 OK
+ * @retval -1 Error
* Upgrade datastore on load before or as an alternative to module-specific upgrading mechanism
*/
int
@@ -1003,6 +1003,72 @@ clixon_plugin_datastore_upgrade_all(clicon_handle h,
return retval;
}
+/*! Call plugin YANG schema mount
+ *
+
+ * (No need to be yang bound?
+ * @param[in] cp Plugin handle
+ * @param[in] h Clixon handle
+ * @param[in] xt XML mount-point in XML tree
+ * @param[out] yanglib XML yang-lib module-set tree
+ * @retval 0 OK
+ * @retval -1 Error
+ */
+int
+clixon_plugin_yang_mount_one(clixon_plugin_t *cp,
+ clicon_handle h,
+ cxobj *xt,
+ cxobj **yanglib)
+{
+ int retval = -1;
+ yang_mount_t *fn;
+ void *wh = NULL;
+
+ if ((fn = cp->cp_api.ca_yang_mount) != NULL){
+ wh = NULL;
+ if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
+ goto done;
+ if (fn(h, xt, yanglib) < 0) {
+ if (clicon_errno < 0)
+ clicon_log(LOG_WARNING, "%s: Internal error: Yang mount callback in plugin: %s returned -1 but did not make a clicon_err call",
+ __FUNCTION__, cp->cp_name);
+ goto done;
+ }
+ if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
+ goto done;
+ }
+ retval = 0;
+ done:
+ return retval;
+}
+
+/*! Call plugin YANG schema mount in all plugins, break at first return
+ *
+ * @param[in] h Clixon handle
+ * @param[in] xt XML mount-point in XML tree
+ * @param[out] yanglib XML yang-lib module-set tree (freed by caller)
+ * @retval 0 OK
+ * @retval -1 Error
+ */
+int
+clixon_plugin_yang_mount_all(clicon_handle h,
+ cxobj *xt,
+ cxobj **yanglib)
+{
+ int retval = -1;
+ clixon_plugin_t *cp = NULL;
+
+ while ((cp = clixon_plugin_each(h, cp)) != NULL) {
+ if (clixon_plugin_yang_mount_one(cp, h, xt, yanglib) < 0)
+ goto done;
+ if (*yanglib)
+ break;
+ }
+ retval = 0;
+ done:
+ return retval;
+}
+
/*--------------------------------------------------------------------
* RPC callbacks for both client/frontend and backend plugins.
*/
@@ -1166,7 +1232,7 @@ rpc_callback_call(clicon_handle h,
*nrp = nr;
retval = 1; /* 0: none found, >0 nr of handlers called */
done:
- clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
+ clicon_debug(CLIXON_DBG_DETAIL, "%s retval:%d", __FUNCTION__, retval);
return retval;
fail:
retval = 0;
@@ -1373,9 +1439,9 @@ upgrade_callback_delete_all(clicon_handle h)
* @param[in] from From revision on the form YYYYMMDD (if DEL or CHANGE)
* @param[in] to To revision on the form YYYYMMDD (if ADD or CHANGE)
* @param[out] cbret Return XML (as string in CLIgen buffer), on invalid
- * @retval -1 Error
- * @retval 0 Invalid - cbret contains reason as netconf
* @retval 1 OK
+ * @retval 0 Invalid - cbret contains reason as netconf
+ * @retval -1 Error
* @see upgrade_callback_reg_fn which registers the callbacks
*/
int
diff --git a/lib/src/clixon_proto.c b/lib/src/clixon_proto.c
index ce987aec..a02f9b1f 100644
--- a/lib/src/clixon_proto.c
+++ b/lib/src/clixon_proto.c
@@ -433,6 +433,7 @@ clicon_msg_rcv(int s,
clicon_debug(CLIXON_DBG_MSG, "Recv: %s", (*msg)->op_body);
retval = 0;
done:
+ clicon_debug(CLIXON_DBG_DETAIL, "%s retval:%d", __FUNCTION__, retval);
if (0)
set_signal(SIGINT, oldhandler, NULL);
return retval;
@@ -643,6 +644,7 @@ clicon_rpc(int sock,
struct clicon_msg *reply = NULL;
char *data = NULL;
+ clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
if (clicon_msg_send(sock, msg) < 0)
goto done;
if (clicon_msg_rcv(sock, &reply, eof) < 0)
@@ -658,6 +660,7 @@ clicon_rpc(int sock,
ok:
retval = 0;
done:
+ clicon_debug(CLIXON_DBG_DETAIL, "%s retval:%d", __FUNCTION__, retval);
if (reply)
free(reply);
return retval;
diff --git a/lib/src/clixon_proto_client.c b/lib/src/clixon_proto_client.c
index d6180615..9348a6db 100644
--- a/lib/src/clixon_proto_client.c
+++ b/lib/src/clixon_proto_client.c
@@ -198,6 +198,7 @@ clicon_rpc_msg(clicon_handle h,
int s = -1;
int eof = 0;
+ clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
#ifdef RPC_USERNAME_ASSERT
assert(strstr(msg->op_body, "username")!=NULL); /* XXX */
#endif
@@ -245,6 +246,7 @@ clicon_rpc_msg(clicon_handle h,
}
retval = 0;
done:
+ clicon_debug(CLIXON_DBG_DETAIL, "%s %d", __FUNCTION__, retval);
if (retdata)
free(retdata);
if (xret)
@@ -961,6 +963,7 @@ clicon_rpc_get(clicon_handle h,
yang_stmt *yspec;
cvec *nscd = NULL;
+ clicon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__);
if (session_id_check(h, &session_id) < 0)
goto done;
if ((cb = cbuf_new()) == NULL){
@@ -1044,6 +1047,7 @@ clicon_rpc_get(clicon_handle h,
}
retval = 0;
done:
+ clicon_debug(CLIXON_DBG_DETAIL, "%s %d", __FUNCTION__, retval);
if (nscd)
cvec_free(nscd);
if (cb)
diff --git a/lib/src/clixon_xml_bind.c b/lib/src/clixon_xml_bind.c
index 3ff35f1f..fff0c56b 100644
--- a/lib/src/clixon_xml_bind.c
+++ b/lib/src/clixon_xml_bind.c
@@ -69,6 +69,8 @@
#include "clixon_options.h"
#include "clixon_data.h"
#include "clixon_yang_module.h"
+#include "clixon_yang_schema_mount.h"
+#include "clixon_plugin.h"
#include "clixon_xml_nsctx.h"
#include "clixon_xpath_ctx.h"
#include "clixon_xpath.h"
@@ -451,7 +453,34 @@ xml_bind_yang0_opt(clicon_handle h,
goto ok;
strip_body_objects(xt);
ybc = YB_PARENT;
+#ifdef YANG_SCHEMA_MOUNT // Maybe in populate?
+ yspec1 = NULL;
+ if ((ret = xml_yang_mount_get(xt, &yspec1)) < 0)
+ goto done;
+ if (ret == 0)
+ yspec1 = yspec;
+ else{
+ if (yspec1)
+ ybc = YB_MODULE;
+ else if (h == NULL)
+ goto ok; /* treat as anydata */
+ else{
+ if ((ret = yang_schema_yanglib_parse_mount(h, xt)) < 0)
+ goto done;
+ if (ret == 0)
+ goto ok;
+ /* Try again */
+ if ((ret = xml_yang_mount_get(xt, &yspec1)) < 0)
+ goto done;
+ if (yspec1)
+ ybc = YB_MODULE;
+ else
+ goto ok;
+ }
+ }
+#else
yspec1 = yspec;
+#endif
xc = NULL; /* Apply on children */
while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) {
/* It is xml2ns in populate_self_parent that needs improvement */
diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c
index e5a98c2c..dc4f5989 100644
--- a/lib/src/clixon_yang.c
+++ b/lib/src/clixon_yang.c
@@ -307,11 +307,10 @@ yang_cvec_set(yang_stmt *ys,
* @retval cv The new cligen variable
* @retval NULL Error
*/
-static cg_var *
+cg_var *
yang_cvec_add(yang_stmt *ys,
enum cv_type type,
char *name)
-
{
cg_var *cv;
cvec *cvv;
@@ -657,18 +656,27 @@ ys_free1(yang_stmt *ys,
cg_var *cv;
rpc_callback_t *rc;
- if (ys->ys_argument){
- free(ys->ys_argument);
- ys->ys_argument = NULL;
- }
if ((cv = yang_cv_get(ys)) != NULL){
yang_cv_set(ys, NULL); /* only frees on replace */
cv_free(cv);
}
if (ys->ys_cvec){
+#ifdef YANG_SCHEMA_MOUNT
+ /* Schema mount uses cvec in unknown to keep track of all yspecs
+ * Freed here once.
+ */
+ if (yang_keyword_get(ys) == Y_UNKNOWN &&
+ strcmp(yang_argument_get(ys), "yangmnt:mount-point")==0){
+ xml_yang_mount_freeall(ys->ys_cvec);
+ }
+#endif
cvec_free(ys->ys_cvec);
ys->ys_cvec = NULL;
}
+ if (ys->ys_argument){
+ free(ys->ys_argument);
+ ys->ys_argument = NULL;
+ }
if (ys->ys_typecache){
yang_type_cache_free(ys->ys_typecache);
ys->ys_typecache = NULL;
@@ -1131,16 +1139,7 @@ yang_find_datanode(yang_stmt *yn,
yang_stmt *yspec;
yang_stmt *ysmatch = NULL;
char *name;
-#ifdef YANG_SCHEMA_MOUNT
- int ret;
-
- /* Sanity-check mount-point extension */
- if ((ret = yang_schema_mount_point(yn)) < 0)
- goto done;
- if (ret == 1){
- ; // NYI
- }
-#endif
+
ys = NULL;
while ((ys = yn_each(yn, ys)) != NULL){
if (yang_keyword_get(ys) == Y_CHOICE){ /* Look for its children */
@@ -1904,7 +1903,7 @@ yang_spec_print(FILE *f,
fprintf(f, "%s", yang_key2str(ym->ys_keyword));
fprintf(f, " %s", ym->ys_argument);
if ((yrev = yang_find(ym, Y_REVISION, NULL)) != NULL){
- fprintf(f, "@%u", cv_uint32_get(yang_cv_get(yrev)));
+ fprintf(f, "@%s", yang_argument_get(yrev));
}
fprintf(f, ".yang");
fprintf(f, "\n");
@@ -2754,10 +2753,6 @@ ys_populate_unknown(clicon_handle h,
clicon_debug(1, "plugin_extension() failed");
return -1;
}
-#endif
-#ifdef YANG_SCHEMA_MOUNT
- if (yang_schema_unknown(h, yext, ys) < 0)
- goto done;
#endif
/* Make extension callbacks that may alter yang structure
* Note: this may be a "layering" violation: assuming plugins are loaded
diff --git a/lib/src/clixon_yang_internal.h b/lib/src/clixon_yang_internal.h
index a240df2f..ff809ccb 100644
--- a/lib/src/clixon_yang_internal.h
+++ b/lib/src/clixon_yang_internal.h
@@ -96,6 +96,7 @@ struct yang_stmt{
types as : list
Y_UNIQUE: vector of descendant schema node ids
Y_EXTENSION: vector of instantiated UNKNOWNSo
+ Y_UNKNOWN: app-dep: yang-mount-points
*/
yang_type_cache *ys_typecache; /* If ys_keyword==Y_TYPE, cache all typedef data except unions */
char *ys_when_xpath; /* Special conditional for a "when"-associated augment/uses xpath */
diff --git a/lib/src/clixon_yang_module.c b/lib/src/clixon_yang_module.c
index b55e0b3b..51c9b074 100644
--- a/lib/src/clixon_yang_module.c
+++ b/lib/src/clixon_yang_module.c
@@ -210,8 +210,10 @@ yang_modules_state_build(clicon_handle h,
yang_stmt *ysub;
char *name;
- if ((ylib = yang_find(yspec, Y_MODULE, module)) == NULL &&
- (ylib = yang_find(yspec, Y_SUBMODULE, module)) == NULL){
+ /* In case of several mountpoints, this is always the top-level */
+ if ((ylib = yang_find(yspec, Y_MODULE, module)) == NULL
+ /* && (ylib = yang_find(yspec0, Y_SUBMODULE, module)) == NULL */
+ ){
clicon_err(OE_YANG, 0, "%s not found", module);
goto done;
}
@@ -219,7 +221,6 @@ yang_modules_state_build(clicon_handle h,
clicon_err(OE_YANG, 0, "%s yang namespace not found", module);
goto done;
}
-
if (clicon_option_bool(h, "CLICON_MODULE_LIBRARY_RFC7895")){
cprintf(cb,"", yang_argument_get(yns));
cprintf(cb,"%s", msid);
@@ -671,7 +672,7 @@ yang_find_module_by_namespace_revision(yang_stmt *yspec,
* @note a module may have many revisions, but only the first is significant
*/
yang_stmt *
-yang_find_module_by_name_revision(yang_stmt *yspec,
+yang_find_module_by_name_revision(yang_stmt *yspec,
const char *name,
const char *rev)
{
@@ -824,3 +825,55 @@ yang_metadata_init(clicon_handle h)
done:
return retval;
}
+
+/*! Given a yang-lib module-set XML tree, parse all modules into an yspec
+ *
+ * This function is used where a yang-lib module-set is available to populate an
+ * XML mount-point.
+ * @param[in] h Clicon handle
+ * @param[in] xylib yang-lib XML tree on the form ...
+ * @param[in] yspec Will be populated with YANGs, is consumed
+ * @retval 1 OK
+ * @retval 0 Parse error
+ * @retval -1 Error
+ * @see xml_schema_add_mount_points
+ */
+int
+yang_lib2yspec(clicon_handle h,
+ cxobj *yanglib,
+ yang_stmt *yspec)
+{
+ int retval = -1;
+ cxobj *xi;
+ char *name;
+ char *revision;
+ cvec *nsc = NULL;
+ cxobj **vec = NULL;
+ size_t veclen;
+ int i;
+
+ if (xpath_vec(yanglib, nsc, "module-set/module", &vec, &veclen) < 0)
+ goto done;
+ for (i=0; i GROUPING id-arg-str ;"); }
+ | K_GROUPING identifier_str
{ if (ysp_add_push(_yy, Y_GROUPING, $2, NULL) == NULL) _YYERROR("grouping_stmt"); }
'{' grouping_substmts '}'
{ if (ystack_pop(_yy) < 0) _YYERROR("grouping_stmt");
- _PARSE_DEBUG("grouping-stmt -> GROUPING id-arg-str { grouping-substmts }"); }
+ _PARSE_DEBUG("grouping-stmt -> GROUPING id-arg-str { grouping-substmts }"); }
;
grouping_substmts : grouping_substmts grouping_substmt
diff --git a/lib/src/clixon_yang_schema_mount.c b/lib/src/clixon_yang_schema_mount.c
index e79f2ee8..5e95fdf1 100644
--- a/lib/src/clixon_yang_schema_mount.c
+++ b/lib/src/clixon_yang_schema_mount.c
@@ -32,6 +32,19 @@
***** END LICENSE BLOCK *****
* RFC 8525 Yang schema mount support
+ *
+ * Structure of mount-points in XML:
+ * YANG mount extentsion -->* YANG unknown mount stmt -->* XML mount-points
+ * |
+ * cvec mapping xpath->yspec mountpoint
+ *
+ * The calls into this code are:
+ * 1. yang_schema_mount_point() Check that a yang nod eis mount-point
+ * 2. xml_yang_mount_get(): from xml_bind_yang and xmldb_put
+ * 3. xml_yang_mount_freeall(): from ys_free1 when deallocatin YANG trees
+ * 4. yang_schema_mount_statedata(): from get_common/get_statedata to retrieve system state
+ * 5. yang_schema_yanglib_parse_mount(): from xml_bind_yang to parse and mount
+ * 6. yang_schema_get_child(): from xmldb_put/text_modify when adding new XML nodes
*/
#ifdef HAVE_CONFIG_H
@@ -43,6 +56,8 @@
#include
#include
#include
+#include
+#include
/* cligen */
#include
@@ -50,18 +65,25 @@
/* clixon */
#include "clixon_queue.h"
#include "clixon_hash.h"
+#include "clixon_string.h"
#include "clixon_handle.h"
#include "clixon_err.h"
#include "clixon_log.h"
#include "clixon_yang.h"
#include "clixon_xml.h"
#include "clixon_xml_io.h"
+#include "clixon_xml_map.h"
+#include "clixon_data.h"
+#include "clixon_xpath_ctx.h"
+#include "clixon_xpath.h"
#include "clixon_yang_module.h"
+#include "clixon_yang_parse_lib.h"
+#include "clixon_plugin.h"
+#include "clixon_xml_bind.h"
#include "clixon_netconf_lib.h"
-
#include "clixon_yang_schema_mount.h"
-/*! Check if y is a RFC 8525 YANG schema mount
+/*! Check if YANG node is a RFC 8525 YANG schema mount
*
* Check if:
* - y is CONTAINER or LIST, AND
@@ -87,7 +109,14 @@ yang_schema_mount_point(yang_stmt *y)
goto done;
}
keyw = yang_keyword_get(y);
- if (keyw != Y_CONTAINER && keyw != Y_LIST)
+ if (keyw != Y_CONTAINER
+#ifndef YANG_SCHEMA_MOUNT_ONLY_PRESENCE_CONTAINERS
+ && keyw != Y_LIST
+#endif
+#if 0 /* See this in some standard YANGs but RFC 8528 does not allow it */
+ && keyw != Y_ANYDATA
+#endif
+ )
goto fail;
if (yang_extension_value(y, "mount-point", YANG_SCHEMA_MOUNT_NAMESPACE, &exist, &value) < 0)
goto done;
@@ -103,6 +132,113 @@ yang_schema_mount_point(yang_stmt *y)
goto done;
}
+/*! Get yangspec mount-point
+ *
+ * @param[in] x XML moint-point node
+ * @param[out] yspec YANG stmt spec
+ * @retval 1 x is a mount-point: yspec may be set
+ * @retval 0 x is not a mount point
+ * @retval -1 Error
+ */
+int
+xml_yang_mount_get(cxobj *x,
+ yang_stmt **yspec)
+{
+ int retval = -1;
+ cvec *cvv = NULL;
+ cg_var *cv;
+ yang_stmt *y;
+ yang_stmt *yu;
+ char *xpath = NULL; // XXX free it
+ int ret;
+
+ if ((y = xml_spec(x)) == NULL)
+ goto fail;
+ if ((ret = yang_schema_mount_point(y)) < 0)
+ goto done;
+ if (ret == 0)
+ goto fail;
+ // XXX
+ if ((yu = yang_find(y, Y_UNKNOWN, "yangmnt:mount-point")) == NULL)
+ goto ok;
+ if (xml2xpath(x, NULL, &xpath) < 0)
+ goto done;
+ if ((cvv = yang_cvec_get(yu)) == NULL)
+ goto ok;
+ if ((cv = cvec_find(cvv, xpath)) == NULL)
+ goto ok;
+ if (yspec)
+ *yspec = cv_void_get(cv);
+ ok:
+ retval = 1;
+ done:
+ if (xpath)
+ free(xpath);
+ return retval;
+ fail:
+ retval = 0;
+ goto done;
+}
+
+/*! Set yangspec mount-point
+ *
+ * Stored in a separate structure (not in XML config tree)
+ * @param[in] x XML moint-point node
+ * @param[in] yspec Yangspec for this mount-point (consumed)
+ * @retval 0 OK
+ * @retval -1 Error
+ */
+int
+xml_yang_mount_set(cxobj *x,
+ yang_stmt *yspec)
+{
+ cg_var *cv;
+ yang_stmt *y;
+ yang_stmt *yu;
+ yang_stmt *yspec0;
+ char *xpath = NULL;
+ cvec *cvv;
+
+ if ((y = xml_spec(x)) == NULL ||
+ (yu = yang_find(y, Y_UNKNOWN, "yangmnt:mount-point")) == NULL){
+ goto done;
+ }
+ if (xml2xpath(x, NULL, &xpath) < 0)
+ goto done;
+ if ((cvv = yang_cvec_get(yu)) != NULL &&
+ (cv = cvec_find(cvv, xpath)) != NULL &&
+ (yspec0 = cv_void_get(cv)) != NULL){
+ assert(0);
+ ys_free(yspec0);
+ cv_void_set(cv, NULL);
+ }
+ else if ((cv = yang_cvec_add(yu, CGV_VOID, xpath)) == NULL)
+ return -1;
+ cv_void_set(cv, yspec);
+ done:
+ if (xpath)
+ free(xpath);
+ return 0;
+}
+
+/*! Free all yspec yang-mounts
+ * @aparm[in] cvv Cligen-variable vector containing xpath -> yspec mapping
+ */
+int
+xml_yang_mount_freeall(cvec *cvv)
+{
+ cg_var *cv = NULL;
+ yang_stmt *ys;
+
+ cv = NULL;
+ while ((cv = cvec_each(cvv, cv)) != NULL){
+ if ((ys = cv_void_get(cv)) != NULL)
+ ys_free(ys);
+ }
+ return 0;
+}
+
+
/*! Find schema mounts - callback function for xml_apply
*
* @param[in] x XML node
@@ -142,7 +278,6 @@ find_schema_mounts(cxobj *x,
* Brute force: traverse whole XML, match all x that have ymount as yspec
* Add yang-library state for all x
* @param[in] h Clicon handle
- * @param[in] yspec Yang spec
* @param[in] xpath XML Xpath
* @param[in] nsc XML Namespace context for xpath
* @param[in,out] xret Existing XML tree, merge x into this
@@ -159,20 +294,20 @@ find_schema_mounts(cxobj *x,
* Alt: see snmp_yang2xml to get instances instead of brute force traverse of whole tree
*/
static int
-schema_mounts_yang_library(clicon_handle h,
- yang_stmt *yspec,
- char *xpath,
- cvec *nsc,
- cxobj **xret,
- cxobj **xerr)
+yang_schema_mount_statedata_yanglib(clicon_handle h,
+ char *xpath,
+ cvec *nsc,
+ cxobj **xret,
+ cxobj **xerr)
{
- int retval = -1;
- cvec *cvv = NULL;
- cg_var *cv;
- cxobj *xmp; /* xml mount-point */
- cxobj *xylib = NULL; /* xml yang-lib */
- cbuf *cb = NULL;
- char *msid = "mount-point"; /* modules-set-id dummy */
+ int retval = -1;
+ cvec *cvv = NULL;
+ cg_var *cv;
+ cxobj *xmp; /* xml mount-point */
+ cxobj *yanglib = NULL; /* xml yang-lib */
+ cbuf *cb = NULL;
+ yang_stmt *yspec;
+ int ret;
if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, 0, "clicon buffer");
@@ -187,25 +322,21 @@ schema_mounts_yang_library(clicon_handle h,
cv = NULL;
while ((cv = cvec_each(cvv, cv)) != NULL) {
xmp = cv_void_get(cv);
- /* addsub here */
- cbuf_reset(cb);
- // XXX change yspec to mount-point
- /* Build a cb string: ... */
- if (yang_modules_state_build(h, yspec, msid, 0, cb) < 0)
+ yanglib = NULL;
+ /* User callback */
+ if (clixon_plugin_yang_mount_all(h, xmp, &yanglib) < 0)
goto done;
- /* Parse cb, x is on the form: ...
- * Note, list is not sorted since it is state (should not be)
- */
- if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, &xylib, NULL) < 0){
- if (xret && netconf_operation_failed_xml(xret, "protocol", clicon_err_reason)< 0)
- goto done;
+ if (yanglib == NULL)
+ continue;
+ yspec = clicon_dbspec_yang(h);
+ // if ((ret = xml_bind_yang(h, yanglib, YB_NONE, yspec, &xerr)) < 0)
+ if ((ret = xml_bind_yang0(h, yanglib, YB_MODULE, yspec, xerr)) < 0)
+ goto done;
+ if (ret == 0)
goto fail;
- }
- if (xml_rootchild(xylib, 0, &xylib) < 0)
+ if (xml_addsub(xmp, yanglib) < 0)
goto done;
- if (xml_addsub(xmp, xylib) < 0)
- goto done;
- xylib = NULL;
+ yanglib = NULL;
}
retval = 1;
done:
@@ -219,7 +350,7 @@ schema_mounts_yang_library(clicon_handle h,
goto done;
}
-/*! Get modules state according to RFC 8528
+/*! Get schema mount-point state according to RFC 8528
*
* @param[in] h Clicon handle
* @param[in] yspec Yang spec
@@ -233,12 +364,12 @@ schema_mounts_yang_library(clicon_handle h,
* @note Only "inline" specification of mounted schema supported, not "shared schema"
*/
int
-schema_mounts_state_get(clicon_handle h,
- yang_stmt *yspec,
- char *xpath,
- cvec *nsc,
- cxobj **xret,
- cxobj **xerr)
+yang_schema_mount_statedata(clicon_handle h,
+ yang_stmt *yspec,
+ char *xpath,
+ cvec *nsc,
+ cxobj **xret,
+ cxobj **xerr)
{
int retval = -1;
cbuf *cb = NULL;
@@ -291,7 +422,7 @@ schema_mounts_state_get(clicon_handle h,
goto fail;
}
/* Find mount-points and return yang-library state */
- if (0 && schema_mounts_yang_library(h, yspec, xpath, nsc, xret, xerr) < 0)
+ if (yang_schema_mount_statedata_yanglib(h, xpath, nsc, xret, xerr) < 0)
goto done;
ok:
retval = 1;
@@ -306,41 +437,85 @@ schema_mounts_state_get(clicon_handle h,
goto done;
}
-/*! Callback for yang schema mount-point extension
- *
- * @param[in] h Clixon handle
- * @param[in] yext Yang node of extension
- * @param[in] ys Yang node of (unknown) statement belonging to extension
- * @retval 0 OK
- * @retval -1 Error
- // XXX his may not even be necessary
+/*! Get yanglib, parse it and mount it
*/
int
-yang_schema_unknown(clicon_handle h,
- yang_stmt *yext,
- yang_stmt *ys)
+yang_schema_yanglib_parse_mount(clicon_handle h,
+ cxobj *xt)
+{
+ int retval = -1;
+ cxobj *yanglib = NULL;
+ yang_stmt *yspec = NULL;
+ int ret;
+
+ if (clixon_plugin_yang_mount_all(h, xt, &yanglib) < 0)
+ goto done;
+ if (yanglib == NULL)
+ goto anydata;
+ /* Parse it and set mount-point */
+ if ((yspec = yspec_new()) == NULL)
+ goto done;
+ if ((ret = yang_lib2yspec(h, yanglib, yspec)) < 0)
+ goto done;
+ if (ret == 0)
+ goto anydata;
+#ifdef YANG_SCHEMA_MOUNT_YANG_LIB_FORCE
+ /* XXX: Ensure yang-lib is always there otherwise get state dont work for mountpoint */
+ if (yang_spec_parse_module(h, "ietf-yang-library", "2019-01-04", yspec) < 0)
+ goto done;
+#endif
+ if (xml_yang_mount_set(xt, yspec) < 0)
+ goto done;
+ retval = 1;
+ done:
+ if (yspec)
+ ys_free(yspec);
+ if (yanglib)
+ xml_free(yanglib);
+ return retval;
+ anydata: // Treat as anydata
+ retval = 0;
+ goto done;
+}
+
+/*! Check if XML nod is mount-point and return matching YANG child
+ * @param[in] h Clicon handle
+ * @param[in] x1 XML node
+ * @param[in] x1c A child of x1
+ * @param[out] yc YANG child
+ * @retval 1 OK, yc contains child
+ * @retval 0 No such child
+ * @retval -1 Error
+ * XXX maybe not needed
+ */
+int
+yang_schema_get_child(clicon_handle h,
+ cxobj *x1,
+ cxobj *x1c,
+ yang_stmt **yc)
{
int retval = -1;
- char *extname;
- char *modname;
- yang_stmt *ymod;
- cg_var *cv;
- char *label;
+ yang_stmt *yspec1;
+ yang_stmt *ymod1 = NULL;
+ char *x1cname;
+ int ret;
- ymod = ys_module(yext);
- modname = yang_argument_get(ymod);
- extname = yang_argument_get(yext);
- if (strcmp(modname, "ietf-yang-schema-mount") != 0 || strcmp(extname, "mount-point") != 0)
- goto ok;
- if ((cv = yang_cv_get(ys)) == NULL){
- clicon_err(OE_YANG, 0, "mount-point extension must have label");
+ x1cname = xml_name(x1c);
+ if ((ret = xml_yang_mount_get(x1, &yspec1)) < 0)
goto done;
+ if (ret == 1 && yspec1 != NULL){
+ if (ys_module_by_xml(yspec1, x1c, &ymod1) <0)
+ goto done;
+ if (ymod1 != NULL)
+ *yc = yang_find_datanode(ymod1, x1cname);
+ else{ /* It is in fact a mountpoint, there is a yang mount, but it is not found */
+ goto fail;
+ }
}
- label = cv_string_get(cv);
- clicon_debug(1, "%s Enabled extension:%s:%s label:%s", __FUNCTION__, modname, extname, label);
- // XXX his may not even be necessary
- ok:
- retval = 0;
+ retval = 1;
done:
return retval;
+ fail:
+ retval = 0;
+ goto done;
}
diff --git a/test/test_yang_schema_mount.sh b/test/test_yang_schema_mount.sh
index 913102d8..d22a894b 100755
--- a/test/test_yang_schema_mount.sh
+++ b/test/test_yang_schema_mount.sh
@@ -11,7 +11,6 @@ if true; then # enable YANG_SCHEMA_MOUNT
if [ -z "${CLIXON_YANG_PATCH}" -a "$s" = $0 ]; then exit 0; else return 0; fi
fi
-
APPNAME=example
cfg=$dir/conf_mount.xml
@@ -33,6 +32,7 @@ cat < $cfg
$dir
true
true
+ true
EOF
@@ -45,13 +45,16 @@ module clixon-example{
prefix yangmnt;
}
container top{
- list root{
+ list mylist{
key name;
leaf name{
type string;
}
- yangmnt:mount-point "myroot"{
- description "Root for other yang models";
+ container root{
+ presence "Otherwise root is not visible";
+ yangmnt:mount-point "myroot"{
+ description "Root for other yang models";
+ }
}
}
}
@@ -73,19 +76,19 @@ fi
new "wait backend"
wait_backend
-new "Add two mountpoints: x and y"
-expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "xy" "" ""
+new "Add two mountpoints: x and y"
+expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "xy" "" ""
new "netconf commit"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" ""
new "Retrieve schema-mounts with Operation"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "clixon-exampletrue"
-if true; then
new "get yang-lib at mountpoint"
-expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" ">" "xy"
-fi
+# XXX maybe too many yangs here, difficult to maintain
+expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" ">" "x
+defaultclixon-autocli2022-02-11http://clicon.org/autocliclixon-example2022-11-01urn:example:clixonietf-datastores2018-02-14urn:ietf:params:xml:ns:yang:ietf-datastoresietf-inet-types2021-02-22urn:ietf:params:xml:ns:yang:ietf-inet-typesietf-yang-library2019-01-04urn:ietf:params:xml:ns:yang:ietf-yang-libraryietf-yang-types2013-07-15urn:ietf:params:xml:ns:yang:ietf-yang-typesmount-pointydefaultclixon-autocli2022-02-11http://clicon.org/autocliclixon-example2022-11-01urn:example:clixonietf-datastores2018-02-14urn:ietf:params:xml:ns:yang:ietf-datastoresietf-inet-types2021-02-22urn:ietf:params:xml:ns:yang:ietf-inet-typesietf-yang-library2019-01-04urn:ietf:params:xml:ns:yang:ietf-yang-libraryietf-yang-types2013-07-15urn:ietf:params:xml:ns:yang:ietf-yang-typesmount-point"
if [ $BE -ne 0 ]; then
new "Kill backend"
@@ -98,7 +101,6 @@ if [ $BE -ne 0 ]; then
stop_backend -f $cfg
fi
-
rm -rf $dir
new "endtest"