diff --git a/CHANGELOG.md b/CHANGELOG.md
index dafd1c16..e435e252 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,11 +39,23 @@ Developers may need to change their code
Users may have to change how they access the system
+* New clixon-lib@2020-12-30.yang revision
+ * Changed: RPC process-control output parameter status to pid
+* New clixon-config@2020-12-30.yang revision
+ * Removed obsolete RESTCONF and SSL options
+* Changed namespace of clixon-restconf@2020-10-30.yang from https://clicon.org/restconf ->http://clicon.org/restconf ->
* CLIspec dbxml API: Ability to specify deletion of _any_ vs _specific_ entry.
* In a cli_del() call, the cvv arg list either exactly matches the api-format-path in which case _any_ deletion is specified, otherwise, if there is an extra element in the cvv list, that is used for a specific delete.
### Minor changes
+* Added callback to process-control RPC feature in clixon-lib.yang to manage processes
+ * WHen an RPC comes in, be able to look at configuration
+* Changed behavior of starting restconf internally using `CLICON_BACKEND_RESTCONF_PROCESS` monitoring changes in enable flag, not only the RPC. The semantics is as follows:
+ * on RPC start, if enable is true, start the service, if false, error or ignore it
+ * on RPC stop, stop the service
+ * on backend start make the state as configured
+ * on enable change, make the state as configured
* Limited fuzz by AFL committed,
* see [fuzz/README.md](fuzz/README.md) for details
diff --git a/LICENSE.md b/LICENSE.md
index ae31e385..455bac51 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,6 @@
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)
+Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC (Netgate)
CLIXON is dual license.
diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c
index 9cef1b8f..f1926d54 100644
--- a/apps/backend/backend_client.c
+++ b/apps/backend/backend_client.c
@@ -1580,23 +1580,18 @@ from_client_process_control(clicon_handle h,
cxobj *x;
char *name = NULL;
char *operation = NULL;
- int status = 0;
+ uint32_t pid = 0;
clicon_debug(1, "%s", __FUNCTION__);
if ((x = xml_find_type(xe, NULL, "name", CX_ELMNT)) != NULL)
name = xml_body(x);
if ((x = xml_find_type(xe, NULL, "operation", CX_ELMNT)) != NULL)
operation = xml_body(x);
- /* Make the actual process operation */
- if (clixon_process_operation(h, name, operation, &status) < 0)
+ /* Make the actual process operation (with wrap function enabled) */
+ if (clixon_process_operation(h, name, operation, 1, &pid) < 0)
goto done;
- if (strcmp(operation, "status") == 0)
- cprintf(cbret, "%s",
- NETCONF_BASE_NAMESPACE,
- CLIXON_LIB_NS,
- status?"true":"false");
- else
- cprintf(cbret, "", NETCONF_BASE_NAMESPACE);
+ cprintf(cbret, "%u",
+ NETCONF_BASE_NAMESPACE, CLIXON_LIB_NS, pid);
retval = 0;
done:
return retval;
@@ -1633,7 +1628,6 @@ from_client_hello(clicon_handle h,
return retval;
}
-
/*! An internal clicon message has arrived from a client. Receive and dispatch.
* @param[in] h Clicon handle
* @param[in] s Socket where message arrived. read from this.
diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c
index 025e803f..1b3c24ac 100644
--- a/apps/backend/backend_main.c
+++ b/apps/backend/backend_main.c
@@ -60,6 +60,7 @@
#include
#include
#include
+#include
/* cligen */
#include
@@ -67,7 +68,7 @@
/* clicon */
#include
-#include "clixon_backend_handle.h"
+#include "clixon_backend_transaction.h"
#include "backend_socket.h"
#include "backend_client.h"
#include "backend_plugin.h"
@@ -178,50 +179,6 @@ backend_server_socket(clicon_handle h)
return ss;
}
-/*! Enable process-control of restconf daemon, ie start/stop restconf
- * @param[in] h Clicon handle
- * @note Could also look in clixon-restconf and start process if enable is true, but that needs to
- * be in start callback using a pseudo plugin.
- */
-static int
-backend_restconf_process_control(clicon_handle h)
-{
- int retval = -1;
- char **argv = NULL;
- int i;
- int nr;
- char dbgstr[8];
- char wwwstr[64];
-
- nr = 4;
- if (clicon_debug_get() != 0)
- nr += 2;
- if ((argv = calloc(nr, sizeof(char *))) == NULL){
- clicon_err(OE_UNIX, errno, "calloc");
- goto done;
- }
- i = 0;
- snprintf(wwwstr, sizeof(wwwstr)-1, "%s/clixon_restconf", clicon_option_str(h, "CLICON_WWWDIR"));
- argv[i++] = wwwstr;
- argv[i++] = "-f";
- argv[i++] = clicon_option_str(h, "CLICON_CONFIGFILE");
- if (clicon_debug_get() != 0){
- argv[i++] = "-D";
- snprintf(dbgstr, sizeof(dbgstr)-1, "%d", clicon_debug_get());
- argv[i++] = dbgstr;
- }
- argv[i++] = NULL;
- if (clixon_process_register(h, "restconf",
- NULL /* XXX network namespace */,
- argv, nr) < 0)
- goto done;
- if (argv != NULL)
- free(argv);
- retval = 0;
- done:
- return retval;
-}
-
/*! Load external NACM file
*/
static int
@@ -431,6 +388,140 @@ ret2status(int ret,
return retval;
}
+/*---------------------------------------------------------------------
+ * Restconf process pseudo plugin
+ */
+
+#define RESTCONF_PROCESS "restconf"
+
+/*! Process rpc callback function
+ * - if RPC op is start, if enable is true, start the service, if false, error or ignore it
+ * - if RPC op is stop, stop the service
+ * These rules give that if RPC op is start and enable is false -> change op to none
+ */
+int
+restconf_rpc_wrapper(clicon_handle h,
+ process_entry_t *pe,
+ char **operation)
+{
+ int retval = -1;
+ cxobj *xt = NULL;
+
+ clicon_debug(1, "%s", __FUNCTION__);
+ if (strcmp(*operation, "stop") == 0){
+ /* if RPC op is stop, stop the service */
+ }
+ else if (strcmp(*operation, "start") == 0){
+ /* RPC op is start & enable is true, then start the service,
+ & enable is false, error or ignore it */
+ if (xmldb_get(h, "running", NULL, "/restconf", &xt) < 0)
+ goto done;
+ if (xt != NULL &&
+ xpath_first(xt, NULL, "/restconf[enable='false']") != NULL) {
+ *operation = "none";
+ }
+ }
+ retval = 0;
+ done:
+ if (xt)
+ xml_free(xt);
+ return retval;
+}
+
+/*! Enable process-control of restconf daemon, ie start/stop restconf by registering restconf process
+ * @param[in] h Clicon handle
+ * @note Could also look in clixon-restconf and start process if enable is true, but that needs to
+ * be in start callback using a pseudo plugin.
+ */
+static int
+restconf_pseudo_process_control(clicon_handle h)
+{
+ int retval = -1;
+ char **argv = NULL;
+ int i;
+ int nr;
+ char dbgstr[8];
+ char wwwstr[64];
+
+ nr = 4;
+ if (clicon_debug_get() != 0)
+ nr += 2;
+ if ((argv = calloc(nr, sizeof(char *))) == NULL){
+ clicon_err(OE_UNIX, errno, "calloc");
+ goto done;
+ }
+ i = 0;
+ snprintf(wwwstr, sizeof(wwwstr)-1, "%s/clixon_restconf", clicon_option_str(h, "CLICON_WWWDIR"));
+ argv[i++] = wwwstr;
+ argv[i++] = "-f";
+ argv[i++] = clicon_option_str(h, "CLICON_CONFIGFILE");
+ if (clicon_debug_get() != 0){
+ argv[i++] = "-D";
+ snprintf(dbgstr, sizeof(dbgstr)-1, "%d", clicon_debug_get());
+ argv[i++] = dbgstr;
+ }
+ argv[i++] = NULL;
+ assert(i==nr);
+ if (clixon_process_register(h, RESTCONF_PROCESS,
+ NULL /* XXX network namespace */,
+ restconf_rpc_wrapper,
+ argv, nr) < 0)
+ goto done;
+ if (argv != NULL)
+ free(argv);
+ retval = 0;
+ done:
+ return retval;
+}
+
+/*! Restconf pseduo-plugin process commit
+ */
+static int
+restconf_pseudo_process_commit(clicon_handle h,
+ transaction_data td)
+{
+ int retval = -1;
+ cxobj *xtarget;
+ cxobj *cx;
+ int enabled = 0;
+
+ clicon_debug(1, "%s", __FUNCTION__);
+ xtarget = transaction_target(td);
+ if (xpath_first(xtarget, NULL, "/restconf[enable='true']") != NULL)
+ enabled++;
+ if ((cx = xpath_first(xtarget, NULL, "/restconf/enable")) != NULL &&
+ xml_flag(cx, XML_FLAG_CHANGE|XML_FLAG_ADD)){
+ if (clixon_process_operation(h, RESTCONF_PROCESS,
+ enabled?"start":"stop", 0, NULL) < 0)
+ goto done;
+ }
+ retval = 0;
+ done:
+ return retval;
+}
+
+/*! Register start/stop restconf RPC and create pseudo-plugin to monitor enable flag
+ * @param[in] h Clixon handle
+ */
+static int
+restconf_pseudo_process_reg(clicon_handle h,
+ yang_stmt *yspec)
+{
+ int retval = -1;
+ clixon_plugin *cp = NULL;
+
+ if (clixon_pseudo_plugin(h, "restconf pseudo plugin", &cp) < 0)
+ goto done;
+ cp->cp_api.ca_trans_commit = restconf_pseudo_process_commit;
+
+ /* Register generic process-control of restconf daemon, ie start/stop restconf */
+ if (restconf_pseudo_process_control(h) < 0)
+ goto done;
+ retval = 0;
+ done:
+ return retval;
+}
+
/*! usage
*/
static void
@@ -789,12 +880,6 @@ main(int argc,
clicon_option_str(h, "CLICON_BACKEND_REGEXP")) < 0)
goto done;
- /* Enable process-control of restconf daemon, ie start/stop restconf */
- if (clicon_option_bool(h, "CLICON_BACKEND_RESTCONF_PROCESS")){
- if (backend_restconf_process_control(h) < 0)
- goto done;
- }
-
/* Load Yang modules
* 1. Load a yang module as a specific absolute filename */
if ((str = clicon_yang_main_file(h)) != NULL)
@@ -815,7 +900,7 @@ main(int argc,
/* Load yang module library, RFC7895 */
if (yang_modules_init(h) < 0)
goto done;
- /* Add netconf yang spec, used by netconf client and as internal protocol
+ /* Add generic yang specs, used by netconf client and as internal protocol
*/
if (netconf_module_load(h) < 0)
goto done;
@@ -834,6 +919,11 @@ main(int argc,
if (clicon_option_bool(h, "CLICON_XMLDB_MODSTATE") &&
yang_spec_parse_module(h, "ietf-yang-library", NULL, yspec)< 0)
goto done;
+ /* Check restconf start/stop from backend */
+ if (clicon_option_bool(h, "CLICON_BACKEND_RESTCONF_PROCESS")){
+ if (restconf_pseudo_process_reg(h, yspec) < 0)
+ goto done;
+ }
/* Here all modules are loaded
* Compute and set canonical namespace context
*/
diff --git a/apps/restconf/restconf_main_evhtp.c b/apps/restconf/restconf_main_evhtp.c
index 18538f53..fdc05501 100644
--- a/apps/restconf/restconf_main_evhtp.c
+++ b/apps/restconf/restconf_main_evhtp.c
@@ -1121,9 +1121,6 @@ restconf_config(clicon_handle h,
/* Add netconf yang spec, used as internal protocol */
if (netconf_module_load(h) < 0)
goto done;
- /* Clixon restconf daemon config */
- if (yang_spec_parse_module(h, "clixon-restconf", NULL, yspec)< 0)
- goto done;
/* Add system modules */
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
@@ -1171,7 +1168,7 @@ restconf_config(clicon_handle h,
clicon_session_id_set(h, id);
break;
}
- if ((nsc = xml_nsctx_init(NULL, "https://clicon.org/restconf")) == NULL)
+ if ((nsc = xml_nsctx_init(NULL, CLIXON_RESTCONF_NS)) == NULL)
goto done;
if ((pw = getpwuid(getuid())) == NULL){
clicon_err(OE_UNIX, errno, "getpwuid");
diff --git a/lib/clixon/clixon_options.h b/lib/clixon/clixon_options.h
index 1f20937c..ba9fc4f3 100644
--- a/lib/clixon/clixon_options.h
+++ b/lib/clixon/clixon_options.h
@@ -50,8 +50,9 @@
* @see clixon-config.yang
* @see clixon-lib.yang
*/
-#define CLIXON_CONF_NS "http://clicon.org/config"
-#define CLIXON_LIB_NS "http://clicon.org/lib"
+#define CLIXON_CONF_NS "http://clicon.org/config"
+#define CLIXON_LIB_NS "http://clicon.org/lib"
+#define CLIXON_RESTCONF_NS "http://clicon.org/restconf"
/*
* Types
diff --git a/lib/clixon/clixon_proc.h b/lib/clixon/clixon_proc.h
index ba1a65b8..cdb2b9fa 100644
--- a/lib/clixon/clixon_proc.h
+++ b/lib/clixon/clixon_proc.h
@@ -38,14 +38,22 @@
#ifndef _CLIXON_PROC_H_
#define _CLIXON_PROC_H_
+/*
+ * Types
+ */
+typedef struct process_entry_t process_entry_t;
+
+/* Process RPC callback function */
+typedef int (proc_cb_t)(clicon_handle h, process_entry_t *pe, char **operation);
+
/*
* Prototypes
*/
int clixon_proc_run(char **argv, void (outcb)(char *), int doerr);
-int clixon_proc_background(char **argv, char *netns, pid_t *pid);
+int clixon_proc_background(char **argv, const char *netns, pid_t *pid);
int clixon_proc_daemon(char **argv, pid_t *pid);
-int clixon_process_register(clicon_handle h, const char *name, const char *netns, char **argv, int argc);
+int clixon_process_register(clicon_handle h, const char *name, const char *netns, proc_cb_t *callback, char **argv, int argc);
int clixon_process_delete_all(clicon_handle h);
-int clixon_process_operation(clicon_handle h, char *name, char *op, int *status);
+int clixon_process_operation(clicon_handle h, const char *name, char *op, const int wrapit, uint32_t *pid);
#endif /* _CLIXON_PROC_H_ */
diff --git a/lib/src/clixon_datastore_read.c b/lib/src/clixon_datastore_read.c
index 144a9fee..b2984f5c 100644
--- a/lib/src/clixon_datastore_read.c
+++ b/lib/src/clixon_datastore_read.c
@@ -902,7 +902,7 @@ xmldb_get(clicon_handle h,
* @note Use of 1 for OK
* @code
* cxobj *xt;
- * if (xmldb_get0(xh, "running", YB_MODULE, nsc, "/interface[name="eth"]", 0, &xt, NULL) < 0)
+ * if (xmldb_get0(h, "running", YB_MODULE, nsc, "/interface[name="eth"]", 0, &xt, NULL) < 0)
* err;
* ...
* xmldb_get0_clear(h, xt); # Clear tree from default values and flags
@@ -910,6 +910,19 @@ xmldb_get(clicon_handle h,
* @endcode
* @see xml_nsctx_node to get a XML namespace context from XML tree
* @see xmldb_get for a copy version (old-style)
+ * @note An annoying issue is one with default values and xpath miss:
+ * Assume a yang spec:
+ * module m {
+ * container c {
+ * leaf x {
+ * default 0;
+ * And a db content:
+ * 1
+ * With the following call:
+ * xmldb_get0(h, "running", NULL, NULL, "/c[x=0]", 1, &xt, NULL)
+ * which result in a miss (there is no c with x=0), but when the returned xt is printed
+ * (the existing tree is discarded), the default (empty) xml tree is:
+ * 0
*/
int
xmldb_get0(clicon_handle h,
diff --git a/lib/src/clixon_netconf_lib.c b/lib/src/clixon_netconf_lib.c
index 966515b9..878c1b60 100644
--- a/lib/src/clixon_netconf_lib.c
+++ b/lib/src/clixon_netconf_lib.c
@@ -1356,7 +1356,7 @@ netconf_module_features(clicon_handle h)
return retval;
}
-/*! Load ietf netconf yang module and set enabled features
+/*! Load generic yang specs, ie ietf netconf yang module and set enabled features
* @param[in] h Clixon handle
* @retval 0 OK
* @retval -1 Error
@@ -1379,6 +1379,9 @@ netconf_module_load(clicon_handle h)
if (clicon_option_bool(h, "CLICON_XML_CHANGELOG"))
if (yang_spec_parse_module(h, "clixon-xml-changelog", NULL, yspec)< 0)
goto done;
+ /* Load restconf yang. Note this is also a part of clixon-config */
+ if (yang_spec_parse_module(h, "clixon-restconf", NULL, yspec)< 0)
+ goto done;
retval = 0;
done:
return retval;
diff --git a/lib/src/clixon_plugin.c b/lib/src/clixon_plugin.c
index 6c5e0ff8..9ea9f170 100644
--- a/lib/src/clixon_plugin.c
+++ b/lib/src/clixon_plugin.c
@@ -317,6 +317,12 @@ done:
* @param[out] cpp Clixon plugin structure (direct pointer)
* @retval 0 OK, with cpp set
* @retval -1 Error
+ * @code
+ * clixon_plugin *cp = NULL;
+ * if (clixon_pseudo_plugin(h, "pseudo plugin", &cp) < 0)
+ * err;
+ * cp->cp_api.ca_extension = my_ext_cb;
+ * @endcode
*/
int
clixon_pseudo_plugin(clicon_handle h,
diff --git a/lib/src/clixon_proc.c b/lib/src/clixon_proc.c
index dd1c28a7..1448deee 100644
--- a/lib/src/clixon_proc.c
+++ b/lib/src/clixon_proc.c
@@ -76,6 +76,19 @@
#include "clixon_queue.h"
#include "clixon_proc.h"
+/*
+ * Types
+ */
+/* Process entry list */
+struct process_entry_t {
+ qelem_t pe_qelem; /* List header */
+ char *pe_name; /* Name of process used for internal use */
+ char *pe_netns; /* Network namespace */
+ char **pe_argv; /* argv with command as element 0 and NULL-terminated */
+ pid_t pe_pid; /* Running process id (state) or 0 if dead */
+ proc_cb_t *pe_callback; /* Wrapper function */
+};
+
/*
* Child process ID
* XXX Really shouldn't be a global variable
@@ -208,9 +221,9 @@ clixon_proc_run(char **argv,
* @note SIGCHLD is set to IGN here. Maybe it should be done in main?
*/
int
-clixon_proc_background(char **argv,
- char *netns,
- pid_t *pid0)
+clixon_proc_background(char **argv,
+ const char *netns,
+ pid_t *pid0)
{
int retval = -1;
pid_t child;
@@ -273,7 +286,6 @@ clixon_proc_background(char **argv,
}
}
#endif /* HAVE_SETNS */
- clicon_debug(1, "%s argv0:%s", __FUNCTION__, argv[0]);
if (execv(argv[0], argv) < 0) {
clicon_err(OE_UNIX, errno, "execv");
exit(1);
@@ -289,7 +301,7 @@ clixon_proc_background(char **argv,
*pid0 = child;
retval = 0;
quit:
- clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
+ clicon_debug(1, "%s retval:%d child:%u", __FUNCTION__, retval, child);
return retval;
}
@@ -373,13 +385,6 @@ clixon_proc_daemon(char **argv,
/*
* Types
*/
-typedef struct {
- qelem_t pe_qelem; /* List header */
- char *pe_name; /* Name of process used for internal use */
- char *pe_netns; /* Network namespace */
- char **pe_argv; /* argv with command as element 0 and NULL-terminated */
- pid_t pe_pid;
-} process_entry_t;
/* List of process callback entries */
static process_entry_t *proc_entry_list = NULL;
@@ -398,6 +403,7 @@ int
clixon_process_register(clicon_handle h,
const char *name,
const char *netns,
+ proc_cb_t *callback,
char **argv,
int argc)
{
@@ -436,6 +442,7 @@ clixon_process_register(clicon_handle h,
clicon_err(OE_UNIX, errno, "strdup");
}
}
+ pe->pe_callback = callback;
ADDQ(pe, proc_entry_list);
retval = 0;
done:
@@ -469,15 +476,15 @@ clixon_process_delete_all(clicon_handle h)
}
static int
-proc_op_run(process_entry_t *pe,
- int *runp)
+proc_op_run(pid_t pid0,
+ int *runp)
{
int retval = -1;
int run;
pid_t pid;
run = 0;
- if ((pid = pe->pe_pid) != 0){ /* if 0 stopped */
+ if ((pid = pid0) != 0){ /* if 0 stopped */
/* Check if lives */
run = 1;
if ((kill(pid, 0)) < 0){
@@ -497,11 +504,53 @@ proc_op_run(process_entry_t *pe,
return retval;
}
-/*! Upgrade specific module identified by namespace, search matching callbacks
+/*! Perform process operation
+ *
+ */
+static int
+clixon_process_operation_one(const char *op,
+ const char *netns,
+ char **argv,
+ pid_t *pidp)
+{
+ int retval = -1;
+ int run = 0;
+
+ /* Check if running */
+ if (proc_op_run(*pidp, &run) < 0)
+ goto done;
+ if (strcmp(op, "stop") == 0 ||
+ strcmp(op, "restart") == 0){
+ if (run)
+ pidfile_zapold(*pidp); /* Ensures its dead */
+ *pidp = 0; /* mark as dead */
+ run = 0;
+ }
+ if (strcmp(op, "start") == 0 ||
+ strcmp(op, "restart") == 0){
+ if (run == 1){
+ ; /* Already runs */
+ }
+ else{
+ if (clixon_proc_background(argv, netns, pidp) < 0)
+ goto done;
+ }
+ }
+ else if (strcmp(op, "status") == 0){
+ ; /* status already set */
+ }
+
+ retval = 0;
+ done:
+ return retval;
+}
+
+/*! Find process operation entry given name and op and perform operation if found
*
* @param[in] h clicon handle
* @param[in] name Name of process
* @param[in] op start, stop.
+ * @param[in] wrapit If set, call potential callback, if false, dont call it
* @param[out] status true if process is running / false if not running on entry
* @retval -1 Error
* @retval 0 OK
@@ -509,13 +558,13 @@ proc_op_run(process_entry_t *pe,
*/
int
clixon_process_operation(clicon_handle h,
- char *name,
+ const char *name,
char *op,
- int *status)
+ int wrapit,
+ uint32_t *pid)
{
int retval = -1;
process_entry_t *pe;
- int run;
clicon_debug(1, "%s name:%s op:%s", __FUNCTION__, name, op);
if (proc_entry_list == NULL)
@@ -523,31 +572,14 @@ clixon_process_operation(clicon_handle h,
pe = proc_entry_list;
do {
if (strcmp(pe->pe_name, name) == 0){
- /* Check if running */
- if (proc_op_run(pe, &run) < 0)
+ /* Call wrapper function that eg changes op based on config */
+ if (wrapit && pe->pe_callback != NULL)
+ if (pe->pe_callback(h, pe, &op) < 0)
+ goto done;
+ if (clixon_process_operation_one(op, pe->pe_netns, pe->pe_argv, &pe->pe_pid) < 0)
goto done;
- if (status) /* Store as output parameter */
- *status = run;
- if (strcmp(op, "stop") == 0 ||
- strcmp(op, "restart") == 0){
- if (run)
- pidfile_zapold(pe->pe_pid); /* Ensures its dead */
- pe->pe_pid = 0; /* mark as dead */
- run = 0;
- }
- if (strcmp(op, "start") == 0 ||
- strcmp(op, "restart") == 0){
- if (run == 1){
- ; /* Already runs */
- }
- else{
- if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &pe->pe_pid) < 0)
- goto done;
- }
- }
- else if (strcmp(op, "status") == 0){
- ; /* status already set */
- }
+ if (pid)
+ *pid = pe->pe_pid;
break; /* hit break here */
}
pe = NEXTQ(process_entry_t *, pe);
diff --git a/test/mem.sh b/test/mem.sh
index 36660d52..338e6798 100755
--- a/test/mem.sh
+++ b/test/mem.sh
@@ -28,8 +28,8 @@ memonce(){
'backend')
valgrindtest=2 # This means backend valgrind test
: ${DEMWAIT:=10} # valgrind backend needs some time to get up
-
- clixon_backend="/usr/bin/valgrind --num-callers=50 --leak-check=full --show-leak-kinds=all --suppressions=./valgrind-clixon.supp --track-fds=yes --trace-children=yes --log-file=$valgrindfile clixon_backend"
+ # trace-children=no for test_restconf_rpc.sh
+ clixon_backend="/usr/bin/valgrind --num-callers=50 --leak-check=full --show-leak-kinds=all --suppressions=./valgrind-clixon.supp --track-fds=yes --trace-children=no --log-file=$valgrindfile clixon_backend"
;;
'restconf')
valgrindtest=3 # This means backend valgrind test
diff --git a/test/test_restconf.sh b/test/test_restconf.sh
index c8645f91..ca421f9e 100755
--- a/test/test_restconf.sh
+++ b/test/test_restconf.sh
@@ -74,7 +74,7 @@ state='{"clixon-example:state":{"op":\["41","42","43"\]}'
if $IPv6; then
# For backend config, create 4 sockets, all combinations IPv4/IPv6 + http/https
RESTCONFIG=$(cat <
+
true
password
$srvcert
@@ -90,7 +90,7 @@ EOF
else
# For backend config, create 4 sockets, all combinations IPv4/IPv6 + http/https
RESTCONFIG=$(cat <
+
true
password
$srvcert
@@ -142,10 +142,12 @@ testrun()
new "kill old restconf daemon"
stop_restconf_pre
- new "start restconf daemon ZZZ"
+ new "start restconf daemon"
echo "cfg:$cfg"
start_restconf -f $cfg
+
fi
+
new "wait restconf"
wait_restconf
@@ -186,7 +188,7 @@ testrun()
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $proto://$addr/restconf/data/ietf-yang-library:modules-state/module=ietf-interfaces,2018-02-20)" 0 'HTTP/1.1 200 OK' '{"ietf-yang-library:module":\[{"name":"ietf-interfaces","revision":"2018-02-20","namespace":"urn:ietf:params:xml:ns:yang:ietf-interfaces","conformance-type":"implement"}\]}'
new "restconf schema resource, mod-state top-level"
- expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $proto://$addr/restconf/data/ietf-yang-library:modules-state)" 0 'HTTP/1.1 200 OK' '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-example","revision":"2020-12-01","namespace":"urn:example:clixon","conformance-type":"implement"},{"name":"clixon-lib","revision":"2020-12-08","'
+ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $proto://$addr/restconf/data/ietf-yang-library:modules-state)" 0 'HTTP/1.1 200 OK' '{"ietf-yang-library:modules-state":{"module-set-id":"0","module":\[{"name":"clixon-example","revision":"2020-12-01","namespace":"urn:example:clixon","conformance-type":"implement"},{"name":"clixon-lib","revision":"2020-12-30","'
new "restconf options. RFC 8040 4.1"
expectpart "$(curl $CURLOPTS -X OPTIONS $proto://$addr/restconf/data)" 0 "HTTP/1.1 200 OK" "Allow: OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE"
@@ -390,7 +392,7 @@ for proto in $protos; do
addrs="$addrs \[::1\]"
fi
for addr in $addrs; do
- new "restconf test: proto:$proto addr:$addr config:$config"
+ new "restconf test: proto:$proto addr:$addr"
testrun $proto $addr
done
done
diff --git a/test/test_restconf_jukebox.sh b/test/test_restconf_jukebox.sh
index 089ee1d7..903945f4 100755
--- a/test/test_restconf_jukebox.sh
+++ b/test/test_restconf_jukebox.sh
@@ -102,7 +102,7 @@ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPR
# 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 $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://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-12-08","namespace":"http://clicon.org/lib","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"}'
+expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://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-12-30","namespace":"http://clicon.org/lib","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"}'
new "B.1.3. Retrieve the Server Capability Information"
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://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_restconf_rpc.sh b/test/test_restconf_rpc.sh
index d89aa876..8d6e59a9 100755
--- a/test/test_restconf_rpc.sh
+++ b/test/test_restconf_rpc.sh
@@ -1,6 +1,12 @@
#!/usr/bin/env bash
-# Restconf direct start/stop using RPC (as alternative to systemd or other)
-# Also try ip netns
+# Restconf direct start/stop using RPC and config enable flag (as alternative to systemd or other)
+# According tot he following behaviour:
+# - on RPC start, if enable is true, start the service, if false, error or ignore it
+# - on RPC stop, stop the service
+# - on backend start make the state as configured
+# - on enable change, make the state as configured
+# - No restconf config means enable: false (extra rule)
+# Also work-in-progress network namespaces, ip netns
# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
@@ -8,17 +14,12 @@ s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
APPNAME=example
cfg=$dir/conf.xml
-
-# Cant get it to work in the general case, single tests work fine
-# More specifically, if mem.sh background netconf, netconf crashes which is valgrindtest 1
-if [ $valgrindtest -eq 1 ]; then
- echo "...skipped "
- return 0 # skip
-fi
+startupdb=$dir/startup_db
cat < $cfg
$cfg
+ ietf-netconf:startup
/usr/local/share/clixon
$IETFRFC
$dir
@@ -31,7 +32,7 @@ cat < $cfg
$APPNAME
/usr/local/var/$APPNAME/$APPNAME.sock
/usr/local/var/$APPNAME/$APPNAME.pidfile
- /usr/local/var/$APPNAME
+ $dir
true
true
@@ -39,6 +40,72 @@ cat < $cfg
EOF
+# Subroutine send a process control RPC and tricks to echo process-id returned
+# Args:
+# 1: operation
+# 2: expectret 0: means expect pi 0 as return, else something else
+testrpc()
+{
+ operation=$1
+ expectret=$2
+
+ new "send rpc $operation"
+ ret=$($clixon_netconf -qf $cfg<
+
+ restconf
+ $operation
+
+]]>]]>
+EOF
+)
+
+ expect1=""
+ match=$(echo "$ret" | grep --null -Go "$expect1")
+ if [ -z "$match" ]; then
+ err "$expect1" "$ret"
+ fi
+
+ expect2="]]>]]>"
+ match=$(echo "$ret" | grep --null -Go "$expect2")
+ if [ -z "$match" ]; then
+ err "$expect2" "$ret"
+ fi
+
+ new "check rpc $operation get pid"
+ pid=$(echo "$ret" | awk -F'[<>]' '{print $5}')
+ if [ -z "$pid" ]; then
+ err "Running process" "$ret"
+ fi
+
+ new "check restconf retvalue"
+ if [ $expectret -eq 0 ]; then
+ if [ $pid -ne 0 ]; then
+ err "No process" "$pid"
+ fi
+ else
+ if [ $pid -eq 0 ]; then
+ err "Running process"
+ fi
+ fi
+
+ >&2 echo "pid:$pid" # debug
+ echo $pid # cant use return that only uses 0-255
+}
+
+new "ENABLE true"
+# First basic operation with restconf enable is true
+cat< $startupdb
+
+
+ true
+
+
+EOF
+
+new "kill old restconf"
+stop_restconf_pre
+
new "test params: -f $cfg"
if [ $BE -ne 0 ]; then
new "kill old backend"
@@ -46,92 +113,82 @@ if [ $BE -ne 0 ]; then
if [ $? -ne 0 ]; then
err
fi
- new "start backend -s init -f $cfg"
- start_backend -s init -f $cfg
- new "waiting"
+ new "start backend -s startup -f $cfg"
+ start_backend -s startup -f $cfg
+
+ new "wait backend"
wait_backend
fi
-new "kill old restconf"
-stop_restconf_pre
+# Get pid of running process and check return xml
+new "Get rpc status"
+pid0=$(testrpc status 1)
+if [ $? -ne 0 ]; then exit -1; fi
-new "1)check no restconf"
-ps=$(ps aux|grep "$WWWDIR/clixon_restconf" | grep -v grep)
-if [ -n "$ps" ]; then
- err "No restconf running" "$ps"
-fi
+new "check restconf process running using ps pid0:$pid0"
+ps=$(ps -hp $pid0)
-new "2)check status off"
-expecteof "$clixon_netconf -qf $cfg" 0 "restconfstatus]]>]]>" "false]]>]]>"
-
-new "start restconf"
-expecteof "$clixon_netconf -qf $cfg" 0 "restconfstart]]>]]>" "]]>]]>"
-
-new "3)check restconf on"
-if [ $valgrindtest -eq 0 ]; then # Cant get pgrep to work properly
- sleep $DEMWAIT # Slows the tests down considerably, but needed in eg docker test
-fi
-ps=$(ps aux|grep "$WWWDIR/clixon_restconf -f $cfg" | grep -v grep)
-if [ -z "$ps" ]; then
- err "restconf running"
-fi
-
-new "4)check status on"
-expecteof "$clixon_netconf -qf $cfg" 0 "restconfstatus]]>]]>" "true]]>]]>"
-
-new "stop restconf"
-expecteof "$clixon_netconf -qf $cfg" 0 "restconfstop]]>]]>" "]]>]]>"
-
-new "start restconf again"
-expecteof "$clixon_netconf -qf $cfg" 0 "restconfstart]]>]]>" "]]>]]>"
-
-new "5)check restconf on"
-if [ $valgrindtest -eq 0 ]; then # Cant get pgrep to work properly
- sleep $DEMWAIT # Slows the tests down considerably, but needed in eg docker test
-fi
-ps=$(ps aux|grep "$WWWDIR/clixon_restconf -f $cfg" | grep -v grep)
if [ -z "$ps" ]; then
err "A restconf running"
fi
+new "stop restconf RPC"
+pid1=$(testrpc stop 0)
+if [ $? -ne 0 ]; then exit -1; fi
+
+new "Get rpc status stopped"
+pid2=$(testrpc status 0)
+if [ $? -ne 0 ]; then exit -1; fi
+
+new "Start rpc again"
+pid3=$(testrpc start 1)
+if [ $? -ne 0 ]; then exit -1; fi
+
+new "check restconf process running using ps"
+ps=$(ps -hp $pid3)
+if [ -z "$ps" ]; then
+ err "A restconf running"
+fi
+
+if [ $pid0 -eq $pid3 ]; then
+ err "A different pid" "$pid3"
+fi
+
new "kill restconf"
stop_restconf_pre
-new "6)check no restconf"
-ps=$(ps aux|grep "$WWWDIR/clixon_restconf" | grep -v grep)
-if [ -n "$ps" ]; then
- err "No restconf running" "$ps"
+new "start restconf RPC"
+pid4=$(testrpc start 1)
+if [ $? -ne 0 ]; then exit -1; fi
+
+new "check status RPC on"
+pid5=$(testrpc status 1)
+if [ $? -ne 0 ]; then exit -1; fi
+
+new "restart restconf RPC"
+pid6=$(testrpc restart 1)
+if [ $? -ne 0 ]; then exit -1; fi
+
+new "Get restconf status rpc"
+pid7=$(testrpc status 1)
+if [ $? -ne 0 ]; then exit -1; fi
+
+if [ $pid5 -eq $pid7 ]; then
+ err "A different pid" "$pid7"
fi
-new "restart restconf"
-expecteof "$clixon_netconf -qf $cfg" 0 "restconfrestart]]>]]>" "]]>]]>"
-
-new "7)check status on"
-expecteof "$clixon_netconf -qf $cfg" 0 "restconfstatus]]>]]>" "true]]>]]>"
-
-if [ $valgrindtest -eq 0 ]; then # Cant get pgrep to work properly
- sleep $DEMWAIT # Slows the tests down considerably, but needed in eg docker test
-fi
-pid0=$(pgrep clixon_restconf)
-
-new "restart restconf"
-expecteof "$clixon_netconf -qf $cfg" 0 "restconfrestart]]>]]>" "]]>]]>"
-
-new "8)check status on"
-expecteof "$clixon_netconf -qf $cfg" 0 "restconfstatus]]>]]>" "true]]>]]>"
-
-if [ $valgrindtest -eq 0 ]; then # Cant get pgrep to work properly
- new "9)check new pid"
- sleep $DEMWAIT # Slows the tests down considerably, but needed in eg docker test
- pid1=$(pgrep clixon_restconf)
- if [ -z "$pid0" -o -z "$pid1" ]; then
- err "Pids expected" "pid0:$pid0 = pid1:$pid1"
- fi
- if [ $pid0 -eq $pid1 ]; then
- err "Different pids" "pid0:$pid0 = pid1:$pid1"
- fi
-fi
+#if [ $valgrindtest -eq 0 ]; then # Cant get pgrep to work properly
+# new "check new pid"
+# sleep $DEMWAIT # Slows the tests down considerably, but needed in eg docker test
+# pid1=$(pgrep clixon_restconf)
+# if [ -z "$pid0" -o -z "$pid1" ]; then
+# err "Pids expected" "pid0:$pid0 = pid1:$pid1"
+# fi
+# if [ $pid0 -eq $pid1 ]; then#
+# err "Different pids" "pid0:$pid0 = pid1:$pid1"
+# fi
+#fi
if [ $BE -ne 0 ]; then
new "Kill backend"
@@ -142,19 +199,70 @@ if [ $BE -ne 0 ]; then
fi
# kill backend
stop_backend -f $cfg
+ fi
- # XXX Cant get this to work in docker/alpine
- if false; then
- new "10)check no restconf"
- sleep $DEMWAIT
- ps=$(ps aux|grep "$WWWDIR/clixon_restconf" | grep -v grep)
- if [ -n "$ps" ]; then
- err "No restconf running" "$ps"
- fi
+# So far, no restconf config enable flag has been true. Now change enable flag.
+
+new "ENABLE false"
+# Second basic operation with restconf enable is false
+cat< $startupdb
+
+
+ false
+
+
+EOF
+
+new "kill old restconf"
+stop_restconf_pre
+
+new "test params: -f $cfg"
+if [ $BE -ne 0 ]; then
+ new "kill old backend"
+ sudo clixon_backend -z -f $cfg
+ if [ $? -ne 0 ]; then
+ err
fi
+ new "start backend -s startup -f $cfg"
+ start_backend -s startup -f $cfg
+
+ new "waiting"
+ wait_backend
fi
-if false; then # Work in progress
+new "check status RPC off"
+pid=$(testrpc status 0)
+if [ $? -ne 0 ]; then exit -1; fi
+
+new "start restconf RPC"
+pid=$(testrpc start 0)
+if [ $? -ne 0 ]; then exit -1; fi
+
+new "check status RPC off"
+pid=$(testrpc status 0)
+if [ $? -ne 0 ]; then exit -1; fi
+
+new "Enable restconf"
+expecteof "$clixon_netconf -qf $cfg" 0 "mergetrue]]>]]>" "^]]>]]>$"
+
+new "netconf commit"
+expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$"
+
+new "check status RPC on"
+pid=$(testrpc status 1)
+if [ $? -ne 0 ]; then exit -1; fi
+
+new "Disable restconf"
+expecteof "$clixon_netconf -qf $cfg" 0 "mergefalse]]>]]>" "^]]>]]>$"
+
+new "netconf commit"
+expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$"
+
+new "check status RPC off"
+pid=$(testrpc status 0)
+if [ $? -ne 0 ]; then exit -1; fi
+
+if false; then # Work in progress - namespace
#-------------------------------
# Now in a separate network namespace
new "restconf rpc in network namespace"
@@ -207,3 +315,4 @@ sudo ip netns delete $netns
fi # namespaces
rm -rf $dir
+
diff --git a/test/test_upgrade_quit.sh b/test/test_upgrade_quit.sh
index 1965e1a6..b157f2a0 100755
--- a/test/test_upgrade_quit.sh
+++ b/test/test_upgrade_quit.sh
@@ -301,7 +301,7 @@ cat < $dir/startup_db
EOF
-MODSTATE1='0clixon-lib2020-12-08http://clicon.org/lib'
+MODSTATE1='0clixon-lib2020-12-30http://clicon.org/lib'
MODSTATE2='interfaces2018-02-20urn:example:interfaces'
diff --git a/yang/clixon/Makefile.in b/yang/clixon/Makefile.in
index 75fd9347..40d2d9ee 100644
--- a/yang/clixon/Makefile.in
+++ b/yang/clixon/Makefile.in
@@ -42,8 +42,8 @@ datarootdir = @datarootdir@
# See also OPT_YANG_INSTALLDIR for the standard yang files
YANG_INSTALLDIR = @YANG_INSTALLDIR@
-YANGSPECS = clixon-config@2020-11-03.yang
-YANGSPECS += clixon-lib@2020-12-08.yang
+YANGSPECS = clixon-config@2020-12-30.yang
+YANGSPECS += clixon-lib@2020-12-30.yang
YANGSPECS += clixon-rfc5277@2008-07-01.yang
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
YANGSPECS += clixon-restconf@2020-10-30.yang
diff --git a/yang/clixon/clixon-config.yang b/yang/clixon/clixon-config.yang
index 5756b75f..a76a1706 120000
--- a/yang/clixon/clixon-config.yang
+++ b/yang/clixon/clixon-config.yang
@@ -1 +1 @@
-clixon-config@2020-10-01.yang
\ No newline at end of file
+clixon-config@2020-12-30.yang
\ No newline at end of file
diff --git a/yang/clixon/clixon-config@2020-10-01.yang b/yang/clixon/clixon-config@2020-12-30.yang
similarity index 93%
rename from yang/clixon/clixon-config@2020-10-01.yang
rename to yang/clixon/clixon-config@2020-12-30.yang
index 4ef7a4ca..0c839363 100644
--- a/yang/clixon/clixon-config@2020-10-01.yang
+++ b/yang/clixon/clixon-config@2020-12-30.yang
@@ -3,6 +3,9 @@ module clixon-config {
namespace "http://clicon.org/config";
prefix cc;
+ import clixon-restconf {
+ prefix clrc;
+ }
organization
"Clicon / Clixon";
@@ -40,9 +43,33 @@ module clixon-config {
***** END LICENSE BLOCK *****";
+ revision 2020-12-30 {
+ description
+ "Removed obsolete options:
+ CLICON_RESTCONF_IPV4_ADDR
+ CLICON_RESTCONF_IPV6_ADDR
+ CLICON_RESTCONF_HTTP_PORT
+ CLICON_RESTCONF_HTTPS_PORT
+ CLICON_SSL_SERVER_CERT
+ CLICON_SSL_SERVER_KEY
+ CLICON_SSL_CA_CERT";
+ }
+ revision 2020-11-03 {
+ description
+ "Added CLICON_BACKEND_RESTCONF_PROCESS
+ Copied to clixon-restconf.yang and marked as obsolete:
+ CLICON_RESTCONF_IPV4_ADDR
+ CLICON_RESTCONF_IPV6_ADDR
+ CLICON_RESTCONF_HTTP_PORT
+ CLICON_RESTCONF_HTTPS_PORT
+ CLICON_SSL_SERVER_CERT
+ CLICON_SSL_SERVER_KEY
+ CLICON_SSL_CA_CERT
+ Removed obsolete option CLICON_TRANSACTION_MOD";
+ }
revision 2020-10-01 {
description
- "Added: CLICON_CONFIGDIR";
+ "Added: CLICON_CONFIGDIR.";
}
revision 2020-08-17 {
description
@@ -264,8 +291,22 @@ module clixon-config {
}
}
}
+ typedef socket_address_family {
+ description "Address family for internal socket";
+ type enumeration{
+ enum UNIX {
+ description "Unix domain socket";
+ }
+ enum IPv4 {
+ description "IPv4";
+ }
+ }
+ }
container clixon-config {
+ container restconf {
+ uses clrc:clixon-restconf;
+ }
leaf-list CLICON_FEATURE {
description
"Supported features as used by YANG feature/if-feature
@@ -392,7 +433,8 @@ module clixon-config {
default "/www-data/fastcgi_restconf.sock";
description
"FastCGI unix socket. Should be specified in webserver
- Eg in nginx: fastcgi_pass unix:/www-data/clicon_restconf.sock";
+ Eg in nginx: fastcgi_pass unix:/www-data/clicon_restconf.sock
+ Only if with-restconf=fcgi, NOT evhtp";
}
leaf CLICON_RESTCONF_PRETTY {
type boolean;
@@ -407,58 +449,6 @@ module clixon-config {
Setting this value to false makes restconf return not pretty-printed
which may be desirable for performance or tests";
}
- leaf CLICON_RESTCONF_IPV4_ADDR {
- type string;
- default "0.0.0.0";
- description
- "RESTCONF IPv4 socket binding address.
- Applies to native http by config option --with-restconf=evhtp.";
- }
- leaf CLICON_RESTCONF_IPV6_ADDR {
- type string;
- default "::";
- description
- "RESTCONF IPv6 socket binding address.
- Applies to native http by config option --with-restconf=evhtp.";
- }
- leaf CLICON_RESTCONF_HTTP_PORT {
- type uint16;
- default 80;
- description
- "RESTCONF socket binding port, non-ssl
- In the restconf daemon, it can be overriden by -P
- Applies to native http only by config option --with-restconf=evhtp.";
- }
- leaf CLICON_RESTCONF_HTTPS_PORT {
- type uint16;
- default 443;
- description
- "RESTCONF socket binding port, ssl
- In the restconf daemon, this is the port chosen if -s is given.
- Note it can be overriden by -P
- Applies to native http by config option --with-restconf=evhtp.";
- }
- leaf CLICON_SSL_SERVER_CERT {
- type string;
- default "/etc/ssl/certs/clixon-server-crt.pem";
- description
- "SSL server cert for restconf https.
- Applies to native http only by config option --with-restconf=evhtp.";
- }
- leaf CLICON_SSL_SERVER_KEY {
- type string;
- default "/etc/ssl/private/clixon-server-key.pem";
- description
- "SSL server private key for restconf https.
- Applies to native http only by config option --with-restconf=evhtp.";
- }
- leaf CLICON_SSL_CA_CERT {
- type string;
- default "/etc/ssl/certs/clixon-ca_crt.pem";
- description
- "SSL CA cert for client authentication.
- Applies to native http only by config option --with-restconf=evhtp.";
- }
leaf CLICON_CLI_DIR {
type string;
description
@@ -624,15 +614,15 @@ module clixon-config {
from a spec, such as in the autocli.";
}
leaf CLICON_SOCK_FAMILY {
- type string;
- default "UNIX";
+ type socket_address_family;
+ default UNIX;
description
- "Address family for communicating with clixon_backend
- (UNIX|IPv4). IPv6 not yet implemented.
+ "Address family for communicating with clixon_backend with one of:
+ Note IPv6 not implemented.
Note that UNIX socket makes credential check as follows:
(1) client needs rw access to the socket
(2) NACM credentials can be checked according to CLICON_NACM_CREDENTIALS
- Warning: IPv4 and IPv6 sockets have no credential mechanism.
+ Warning: Only UNIX (not IPv4) sockets have credential mechanism.
";
}
leaf CLICON_SOCK {
@@ -681,6 +671,20 @@ module clixon-config {
mandatory true;
description "Process-id file of backend daemon";
}
+ leaf CLICON_BACKEND_RESTCONF_PROCESS {
+ type boolean;
+ default false;
+ description
+ "If set, enable process-control of restconf daemon, ie start/stop restconf
+ daemon internally from backend daemon.
+ It uses clixon-restconf.yang for config and clixon-lib.yang for RPC
+ Process control of restconf daemon is as follows:
+ - on RPC start, if enable is true, start the service, if false, error or ignore it
+ - on RPC stop, stop the service
+ - on backend start make the state as configured
+ - on enable change, make the state as configured
+ Disable if you start the restconf daemon by other means.";
+ }
leaf CLICON_AUTOCOMMIT {
type int32;
default 0;
diff --git a/yang/clixon/clixon-lib@2020-12-30.yang b/yang/clixon/clixon-lib@2020-12-30.yang
new file mode 100644
index 00000000..2886b28a
--- /dev/null
+++ b/yang/clixon/clixon-lib@2020-12-30.yang
@@ -0,0 +1,183 @@
+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-12-30 {
+ description
+ "Changed: RPC process-control output parameter status to pid";
+ }
+ revision 2020-12-08 {
+ description
+ "Added: autocli-op extension.
+ rpc process-control for process/daemon management
+ Released in clixon 4.9";
+ }
+ revision 2020-04-23 {
+ description
+ "Added: stats RPC for clixon XML and memory statistics.
+ Added: restart-plugin RPC for restarting individual plugins without restarting backend.";
+ }
+ 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";
+ }
+ typedef service-operation {
+ type enumeration {
+ enum start {
+ description
+ "Start if not already running";
+ }
+ enum stop {
+ description
+ "Stop if running";
+ }
+ enum restart {
+ description
+ "Stop if running, then start";
+ }
+ enum status {
+ description
+ "Check status";
+ }
+ }
+ description
+ "Common operations that can be performed on a service";
+ }
+ extension autocli-op {
+ description
+ "Takes an argument an operation defing how to modify the clispec at
+ this point in the YANG tree for the automated generated CLI.
+ Note that this extension is only used in clixon_cli.
+ Operations is expected to be extended, but the following operations are defined:
+ - hide This command is active but not shown by ? or TAB";
+ argument cliop;
+ }
+ rpc debug {
+ description "Set debug level of backend.";
+ input {
+ leaf level {
+ type uint32;
+ }
+ }
+ }
+ rpc ping {
+ description "Check aliveness of backend daemon.";
+ }
+ rpc stats {
+ description "Clixon XML statistics.";
+ output {
+ container global{
+ description "Clixon global statistics";
+ leaf xmlnr{
+ description "Number of XML objects: 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;
+ }
+ }
+
+ }
+ }
+ rpc restart-plugin {
+ description "Restart specific backend plugins.";
+ input {
+ leaf-list plugin {
+ description "Name of plugin to restart";
+ type string;
+ }
+ }
+ }
+
+ rpc process-control {
+ description
+ "Control a specific process or daemon: start/stop, etc.
+ This is for direct managing of a porcess by the backend.
+ Alternatively one can manage a daemon via systemd, containerd, kubernetes, etc.";
+ input {
+ leaf name {
+ description "Name of process";
+ type string;
+ mandatory true;
+ }
+ leaf operation {
+ type service-operation;
+ mandatory true;
+ description
+ "One of the strings 'start', 'stop', 'restart', or 'status'.";
+ }
+ }
+ output {
+ leaf pid {
+ description "Process-id of running process if operation is start,
+ restart or status. 0 if not running.
+ This is for two reasons:
+ - to check process running for status
+ - get the actual pid for targeting the actual process";
+ type uint32;
+ }
+ }
+ }
+}
diff --git a/yang/clixon/clixon-restconf@2020-10-30.yang b/yang/clixon/clixon-restconf@2020-10-30.yang
index 05b17204..9344d855 100644
--- a/yang/clixon/clixon-restconf@2020-10-30.yang
+++ b/yang/clixon/clixon-restconf@2020-10-30.yang
@@ -1,6 +1,6 @@
module clixon-restconf {
yang-version 1.1;
- namespace "https://clicon.org/restconf";
+ namespace "http://clicon.org/restconf";
prefix "clrc";
import ietf-inet-types {
@@ -124,6 +124,13 @@ module clixon-restconf {
}
}
container restconf {
+ description
+ "This presence is strictly not necessary since the enable flag
+ in clixon-restconf is the flag bearing the actual semantics.
+ However, removing the presence leads to default config in all
+ clixon installations, even those which do not use backend-started restconf.
+ One could see this as mostly cosmetically annoying.
+ Alternative would be to make the inclusion of this yang conditional.";
presence "Enables RESTCONF";
uses clixon-restconf;
}