* Pushed tag to 4.0.1.PRE
* Restconf RFC 8040 increased feature compliance
* Cache-Control: no-cache added in HTTP responses (RFC Section 5.5)
* Restconf monitoring capabilities (RFC Section 9.1)
* Added support for Yang extensions
* New plugin callback: ca_extension
* Main backend example includes example code on how to implement a Yang extension in a plugin.
* JSON changes
* Non-pretty-print output removed all extra spaces.
* Example: `{"nacm-example:x": 42}` --> {"nacm-example:x":42}`
* Empty JSON container changed from `null` to `{}`.
* Empty list and leafs remain as `null`
* Removed unnecessary configure dependencies
* libnsl, libcrypt, libm, if_vlan,...
* pseudo-plugin added, to enable callbacks also for main programs. Useful for extensions
* Yang Unique statements with multiple schema identifiers did not work on some platforms due to memory error.
This commit is contained in:
parent
fe46a0e093
commit
e7b60619da
60 changed files with 1619 additions and 568 deletions
|
|
@ -61,7 +61,7 @@ CLIXON_LIB = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR).$(CLIXON_MINOR)
|
|||
# even though it may exist in $(libdir). But the new version may not have been installed yet.
|
||||
LIBDEPS = $(top_srcdir)/lib/src/$(CLIXON_LIB)
|
||||
|
||||
LIBS = -L$(top_srcdir)/lib/src @LIBS@ $(top_srcdir)/lib/src/$(CLIXON_LIB) -lpthread
|
||||
LIBS = -L$(top_srcdir)/lib/src @LIBS@ $(top_srcdir)/lib/src/$(CLIXON_LIB)
|
||||
CPPFLAGS = @CPPFLAGS@ -fPIC
|
||||
INCLUDES = -I. -I$(top_srcdir)/lib/src -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir) @INCLUDES@
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,37 @@ backend_client_rm(clicon_handle h,
|
|||
return backend_client_delete(h, ce); /* actually purge it */
|
||||
}
|
||||
|
||||
/*!
|
||||
* Maybe should be in the restconf client instead of backend?
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] yspec Yang spec
|
||||
* @param[in] xpath Xpath selection, not used but may be to filter early
|
||||
* @param[out] xrs XML restconf-state node
|
||||
* @see netconf_create_hello
|
||||
* @see rfc8040 Sections 9.1
|
||||
*/
|
||||
static int
|
||||
client_get_capabilities(clicon_handle h,
|
||||
yang_stmt *yspec,
|
||||
char *xpath,
|
||||
cxobj **xret)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xrstate = NULL; /* xml restconf-state node */
|
||||
cxobj *xcap = NULL; /* xml capabilities node */
|
||||
|
||||
if ((xrstate = xpath_first(*xret, "restconf-state")) == NULL){
|
||||
clicon_err(OE_YANG, ENOENT, "restconf-state not found in config node");
|
||||
goto done;
|
||||
}
|
||||
if ((xcap = xml_new("capabilities", xrstate, yspec)) == NULL)
|
||||
goto done;
|
||||
if (xml_parse_va(&xcap, yspec, "<capability>urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=explicit</capability>") < 0)
|
||||
goto done;
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Get streams state according to RFC 8040 or RFC5277 common function
|
||||
* @param[in] h Clicon handle
|
||||
|
|
@ -165,23 +196,18 @@ static int
|
|||
client_get_streams(clicon_handle h,
|
||||
yang_stmt *yspec,
|
||||
char *xpath,
|
||||
char *module,
|
||||
yang_stmt *ymod,
|
||||
char *top,
|
||||
cxobj **xret)
|
||||
{
|
||||
int retval = -1;
|
||||
yang_stmt *ystream = NULL; /* yang stream module */
|
||||
yang_stmt *yns = NULL; /* yang namespace */
|
||||
cxobj *x = NULL;
|
||||
cbuf *cb = NULL;
|
||||
int ret;
|
||||
|
||||
if ((ystream = yang_find(yspec, Y_MODULE, module)) == NULL){
|
||||
clicon_err(OE_YANG, 0, "%s yang module not found", module);
|
||||
goto done;
|
||||
}
|
||||
if ((yns = yang_find(ystream, Y_NAMESPACE, NULL)) == NULL){
|
||||
clicon_err(OE_YANG, 0, "%s yang namespace not found", module);
|
||||
if ((yns = yang_find(ymod, Y_NAMESPACE, NULL)) == NULL){
|
||||
clicon_err(OE_YANG, 0, "%s yang namespace not found", yang_argument_get(ymod));
|
||||
goto done;
|
||||
}
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
|
|
@ -189,6 +215,9 @@ client_get_streams(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
cprintf(cb,"<%s xmlns=\"%s\">", top, yang_argument_get(yns));
|
||||
/* Second argument is a hack to have the same function for the
|
||||
* RFC5277 and 8040 stream cases
|
||||
*/
|
||||
if (stream_get_xml(h, strcmp(top,"restconf-state")==0, cb) < 0)
|
||||
goto done;
|
||||
cprintf(cb,"</%s>", top);
|
||||
|
|
@ -234,23 +263,47 @@ client_statedata(clicon_handle h,
|
|||
size_t xlen;
|
||||
int i;
|
||||
yang_stmt *yspec;
|
||||
yang_stmt *ymod;
|
||||
int ret;
|
||||
char *namespace;
|
||||
|
||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
||||
clicon_err(OE_YANG, ENOENT, "No yang spec");
|
||||
goto done;
|
||||
}
|
||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277")){
|
||||
if ((ret = client_get_streams(h, yspec, xpath, "clixon-rfc5277", "netconf", xret)) < 0)
|
||||
if ((ymod = yang_find_module_by_name(yspec, "clixon-rfc5277")) == NULL){
|
||||
clicon_err(OE_YANG, ENOENT, "yang module clixon-rfc5277 not found");
|
||||
goto done;
|
||||
}
|
||||
if ((namespace = yang_find_mynamespace(ymod)) == NULL){
|
||||
clicon_err(OE_YANG, ENOENT, "clixon-rfc5277 namespace not found");
|
||||
goto done;
|
||||
}
|
||||
if (xml_parse_va(xret, yspec, "<netconf xmlns=\"%s\"/>", namespace) < 0)
|
||||
goto done;
|
||||
if ((ret = client_get_streams(h, yspec, xpath, ymod, "netconf", xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
}
|
||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040")){
|
||||
if ((ret = client_get_streams(h, yspec, xpath, "ietf-restconf-monitoring", "restconf-state", xret)) < 0)
|
||||
if ((ymod = yang_find_module_by_name(yspec, "ietf-restconf-monitoring")) == NULL){
|
||||
clicon_err(OE_YANG, ENOENT, "yang module ietf-restconf-monitoring not found");
|
||||
goto done;
|
||||
}
|
||||
if ((namespace = yang_find_mynamespace(ymod)) == NULL){
|
||||
clicon_err(OE_YANG, ENOENT, "ietf-restconf-monitoring namespace not found");
|
||||
goto done;
|
||||
}
|
||||
if (xml_parse_va(xret, yspec, "<restconf-state xmlns=\"%s\"/>", namespace) < 0)
|
||||
goto done;
|
||||
if ((ret = client_get_streams(h, yspec, xpath, ymod, "restconf-state", xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
if ((ret = client_get_capabilities(h, yspec, xpath, xret)) < 0)
|
||||
goto done;
|
||||
}
|
||||
if (clicon_option_bool(h, "CLICON_MODULE_LIBRARY_RFC7895")){
|
||||
if ((ret = yang_modules_state_get(h, yspec, xpath, nsc, 0, xret)) < 0)
|
||||
|
|
|
|||
|
|
@ -332,6 +332,7 @@ main(int argc,
|
|||
cbuf *cbret = NULL; /* startup cbuf if invalid */
|
||||
enum startup_status status = STARTUP_ERR; /* Startup status */
|
||||
int ret;
|
||||
char *dir;
|
||||
|
||||
/* In the startup, logs to stderr & syslog and debug flag set later */
|
||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||
|
|
@ -573,6 +574,13 @@ main(int argc,
|
|||
if ((yspec = yspec_new()) == NULL)
|
||||
goto done;
|
||||
clicon_dbspec_yang_set(h, yspec);
|
||||
|
||||
/* Load backend plugins before yangs are loaded (eg extension callbacks) */
|
||||
if ((dir = clicon_backend_dir(h)) != NULL &&
|
||||
clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir,
|
||||
clicon_option_str(h, "CLICON_BACKEND_REGEXP")) < 0)
|
||||
goto done;
|
||||
|
||||
/* Load Yang modules
|
||||
* 1. Load a yang module as a specific absolute filename */
|
||||
if ((str = clicon_yang_main_file(h)) != NULL)
|
||||
|
|
@ -596,6 +604,9 @@ main(int argc,
|
|||
/* Add netconf yang spec, used by netconf client and as internal protocol */
|
||||
if (netconf_module_load(h) < 0)
|
||||
goto done;
|
||||
/* Load yang restconf module */
|
||||
if (yang_spec_parse_module(h, "ietf-restconf", NULL, yspec)< 0)
|
||||
goto done;
|
||||
/* Load yang Restconf stream discovery */
|
||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
|
||||
yang_spec_parse_module(h, "ietf-restconf-monitoring", NULL, yspec)< 0)
|
||||
|
|
@ -646,8 +657,6 @@ main(int argc,
|
|||
goto done;
|
||||
case SM_NONE: /* Fall through *
|
||||
* Load plugins and call plugin_init() */
|
||||
if (backend_plugin_initiate(h) != 0)
|
||||
goto done;
|
||||
status = STARTUP_OK;
|
||||
break;
|
||||
case SM_RUNNING: /* Use running as startup */
|
||||
|
|
@ -735,7 +744,6 @@ main(int argc,
|
|||
clicon_err(OE_DEMON, errno, "Setting signal");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Initialize server socket and save it to handle */
|
||||
if ((ss = backend_server_socket(h)) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -63,23 +63,6 @@
|
|||
#include "backend_plugin.h"
|
||||
#include "backend_commit.h"
|
||||
|
||||
/*! Load a plugin group.
|
||||
* @param[in] h Clicon handle
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
*/
|
||||
int
|
||||
backend_plugin_initiate(clicon_handle h)
|
||||
{
|
||||
char *dir;
|
||||
|
||||
/* Load application plugins */
|
||||
if ((dir = clicon_backend_dir(h)) == NULL)
|
||||
return 0;
|
||||
return clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir,
|
||||
clicon_option_str(h, "CLICON_BACKEND_REGEXP"));
|
||||
}
|
||||
|
||||
/*! Request plugins to reset system state
|
||||
* The system 'state' should be the same as the contents of running_db
|
||||
* @param[in] h Clicon handle
|
||||
|
|
|
|||
|
|
@ -67,8 +67,6 @@ typedef struct {
|
|||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
int backend_plugin_initiate(clicon_handle h);
|
||||
|
||||
int clixon_plugin_reset(clicon_handle h, char *db);
|
||||
|
||||
int clixon_plugin_statedata(clicon_handle h, yang_stmt *yspec, cvec *nsc,
|
||||
|
|
|
|||
|
|
@ -138,9 +138,6 @@ startup_mode_startup(clicon_handle h,
|
|||
clicon_err(OE_FATAL, 0, "Invalid startup db: %s", db);
|
||||
goto done;
|
||||
}
|
||||
/* Load plugins and call plugin_init() */
|
||||
if (backend_plugin_initiate(h) != 0)
|
||||
goto done;
|
||||
/* If startup does not exist, create it empty */
|
||||
if (xmldb_exists(h, db) != 1){ /* diff */
|
||||
if (xmldb_create(h, db) < 0) /* diff */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue