diff --git a/CHANGELOG.md b/CHANGELOG.md
index 76e06c37..2b9635e5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,10 +31,14 @@ Expected: May 2020
### API changes on existing protocol/config features (You may have have to change how you use Clixon)
+* xml-stats moved from clixon-config.yang as state data to an rpc `datastats`in clixon-lib.yang
* Stricter incoming RPC sanity checking, error messages may have changed.
### C-API changes on existing features (you may need to change your plugin C-code)
+* Two new plugin callbacks added
+ * ca_daemon: Called just after a server has "daemonized", ie put in background.
+ * ca_trans_commit_done: Called when all plugin commits have been done.
* Length of xml vector in many structs changed from `size_t` to `int`since it is a vector size, not byte size. This includes `transaction_data_t`
* `xml_merge()` changed to use 3-value return: 1:OK, 0:Yang failed, -1: Error
* `clixon_netconf_error(category, xerr, msg, arg)` removed first argument -> `clixon_netconf_error(xerr, msg, arg)`
diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c
index eda51dac..da322297 100644
--- a/apps/backend/backend_client.c
+++ b/apps/backend/backend_client.c
@@ -269,67 +269,26 @@ clixon_stats_get_db(clicon_handle h,
char *dbname,
cbuf *cb)
{
- int retval = -1;
- cxobj *xt = NULL;
- uint64_t nr = 0;
- size_t sz = 0;
- db_elmnt *de = NULL;
+ int retval = -1;
+ cxobj *xt = NULL;
+ uint64_t nr = 0;
+ size_t sz = 0;
+ db_elmnt *de = NULL;
/* This is the db cache */
- if ((de = clicon_db_elmnt_get(h, dbname)) != NULL)
- xt = de->de_xml;
- xml_stats(xt, &nr, &sz);
- cprintf(cb, "%s%" PRIu64 ""
- "%" PRIu64 "",
- dbname, nr, sz);
- retval = 0;
- return retval;
-}
-
-/*! Get clixon stats
- * @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
- * @retval 0 OK
- * @retval -1 Error
- */
-int
-clixon_stats_get(clicon_handle h,
- yang_stmt *yspec,
- char *xpath,
- cvec *nsc,
- cxobj **xret)
-{
- int retval = -1;
- cbuf *cb = NULL;
- uint64_t nr;
- int ret;
-
- if ((cb = cbuf_new()) == NULL){
- clicon_err(OE_UNIX, errno, "cbuf_new");
- goto done;
+ if ((de = clicon_db_elmnt_get(h, dbname)) == NULL ||
+ (xt = de->de_xml) == NULL){
+ cprintf(cb, "%s00", dbname);
}
- cprintf(cb, "", CLIXON_CONF_NS);
- nr=0;
- xml_stats_global(&nr);
- cprintf(cb, "%" PRIu64 "", nr);
- clixon_stats_get_db(h, "running", cb);
- clixon_stats_get_db(h, "candidate", cb);
- clixon_stats_get_db(h, "startup", cb);
- cprintf(cb, "");
- if ((ret = clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, NULL)) < 0)
- goto done;
- if (ret == 0){
- clicon_err(OE_XML, EINVAL, "Internal error");
- goto done;
+ else{
+ if (xml_stats(xt, &nr, &sz) < 0)
+ goto done;
+ cprintf(cb, "%s%" PRIu64 ""
+ "%" PRIu64 "",
+ dbname, nr, sz);
}
retval = 0;
done:
- clicon_debug(1, "%s %d", __FUNCTION__, retval);
- if (cb)
- cbuf_free(cb);
return retval;
}
@@ -408,11 +367,6 @@ client_statedata(clicon_handle h,
if (ret == 0)
goto fail;
}
- /* Clixon-config has a state data, if yang is present */
- if (yang_find(yspec, Y_MODULE, "clixon-config") != NULL){
- if (clixon_stats_get(h, yspec, xpath, nsc, xret) < 0)
- goto done;
- }
if ((ret = clixon_plugin_statedata(h, yspec, nsc, xpath, xret)) < 0)
goto done;
if (ret == 0)
@@ -1441,6 +1395,41 @@ from_client_ping(clicon_handle h,
return 0;
}
+/*! Check liveness of backend daemon, just send a reply
+ * @param[in] h Clicon handle
+ * @param[in] xe Request:
+ * @param[out] cbret Return xml tree, eg ..., ");
+ nr=0;
+ xml_stats_global(&nr);
+ cprintf(cbret, "%" PRIu64 "", nr);
+ if (clixon_stats_get_db(h, "running", cbret) < 0)
+ goto done;
+ if (clixon_stats_get_db(h, "candidate", cbret) < 0)
+ goto done;
+ if (clixon_stats_get_db(h, "startup", cbret) < 0)
+ goto done;
+ cprintf(cbret, "");
+ retval = 0;
+ done:
+ return retval;
+}
+
/*! Verify nacm user with peer uid credentials
* @param[in] mode Peer credential mode: none, exact or except
* @param[in] peername Peer username if any
@@ -1797,10 +1786,13 @@ backend_rpc_init(clicon_handle h)
goto done;
/* Clixon RPC */
if (rpc_callback_register(h, from_client_debug, NULL,
- "http://clicon.org/lib", "debug") < 0)
+ CLIXON_LIB_NS, "debug") < 0)
goto done;
if (rpc_callback_register(h, from_client_ping, NULL,
- "http://clicon.org/lib", "ping") < 0)
+ CLIXON_LIB_NS, "ping") < 0)
+ goto done;
+ if (rpc_callback_register(h, from_client_datastats, NULL,
+ CLIXON_LIB_NS, "datastats") < 0)
goto done;
retval =0;
done:
diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c
index 0d314bee..1de0a49d 100644
--- a/apps/backend/backend_commit.c
+++ b/apps/backend/backend_commit.c
@@ -349,6 +349,9 @@ startup_commit(clicon_handle h,
/* 8. Call plugin transaction commit callbacks */
if (plugin_transaction_commit(h, td) < 0)
goto done;
+ /* After commit, make a post-commit call (sure that all plugins have committed) */
+ if (plugin_transaction_commit_done(h, td) < 0)
+ goto done;
/* Clear cached trees from default values and marking */
if (xmldb_get0_clear(h, td->td_target) < 0)
goto done;
@@ -538,6 +541,9 @@ candidate_commit(clicon_handle h,
/* 7. Call plugin transaction commit callbacks */
if (plugin_transaction_commit(h, td) < 0)
goto done;
+ /* After commit, make a post-commit call (sure that all plugins have committed) */
+ if (plugin_transaction_commit_done(h, td) < 0)
+ goto done;
/* Clear cached trees from default values and marking */
if (xmldb_get0_clear(h, td->td_target) < 0)
diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c
index 6c016ca3..aa2b13bb 100644
--- a/apps/backend/backend_main.c
+++ b/apps/backend/backend_main.c
@@ -885,6 +885,10 @@ main(int argc,
}
}
+ /* Call plugin callbacks when in background and before dropped privileges */
+ if (clixon_plugin_daemon(h) < 0)
+ goto done;
+
/* Write pid-file */
if ((pid = pidfile_write(pidfile)) < 0)
goto done;
diff --git a/apps/backend/backend_plugin.c b/apps/backend/backend_plugin.c
index cea976ab..78002aaf 100644
--- a/apps/backend/backend_plugin.c
+++ b/apps/backend/backend_plugin.c
@@ -92,6 +92,32 @@ clixon_plugin_reset(clicon_handle h,
return retval;
}
+/*! Request plugins to reset system state
+ * The system 'state' should be the same as the contents of running_db
+ * @param[in] h Clicon handle
+ * @param[in] db Name of database
+ * @retval 0 OK
+ * @retval -1 Error
+ */
+int
+clixon_plugin_daemon(clicon_handle h)
+{
+ clixon_plugin *cp = NULL;
+ plgdaemon_t *daemonfn; /* Plugin auth */
+ int retval = 1;
+
+ while ((cp = clixon_plugin_each(h, cp)) != NULL) {
+ if ((daemonfn = cp->cp_api.ca_daemon) == NULL)
+ continue;
+ if ((retval = daemonfn(h)) < 0) {
+ clicon_debug(1, "plugin_daemon() failed");
+ return -1;
+ }
+ break;
+ }
+ return retval;
+}
+
/*! Go through all backend statedata callbacks and collect state data
* This is internal system call, plugin is invoked (does not call) this function
* Backend plugins can register
@@ -345,6 +371,36 @@ plugin_transaction_commit(clicon_handle h,
return retval;
}
+/*! Call transaction_commit_done callbacks in all backend plugins
+ * @param[in] h Clicon handle
+ * @param[in] td Transaction data
+ * @retval 0 OK
+ * @retval -1 Error: one of the plugin callbacks returned error
+ * @note no revert is done
+ */
+int
+plugin_transaction_commit_done(clicon_handle h,
+ transaction_data_t *td)
+{
+ int retval = 0;
+ clixon_plugin *cp = NULL;
+ trans_cb_t *fn;
+ int i=0;
+
+ while ((cp = clixon_plugin_each(h, cp)) != NULL) {
+ i++;
+ if ((fn = cp->cp_api.ca_trans_commit_done) == NULL)
+ continue;
+ if ((retval = fn(h, (transaction_data)td)) < 0){
+ if (!clicon_errno) /* sanity: log if clicon_err() is not called ! */
+ clicon_log(LOG_NOTICE, "%s: Plugin '%s' trans_commit_done callback does not make clicon_err call on error",
+ __FUNCTION__, cp->cp_name);
+ break;
+ }
+ }
+ return retval;
+}
+
/*! Call transaction_end() in all plugins after a successful commit.
* @param[in] h Clicon handle
* @param[in] td Transaction data
diff --git a/apps/backend/backend_plugin.h b/apps/backend/backend_plugin.h
index 5aea3d12..39e4e1ad 100644
--- a/apps/backend/backend_plugin.h
+++ b/apps/backend/backend_plugin.h
@@ -2,7 +2,9 @@
*
***** BEGIN LICENSE BLOCK *****
- Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
+ Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
+ Copyright (C) 2017-2019 Olof Hagsand
+ Copyright (C) 2020 Olof Hagsand and Rubicon Communications, LLC(Netgate)
This file is part of CLIXON.
@@ -69,6 +71,8 @@ typedef struct {
*/
int clixon_plugin_reset(clicon_handle h, char *db);
+int clixon_plugin_daemon(clicon_handle h);
+
int clixon_plugin_statedata(clicon_handle h, yang_stmt *yspec, cvec *nsc,
char *xpath, cxobj **xtop);
transaction_data_t * transaction_new(void);
@@ -78,6 +82,7 @@ int plugin_transaction_begin(clicon_handle h, transaction_data_t *td);
int plugin_transaction_validate(clicon_handle h, transaction_data_t *td);
int plugin_transaction_complete(clicon_handle h, transaction_data_t *td);
int plugin_transaction_commit(clicon_handle h, transaction_data_t *td);
+int plugin_transaction_commit_done(clicon_handle h, transaction_data_t *td);
int plugin_transaction_end(clicon_handle h, transaction_data_t *td);
int plugin_transaction_abort(clicon_handle h, transaction_data_t *td);
diff --git a/example/main/clixon-example@2020-03-11.yang b/example/main/clixon-example@2020-03-11.yang
index a4b0c23b..4d7f7fc2 100644
--- a/example/main/clixon-example@2020-03-11.yang
+++ b/example/main/clixon-example@2020-03-11.yang
@@ -26,6 +26,7 @@ module clixon-example {
import iana-if-type {
prefix ianaift;
}
+
/* Example interface type for tests, local callbacks, etc */
identity eth {
base if:interface-type;
@@ -33,7 +34,20 @@ module clixon-example {
identity loopback {
base if:interface-type;
}
- /* Translation function example - See also example_cli */
+ /* Generic config data */
+ container table{
+ list parameter{
+ key name;
+ leaf name{
+ type string;
+ }
+ leaf value{
+ type string;
+ }
+ }
+ }
+ /* Translation function example - See also example_cli
+ * XXX use table ^instead */
container translate{
description "dont have lists directly under top since restconf cant address list directly";
list translate{
diff --git a/lib/clixon/clixon_options.h b/lib/clixon/clixon_options.h
index bf19a169..671d0eb8 100644
--- a/lib/clixon/clixon_options.h
+++ b/lib/clixon/clixon_options.h
@@ -46,8 +46,10 @@
/*! Clixon configuration namespace
* Probably should be defined somewhere else or extracted from yang
* @see clixon-config.yang
+ * @see clixon-lib.yang
*/
#define CLIXON_CONF_NS "http://clicon.org/config"
+#define CLIXON_LIB_NS "http://clicon.org/lib"
/*
* Types
diff --git a/lib/clixon/clixon_plugin.h b/lib/clixon/clixon_plugin.h
index 97810cfb..1cc306a1 100644
--- a/lib/clixon/clixon_plugin.h
+++ b/lib/clixon/clixon_plugin.h
@@ -105,6 +105,12 @@ typedef int (*clicon_upgrade_cb)(
*/
typedef int (plgstart_t)(clicon_handle); /* Plugin start */
+/* Called just after a server has "daemonized", ie put in background.
+ * Backend: If daemon privileges are dropped this callback is called *before* privileges are dropped.
+ * If daemon is started in foreground (-F) it is still called.
+ */
+typedef int (plgdaemon_t)(clicon_handle); /* Plugin daemonized */
+
/* Called just before plugin unloaded.
*/
typedef int (plgexit_t)(clicon_handle); /* Plugin exit */
@@ -211,12 +217,14 @@ struct clixon_plugin_api{
struct { /* netconf-specific */
} cau_netconf;
struct { /* backend-specific */
+ plgdaemon_t *cb_daemon; /* Plugin daemonized */
plgreset_t *cb_reset; /* Reset system status */
plgstatedata_t *cb_statedata; /* Get state data from plugin (backend only) */
trans_cb_t *cb_trans_begin; /* Transaction start */
trans_cb_t *cb_trans_validate; /* Transaction validation */
trans_cb_t *cb_trans_complete; /* Transaction validation complete */
trans_cb_t *cb_trans_commit; /* Transaction commit */
+ trans_cb_t *cb_trans_commit_done; /* Transaction when commit done */
trans_cb_t *cb_trans_revert; /* Transaction revert */
trans_cb_t *cb_trans_end; /* Transaction completed */
trans_cb_t *cb_trans_abort; /* Transaction aborted */
@@ -229,12 +237,14 @@ struct clixon_plugin_api{
#define ca_suspend u.cau_cli.ci_suspend
#define ca_interrupt u.cau_cli.ci_interrupt
#define ca_auth u.cau_restconf.cr_auth
+#define ca_daemon u.cau_backend.cb_daemon
#define ca_reset u.cau_backend.cb_reset
#define ca_statedata u.cau_backend.cb_statedata
#define ca_trans_begin u.cau_backend.cb_trans_begin
#define ca_trans_validate u.cau_backend.cb_trans_validate
#define ca_trans_complete u.cau_backend.cb_trans_complete
#define ca_trans_commit u.cau_backend.cb_trans_commit
+#define ca_trans_commit_done u.cau_backend.cb_trans_commit_done
#define ca_trans_revert u.cau_backend.cb_trans_revert
#define ca_trans_end u.cau_backend.cb_trans_end
#define ca_trans_abort u.cau_backend.cb_trans_abort
diff --git a/lib/clixon/clixon_xml.h b/lib/clixon/clixon_xml.h
index 40950f91..590da2e1 100644
--- a/lib/clixon/clixon_xml.h
+++ b/lib/clixon/clixon_xml.h
@@ -154,7 +154,7 @@ typedef struct clixon_xml_vec clixon_xvec; /* struct defined in clicon_xml_vec.c
*/
char *xml_type2str(enum cxobj_type type);
int xml_stats_global(uint64_t *nr);
-size_t xml_stats(cxobj *xt, uint64_t *nrp, size_t *szp);
+int xml_stats(cxobj *xt, uint64_t *nrp, size_t *szp);
char *xml_name(cxobj *xn);
int xml_name_set(cxobj *xn, char *name);
char *xml_prefix(cxobj *xn);
diff --git a/lib/src/clixon_plugin.c b/lib/src/clixon_plugin.c
index 55f3a1f9..65259b27 100644
--- a/lib/src/clixon_plugin.c
+++ b/lib/src/clixon_plugin.c
@@ -471,7 +471,7 @@ clixon_plugin_extension(clicon_handle h,
return retval;
}
-/*! Call plugingeneral-purpose datastore upgrade in all plugins
+/*! Call plugin general-purpose datastore upgrade in all plugins
*
* @param[in] h Clicon handle
* @param[in] db Name of datastore, eg "running", "startup" or "tmp"
diff --git a/lib/src/clixon_proto_client.c b/lib/src/clixon_proto_client.c
index fcf9d2e4..428de77b 100644
--- a/lib/src/clixon_proto_client.c
+++ b/lib/src/clixon_proto_client.c
@@ -1011,7 +1011,10 @@ clicon_rpc_debug(clicon_handle h,
goto done;
username = clicon_username_get(h);
if ((msg = clicon_msg_encode(session_id,
- "%d", username?username:"", level)) == NULL)
+ "%d",
+ username?username:"",
+ CLIXON_LIB_NS,
+ level)) == NULL)
goto done;
if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
goto done;
diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c
index 73ce63c3..33faedda 100644
--- a/lib/src/clixon_xml.c
+++ b/lib/src/clixon_xml.c
@@ -284,18 +284,24 @@ xml_stats_one(cxobj *x,
}
/*! Return statistics of an XML tree recursively
- * @param[in] x XML object
+ * @param[in] xt XML object
* @param[out] szp Size of this XML obj recursively
* @retval 0 OK
+ * @retval -1 Error
*/
-size_t
+int
xml_stats(cxobj *xt,
uint64_t *nrp,
size_t *szp)
{
+ int retval = -1;
size_t sz = 0;
cxobj *xc;
+ if (xt == NULL){
+ clicon_err(OE_XML, EINVAL, "xml node is NULL");
+ goto done;
+ }
*nrp += 1;
xml_stats_one(xt, &sz);
if (szp)
@@ -308,7 +314,9 @@ xml_stats(cxobj *xt,
*szp += sz;
}
clicon_debug(1, "%s %zu", __FUNCTION__, *szp);
- return 0;
+ retval = 0;
+ done:
+ return retval;
}
/*
diff --git a/test/test_nacm_ext.sh b/test/test_nacm_ext.sh
index 564e26e6..512db9df 100755
--- a/test/test_nacm_ext.sh
+++ b/test/test_nacm_ext.sh
@@ -157,8 +157,7 @@ if [ $RC -ne 0 ]; then
fi
new "auth get"
-expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data)" 0 '{"data":{"clixon-example:state":{"op":["41","42","43"]}}}
-
'
+expectpart "$(curl -u andy:bar -siS -X GET http://localhost/restconf/data)" 0 'HTTP/1.1 200 OK' '{"data":{"clixon-example:state":{"op":\["41","42","43"\]}'
new "Set x to 0"
expecteq "$(curl -u andy:bar -sS -X PUT -H "Content-Type: application/yang-data+json" -d '{"nacm-example:x": 0}' http://localhost/restconf/data/nacm-example:x)" 0 ""
diff --git a/test/test_restconf.sh b/test/test_restconf.sh
index bfc97982..94d7ffc2 100755
--- a/test/test_restconf.sh
+++ b/test/test_restconf.sh
@@ -77,12 +77,11 @@ expecteq "$(curl -s -H 'Accept: application/yang-data+xml' -G http://localhost/r
# Should be alphabetically ordered
new "restconf get restconf/operations. RFC8040 3.3.2 (json)"
-expecteq "$(curl -sG http://localhost/restconf/operations)" 0 '{"operations":{"clixon-example:client-rpc":[null],"clixon-example:empty":[null],"clixon-example:optional":[null],"clixon-example:example":[null],"clixon-lib:debug":[null],"clixon-lib:ping":[null],"ietf-netconf:get-config":[null],"ietf-netconf:edit-config":[null],"ietf-netconf:copy-config":[null],"ietf-netconf:delete-config":[null],"ietf-netconf:lock":[null],"ietf-netconf:unlock":[null],"ietf-netconf:get":[null],"ietf-netconf:close-session":[null],"ietf-netconf:kill-session":[null],"ietf-netconf:commit":[null],"ietf-netconf:discard-changes":[null],"ietf-netconf:validate":[null],"clixon-rfc5277:create-subscription":[null]}}
-
'
+expectpart "$(curl -siG http://localhost/restconf/operations)" 0 'HTTP/1.1 200 OK' '{"operations":{"clixon-example:client-rpc":\[null\],"clixon-example:empty":\[null\],"clixon-example:optional":\[null\],"clixon-example:example":\[null\],"clixon-lib:debug":\[null\],"clixon-lib:ping":\[null\],"clixon-lib:datastats":\[null\],"ietf-netconf:get-config":\[null\],"ietf-netconf:edit-config":\[null\],"ietf-netconf:copy-config":\[null\],"ietf-netconf:delete-config":\[null\],"ietf-netconf:lock":\[null\],"ietf-netconf:unlock":\[null\],"ietf-netconf:get":\[null\],"ietf-netconf:close-session":\[null\],"ietf-netconf:kill-session":\[null\],"ietf-netconf:commit":\[null\],"ietf-netconf:discard-changes":\[null\],"ietf-netconf:validate":\[null\],"clixon-rfc5277:create-subscription":\[null\]}}'
new "restconf get restconf/operations. RFC8040 3.3.2 (xml)"
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/operations)
-expect=''
+expect=''
match=`echo $ret | grep --null -Eo "$expect"`
if [ -z "$match" ]; then
err "$expect" "$ret"
diff --git a/test/test_restconf_jukebox.sh b/test/test_restconf_jukebox.sh
index 773fdff8..ce9560d4 100755
--- a/test/test_restconf_jukebox.sh
+++ b/test/test_restconf_jukebox.sh
@@ -101,7 +101,7 @@ expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+xml' http://loca
# This just catches the header and the jukebox module, the RFC has foo and bar which
# seems wrong to recreate
new "B.1.2. Retrieve the Server Module Information"
-expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+json' http://localhost/restconf/data/ietf-yang-library:modules-state)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-lib","revision":"2019-08-13","namespace":"http://clicon.org/lib","conformance-type":"implement"},{"name":"clixon-rfc5277","revision":"2008-07-01","namespace":"urn:ietf:params:xml:ns:netmod:notification","conformance-type":"implement"},{"name":"example-events","revision":"","namespace":"urn:example:events","conformance-type":"implement"},{"name":"example-jukebox","revision":"2016-08-15","namespace":"http://example.com/ns/example-jukebox","conformance-type":"implement"},{"name":"example-system","revision":"","namespace":"http://example.com/ns/example-system","conformance-type":"implement"},{"name":"ietf-inet-types","revision":"2013-07-15","namespace":"urn:ietf:params:xml:ns:yang:ietf-inet-types","conformance-type":"implement"},'
+expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+json' http://localhost/restconf/data/ietf-yang-library:modules-state)" 0 "HTTP/1.1 200 OK" 'Cache-Control: no-cache' "Content-Type: application/yang-data+json" '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-lib","revision":"2020-04-23","namespace":"http://clicon.org/lib","conformance-type":"implement"},{"name":"clixon-rfc5277","revision":"2008-07-01","namespace":"urn:ietf:params:xml:ns:netmod:notification","conformance-type":"implement"},{"name":"example-events","revision":"","namespace":"urn:example:events","conformance-type":"implement"},{"name":"example-jukebox","revision":"2016-08-15","namespace":"http://example.com/ns/example-jukebox","conformance-type":"implement"},{"name":"example-system","revision":"","namespace":"http://example.com/ns/example-system","conformance-type":"implement"},{"name":"ietf-inet-types","revision":"2013-07-15","namespace":"urn:ietf:params:xml:ns:yang:ietf-inet-types","conformance-type":"implement"},'
new "B.1.3. Retrieve the Server Capability Information"
expectpart "$(curl -si -X GET -H 'Accept: application/yang-data+xml' http://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/capabilities)" 0 "HTTP/1.1 200 OK" "Content-Type: application/yang-data+xml" 'Cache-Control: no-cache' 'urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=expliciturn:ietf:params:restconf:capability:depth
diff --git a/test/test_submodule.sh b/test/test_submodule.sh
index 45c549a6..8350a6f5 100755
--- a/test/test_submodule.sh
+++ b/test/test_submodule.sh
@@ -205,16 +205,16 @@ expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^<
# Now same with restconf
new "restconf edit main"
-expectpart "$(curl -s -i -X POST -H "Content-Type: application/yang-data+json" http://localhost/restconf/data -d '{"main:main":{"x":"foo","ext":"foo"}}')" 0 'HTTP/1.1 201 Created'
+expectpart "$(curl -si -X POST -H "Content-Type: application/yang-data+json" http://localhost/restconf/data -d '{"main:main":{"x":"foo","ext":"foo"}}')" 0 'HTTP/1.1 201 Created'
new "restconf edit sub1"
-expectpart "$(curl -s -i -X POST -H "Content-Type: application/yang-data+json" http://localhost/restconf/data -d '{"main:sub1":{"x":"foo","ext1":"foo"}}')" 0 'HTTP/1.1 201 Created'
+expectpart "$(curl -si -X POST -H "Content-Type: application/yang-data+json" http://localhost/restconf/data -d '{"main:sub1":{"x":"foo","ext1":"foo"}}')" 0 'HTTP/1.1 201 Created'
new "restconf edit sub2"
-expectpart "$(curl -s -i -X POST -H "Content-Type: application/yang-data+json" http://localhost/restconf/data -d '{"main:sub2":{"x":"foo","ext2":"foo"}}')" 0 'HTTP/1.1 201 Created'
+expectpart "$(curl -si -X POST -H "Content-Type: application/yang-data+json" http://localhost/restconf/data -d '{"main:sub2":{"x":"foo","ext2":"foo"}}')" 0 'HTTP/1.1 201 Created'
new "restconf check main/sub1/sub2 contents"
-expectpart "$(curl -s -X GET http://localhost/restconf/data)" 0 '{"data":{"main:main":{"ext":"foo","x":"foo"},"main:sub1":{"ext1":"foo","x":"foo"},"main:sub2":{"ext2":"foo","x":"foo"}}}'
+expectpart "$(curl -si -X GET http://localhost/restconf/data?content=config)" 0 'HTTP/1.1 200 OK' '{"data":{"main:main":{"ext":"foo","x":"foo"},"main:sub1":{"ext1":"foo","x":"foo"},"main:sub2":{"ext2":"foo","x":"foo"}}}'
new "Kill restconf daemon"
stop_restconf
diff --git a/yang/clixon/Makefile.in b/yang/clixon/Makefile.in
index 17521441..188e22f8 100644
--- a/yang/clixon/Makefile.in
+++ b/yang/clixon/Makefile.in
@@ -1,8 +1,9 @@
#
# ***** BEGIN LICENSE BLOCK *****
#
-# Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
-#
+# Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
+# Copyright (C) 2017-2019 Olof Hagsand
+# Copyright (C) 2020 Olof Hagsand and Rubicon Communications, LLC(Netgate)#
# This file is part of CLIXON
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -42,7 +43,7 @@ datarootdir = @datarootdir@
YANG_INSTALLDIR = @YANG_INSTALLDIR@
YANGSPECS = clixon-config@2020-02-22.yang
-YANGSPECS += clixon-lib@2019-08-13.yang
+YANGSPECS += clixon-lib@2020-04-23.yang
YANGSPECS += clixon-rfc5277@2008-07-01.yang
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
diff --git a/yang/clixon/clixon-config@2020-02-22.yang b/yang/clixon/clixon-config@2020-02-22.yang
index aa08151f..0281ec10 100644
--- a/yang/clixon/clixon-config@2020-02-22.yang
+++ b/yang/clixon/clixon-config@2020-02-22.yang
@@ -40,6 +40,8 @@ module clixon-config {
***** END LICENSE BLOCK *****";
+ /* Deleted: clixon-stats state for clixon XML and memory statistics. (moved to clixon-lib)
+ */
revision 2020-02-22 {
description
"Added: search index extension,
@@ -718,33 +720,4 @@ module clixon-config {
}
}
- container clixon-stats{
- config false;
- description "Clixon backend statistics.";
- container global{
- description "Clixon global statistics";
- leaf xmlnr{
- description "Number of XML objects. That is number of residing xml/json objects
- in the internal 'cxobj' representation.";
- type uint64;
- }
- }
- list datastore{
- description "Datastore statistics";
- key "name";
- leaf name{
- description "name of datastore (eg running).";
- type string;
- }
- leaf nr{
- description "Number of XML objects. That is number of residing xml/json objects
- in the internal 'cxobj' representation.";
- type uint64;
- }
- leaf size{
- description "Size in bytes of internal datastore cache of datastore tree.";
- type uint64;
- }
- }
- }
}
diff --git a/yang/clixon/clixon-lib@2020-04-23.yang b/yang/clixon/clixon-lib@2020-04-23.yang
new file mode 100644
index 00000000..19e43fc7
--- /dev/null
+++ b/yang/clixon/clixon-lib@2020-04-23.yang
@@ -0,0 +1,102 @@
+module clixon-lib {
+ yang-version 1.1;
+ namespace "http://clicon.org/lib";
+ prefix cl;
+
+ organization
+ "Clicon / Clixon";
+
+ contact
+ "Olof Hagsand ";
+
+ description
+ "Clixon Netconf extensions for communication between clients and backend.
+
+ ***** BEGIN LICENSE BLOCK *****
+ Copyright (C) 2009-2019 Olof Hagsand
+ Copyright (C) 2020 Olof Hagsand and Rubicon Communications, LLC(Netgate)
+
+ This file is part of CLIXON
+
+ Licensed under the Apache License, Version 2.0 (the \"License\");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an \"AS IS\" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ Alternatively, the contents of this file may be used under the terms of
+ the GNU General Public License Version 3 or later (the \"GPL\"),
+ in which case the provisions of the GPL are applicable instead
+ of those above. If you wish to allow use of your version of this file only
+ under the terms of the GPL, and not to allow others to
+ use your version of this file under the terms of Apache License version 2,
+ indicate your decision by deleting the provisions above and replace them with
+ the notice and other provisions required by the GPL. If you do not delete
+ the provisions above, a recipient may use your version of this file under
+ the terms of any one of the Apache License version 2 or the GPL.
+
+ ***** END LICENSE BLOCK *****";
+
+ revision 2020-04-23 {
+ description
+ "Added: clixon-stats state for clixon XML and memory statistics.";
+ }
+ revision 2019-08-13 {
+ description
+ "No changes (reverted change)";
+ }
+ revision 2019-06-05 {
+ description
+ "ping rpc added for liveness";
+ }
+ revision 2019-01-02 {
+ description
+ "Released in Clixon 3.9";
+ }
+ rpc debug {
+ description "Set debug level of backend.";
+ input {
+ leaf level {
+ type uint32;
+ }
+ }
+ }
+ rpc ping {
+ description "Check aliveness of backend daemon.";
+ }
+ rpc datastats {
+ description "Clixon XML statistics.";
+ output {
+ container global{
+ description "Clixon global statistics";
+ leaf xmlnr{
+ description "Number of XML objects. That is number of residing xml/json objects
+ in the internal 'cxobj' representation.";
+ type uint64;
+ }
+ }
+ list datastore{
+ description "Datastore statistics";
+ key "name";
+ leaf name{
+ description "name of datastore (eg running).";
+ type string;
+ }
+ leaf nr{
+ description "Number of XML objects. That is number of residing xml/json objects
+ in the internal 'cxobj' representation.";
+ type uint64;
+ }
+ leaf size{
+ description "Size in bytes of internal datastore cache of datastore tree.";
+ type uint64;
+ }
+ }
+
+ }
+ }
+}