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; + } + } + + } + } +}