* New clixon-config@2020-12-30.yang revision
* New clixon-lib@2020-12-30.yang revision * Added callback to process-control RPC feature in clixon-lib.yang to manage processes * Changed behavior of starting restconf internally using `CLICON_BACKEND_RESTCONF_PROCESS` monitoring changes in enable flag, not only the RPC. * Changed: RPC process-control output parameter status to pid
This commit is contained in:
parent
7459925bd0
commit
cf63d0f761
21 changed files with 741 additions and 280 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
|
@ -39,11 +39,23 @@ Developers may need to change their code
|
||||||
|
|
||||||
Users may have to change how they access the system
|
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.
|
* 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.
|
* 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
|
### 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,
|
* Limited fuzz by AFL committed,
|
||||||
* see [fuzz/README.md](fuzz/README.md) for details
|
* see [fuzz/README.md](fuzz/README.md) for details
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
||||||
Copyright (C) 2017-2019 Olof Hagsand
|
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.
|
CLIXON is dual license.
|
||||||
|
|
|
||||||
|
|
@ -1580,23 +1580,18 @@ from_client_process_control(clicon_handle h,
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
char *name = NULL;
|
char *name = NULL;
|
||||||
char *operation = NULL;
|
char *operation = NULL;
|
||||||
int status = 0;
|
uint32_t pid = 0;
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
if ((x = xml_find_type(xe, NULL, "name", CX_ELMNT)) != NULL)
|
if ((x = xml_find_type(xe, NULL, "name", CX_ELMNT)) != NULL)
|
||||||
name = xml_body(x);
|
name = xml_body(x);
|
||||||
if ((x = xml_find_type(xe, NULL, "operation", CX_ELMNT)) != NULL)
|
if ((x = xml_find_type(xe, NULL, "operation", CX_ELMNT)) != NULL)
|
||||||
operation = xml_body(x);
|
operation = xml_body(x);
|
||||||
/* Make the actual process operation */
|
/* Make the actual process operation (with wrap function enabled) */
|
||||||
if (clixon_process_operation(h, name, operation, &status) < 0)
|
if (clixon_process_operation(h, name, operation, 1, &pid) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (strcmp(operation, "status") == 0)
|
cprintf(cbret, "<rpc-reply xmlns=\"%s\"><pid xmlns=\"%s\">%u</pid></rpc-reply>",
|
||||||
cprintf(cbret, "<rpc-reply xmlns=\"%s\"><status xmlns=\"%s\">%s</status></rpc-reply>",
|
NETCONF_BASE_NAMESPACE, CLIXON_LIB_NS, pid);
|
||||||
NETCONF_BASE_NAMESPACE,
|
|
||||||
CLIXON_LIB_NS,
|
|
||||||
status?"true":"false");
|
|
||||||
else
|
|
||||||
cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", NETCONF_BASE_NAMESPACE);
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -1633,7 +1628,6 @@ from_client_hello(clicon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! An internal clicon message has arrived from a client. Receive and dispatch.
|
/*! An internal clicon message has arrived from a client. Receive and dispatch.
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] s Socket where message arrived. read from this.
|
* @param[in] s Socket where message arrived. read from this.
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
@ -67,7 +68,7 @@
|
||||||
/* clicon */
|
/* clicon */
|
||||||
#include <clixon/clixon.h>
|
#include <clixon/clixon.h>
|
||||||
|
|
||||||
#include "clixon_backend_handle.h"
|
#include "clixon_backend_transaction.h"
|
||||||
#include "backend_socket.h"
|
#include "backend_socket.h"
|
||||||
#include "backend_client.h"
|
#include "backend_client.h"
|
||||||
#include "backend_plugin.h"
|
#include "backend_plugin.h"
|
||||||
|
|
@ -178,50 +179,6 @@ backend_server_socket(clicon_handle h)
|
||||||
return ss;
|
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
|
/*! Load external NACM file
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
|
|
@ -431,6 +388,140 @@ ret2status(int ret,
|
||||||
return retval;
|
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
|
/*! usage
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
|
|
@ -789,12 +880,6 @@ main(int argc,
|
||||||
clicon_option_str(h, "CLICON_BACKEND_REGEXP")) < 0)
|
clicon_option_str(h, "CLICON_BACKEND_REGEXP")) < 0)
|
||||||
goto done;
|
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
|
/* Load Yang modules
|
||||||
* 1. Load a yang module as a specific absolute filename */
|
* 1. Load a yang module as a specific absolute filename */
|
||||||
if ((str = clicon_yang_main_file(h)) != NULL)
|
if ((str = clicon_yang_main_file(h)) != NULL)
|
||||||
|
|
@ -815,7 +900,7 @@ main(int argc,
|
||||||
/* Load yang module library, RFC7895 */
|
/* Load yang module library, RFC7895 */
|
||||||
if (yang_modules_init(h) < 0)
|
if (yang_modules_init(h) < 0)
|
||||||
goto done;
|
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)
|
if (netconf_module_load(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -834,6 +919,11 @@ main(int argc,
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_MODSTATE") &&
|
if (clicon_option_bool(h, "CLICON_XMLDB_MODSTATE") &&
|
||||||
yang_spec_parse_module(h, "ietf-yang-library", NULL, yspec)< 0)
|
yang_spec_parse_module(h, "ietf-yang-library", NULL, yspec)< 0)
|
||||||
goto done;
|
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
|
/* Here all modules are loaded
|
||||||
* Compute and set canonical namespace context
|
* Compute and set canonical namespace context
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1121,9 +1121,6 @@ restconf_config(clicon_handle h,
|
||||||
/* Add netconf yang spec, used as internal protocol */
|
/* Add netconf yang spec, used as internal protocol */
|
||||||
if (netconf_module_load(h) < 0)
|
if (netconf_module_load(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Clixon restconf daemon config */
|
|
||||||
if (yang_spec_parse_module(h, "clixon-restconf", NULL, yspec)< 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Add system modules */
|
/* Add system modules */
|
||||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
|
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
|
||||||
|
|
@ -1171,7 +1168,7 @@ restconf_config(clicon_handle h,
|
||||||
clicon_session_id_set(h, id);
|
clicon_session_id_set(h, id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((nsc = xml_nsctx_init(NULL, "https://clicon.org/restconf")) == NULL)
|
if ((nsc = xml_nsctx_init(NULL, CLIXON_RESTCONF_NS)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if ((pw = getpwuid(getuid())) == NULL){
|
if ((pw = getpwuid(getuid())) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "getpwuid");
|
clicon_err(OE_UNIX, errno, "getpwuid");
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,9 @@
|
||||||
* @see clixon-config.yang
|
* @see clixon-config.yang
|
||||||
* @see clixon-lib.yang
|
* @see clixon-lib.yang
|
||||||
*/
|
*/
|
||||||
#define CLIXON_CONF_NS "http://clicon.org/config"
|
#define CLIXON_CONF_NS "http://clicon.org/config"
|
||||||
#define CLIXON_LIB_NS "http://clicon.org/lib"
|
#define CLIXON_LIB_NS "http://clicon.org/lib"
|
||||||
|
#define CLIXON_RESTCONF_NS "http://clicon.org/restconf"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Types
|
* Types
|
||||||
|
|
|
||||||
|
|
@ -38,14 +38,22 @@
|
||||||
#ifndef _CLIXON_PROC_H_
|
#ifndef _CLIXON_PROC_H_
|
||||||
#define _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
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
int clixon_proc_run(char **argv, void (outcb)(char *), int doerr);
|
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_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_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_ */
|
#endif /* _CLIXON_PROC_H_ */
|
||||||
|
|
|
||||||
|
|
@ -902,7 +902,7 @@ xmldb_get(clicon_handle h,
|
||||||
* @note Use of 1 for OK
|
* @note Use of 1 for OK
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xt;
|
* 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;
|
* err;
|
||||||
* ...
|
* ...
|
||||||
* xmldb_get0_clear(h, xt); # Clear tree from default values and flags
|
* xmldb_get0_clear(h, xt); # Clear tree from default values and flags
|
||||||
|
|
@ -910,6 +910,19 @@ xmldb_get(clicon_handle h,
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see xml_nsctx_node to get a XML namespace context from XML tree
|
* @see xml_nsctx_node to get a XML namespace context from XML tree
|
||||||
* @see xmldb_get for a copy version (old-style)
|
* @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:
|
||||||
|
* <c><x>1</x></c>
|
||||||
|
* 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:
|
||||||
|
* <c><x>0</x></c>
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xmldb_get0(clicon_handle h,
|
xmldb_get0(clicon_handle h,
|
||||||
|
|
|
||||||
|
|
@ -1356,7 +1356,7 @@ netconf_module_features(clicon_handle h)
|
||||||
return retval;
|
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
|
* @param[in] h Clixon handle
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
|
@ -1379,6 +1379,9 @@ netconf_module_load(clicon_handle h)
|
||||||
if (clicon_option_bool(h, "CLICON_XML_CHANGELOG"))
|
if (clicon_option_bool(h, "CLICON_XML_CHANGELOG"))
|
||||||
if (yang_spec_parse_module(h, "clixon-xml-changelog", NULL, yspec)< 0)
|
if (yang_spec_parse_module(h, "clixon-xml-changelog", NULL, yspec)< 0)
|
||||||
goto done;
|
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;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -317,6 +317,12 @@ done:
|
||||||
* @param[out] cpp Clixon plugin structure (direct pointer)
|
* @param[out] cpp Clixon plugin structure (direct pointer)
|
||||||
* @retval 0 OK, with cpp set
|
* @retval 0 OK, with cpp set
|
||||||
* @retval -1 Error
|
* @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
|
int
|
||||||
clixon_pseudo_plugin(clicon_handle h,
|
clixon_pseudo_plugin(clicon_handle h,
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,19 @@
|
||||||
#include "clixon_queue.h"
|
#include "clixon_queue.h"
|
||||||
#include "clixon_proc.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
|
* Child process ID
|
||||||
* XXX Really shouldn't be a global variable
|
* 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?
|
* @note SIGCHLD is set to IGN here. Maybe it should be done in main?
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clixon_proc_background(char **argv,
|
clixon_proc_background(char **argv,
|
||||||
char *netns,
|
const char *netns,
|
||||||
pid_t *pid0)
|
pid_t *pid0)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
pid_t child;
|
pid_t child;
|
||||||
|
|
@ -273,7 +286,6 @@ clixon_proc_background(char **argv,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* HAVE_SETNS */
|
#endif /* HAVE_SETNS */
|
||||||
clicon_debug(1, "%s argv0:%s", __FUNCTION__, argv[0]);
|
|
||||||
if (execv(argv[0], argv) < 0) {
|
if (execv(argv[0], argv) < 0) {
|
||||||
clicon_err(OE_UNIX, errno, "execv");
|
clicon_err(OE_UNIX, errno, "execv");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -289,7 +301,7 @@ clixon_proc_background(char **argv,
|
||||||
*pid0 = child;
|
*pid0 = child;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
quit:
|
quit:
|
||||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
clicon_debug(1, "%s retval:%d child:%u", __FUNCTION__, retval, child);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -373,13 +385,6 @@ clixon_proc_daemon(char **argv,
|
||||||
/*
|
/*
|
||||||
* Types
|
* 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 */
|
/* List of process callback entries */
|
||||||
static process_entry_t *proc_entry_list = NULL;
|
static process_entry_t *proc_entry_list = NULL;
|
||||||
|
|
@ -398,6 +403,7 @@ int
|
||||||
clixon_process_register(clicon_handle h,
|
clixon_process_register(clicon_handle h,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *netns,
|
const char *netns,
|
||||||
|
proc_cb_t *callback,
|
||||||
char **argv,
|
char **argv,
|
||||||
int argc)
|
int argc)
|
||||||
{
|
{
|
||||||
|
|
@ -436,6 +442,7 @@ clixon_process_register(clicon_handle h,
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pe->pe_callback = callback;
|
||||||
ADDQ(pe, proc_entry_list);
|
ADDQ(pe, proc_entry_list);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -469,15 +476,15 @@ clixon_process_delete_all(clicon_handle h)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
proc_op_run(process_entry_t *pe,
|
proc_op_run(pid_t pid0,
|
||||||
int *runp)
|
int *runp)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int run;
|
int run;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
run = 0;
|
run = 0;
|
||||||
if ((pid = pe->pe_pid) != 0){ /* if 0 stopped */
|
if ((pid = pid0) != 0){ /* if 0 stopped */
|
||||||
/* Check if lives */
|
/* Check if lives */
|
||||||
run = 1;
|
run = 1;
|
||||||
if ((kill(pid, 0)) < 0){
|
if ((kill(pid, 0)) < 0){
|
||||||
|
|
@ -497,11 +504,53 @@ proc_op_run(process_entry_t *pe,
|
||||||
return retval;
|
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] h clicon handle
|
||||||
* @param[in] name Name of process
|
* @param[in] name Name of process
|
||||||
* @param[in] op start, stop.
|
* @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
|
* @param[out] status true if process is running / false if not running on entry
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
|
|
@ -509,13 +558,13 @@ proc_op_run(process_entry_t *pe,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clixon_process_operation(clicon_handle h,
|
clixon_process_operation(clicon_handle h,
|
||||||
char *name,
|
const char *name,
|
||||||
char *op,
|
char *op,
|
||||||
int *status)
|
int wrapit,
|
||||||
|
uint32_t *pid)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
process_entry_t *pe;
|
process_entry_t *pe;
|
||||||
int run;
|
|
||||||
|
|
||||||
clicon_debug(1, "%s name:%s op:%s", __FUNCTION__, name, op);
|
clicon_debug(1, "%s name:%s op:%s", __FUNCTION__, name, op);
|
||||||
if (proc_entry_list == NULL)
|
if (proc_entry_list == NULL)
|
||||||
|
|
@ -523,31 +572,14 @@ clixon_process_operation(clicon_handle h,
|
||||||
pe = proc_entry_list;
|
pe = proc_entry_list;
|
||||||
do {
|
do {
|
||||||
if (strcmp(pe->pe_name, name) == 0){
|
if (strcmp(pe->pe_name, name) == 0){
|
||||||
/* Check if running */
|
/* Call wrapper function that eg changes op based on config */
|
||||||
if (proc_op_run(pe, &run) < 0)
|
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;
|
goto done;
|
||||||
if (status) /* Store as output parameter */
|
if (pid)
|
||||||
*status = run;
|
*pid = pe->pe_pid;
|
||||||
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 */
|
|
||||||
}
|
|
||||||
break; /* hit break here */
|
break; /* hit break here */
|
||||||
}
|
}
|
||||||
pe = NEXTQ(process_entry_t *, pe);
|
pe = NEXTQ(process_entry_t *, pe);
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ memonce(){
|
||||||
'backend')
|
'backend')
|
||||||
valgrindtest=2 # This means backend valgrind test
|
valgrindtest=2 # This means backend valgrind test
|
||||||
: ${DEMWAIT:=10} # valgrind backend needs some time to get up
|
: ${DEMWAIT:=10} # valgrind backend needs some time to get up
|
||||||
|
# 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=yes --log-file=$valgrindfile clixon_backend"
|
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')
|
'restconf')
|
||||||
valgrindtest=3 # This means backend valgrind test
|
valgrindtest=3 # This means backend valgrind test
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ state='{"clixon-example:state":{"op":\["41","42","43"\]}'
|
||||||
if $IPv6; then
|
if $IPv6; then
|
||||||
# For backend config, create 4 sockets, all combinations IPv4/IPv6 + http/https
|
# For backend config, create 4 sockets, all combinations IPv4/IPv6 + http/https
|
||||||
RESTCONFIG=$(cat <<EOF
|
RESTCONFIG=$(cat <<EOF
|
||||||
<restconf xmlns="https://clicon.org/restconf">
|
<restconf xmlns="http://clicon.org/restconf">
|
||||||
<enable>true</enable>
|
<enable>true</enable>
|
||||||
<auth-type>password</auth-type>
|
<auth-type>password</auth-type>
|
||||||
<server-cert-path>$srvcert</server-cert-path>
|
<server-cert-path>$srvcert</server-cert-path>
|
||||||
|
|
@ -90,7 +90,7 @@ EOF
|
||||||
else
|
else
|
||||||
# For backend config, create 4 sockets, all combinations IPv4/IPv6 + http/https
|
# For backend config, create 4 sockets, all combinations IPv4/IPv6 + http/https
|
||||||
RESTCONFIG=$(cat <<EOF
|
RESTCONFIG=$(cat <<EOF
|
||||||
<restconf xmlns="https://clicon.org/restconf">
|
<restconf xmlns="http://clicon.org/restconf">
|
||||||
<enable>true</enable>
|
<enable>true</enable>
|
||||||
<auth-type>password</auth-type>
|
<auth-type>password</auth-type>
|
||||||
<server-cert-path>$srvcert</server-cert-path>
|
<server-cert-path>$srvcert</server-cert-path>
|
||||||
|
|
@ -142,10 +142,12 @@ testrun()
|
||||||
new "kill old restconf daemon"
|
new "kill old restconf daemon"
|
||||||
stop_restconf_pre
|
stop_restconf_pre
|
||||||
|
|
||||||
new "start restconf daemon ZZZ"
|
new "start restconf daemon"
|
||||||
echo "cfg:$cfg"
|
echo "cfg:$cfg"
|
||||||
start_restconf -f $cfg
|
start_restconf -f $cfg
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "wait restconf"
|
new "wait restconf"
|
||||||
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"}\]}'
|
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"
|
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"
|
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"
|
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\]"
|
addrs="$addrs \[::1\]"
|
||||||
fi
|
fi
|
||||||
for addr in $addrs; do
|
for addr in $addrs; do
|
||||||
new "restconf test: proto:$proto addr:$addr config:$config"
|
new "restconf test: proto:$proto addr:$addr"
|
||||||
testrun $proto $addr
|
testrun $proto $addr
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
|
||||||
|
|
@ -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
|
# This just catches the header and the jukebox module, the RFC has foo and bar which
|
||||||
# seems wrong to recreate
|
# seems wrong to recreate
|
||||||
new "B.1.2. Retrieve the Server Module Information"
|
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"
|
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' '<capabilities xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf-monitoring"><capability>urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=explicit</capability><capability>urn:ietf:params:restconf:capability:depth</capability>
|
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' '<capabilities xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf-monitoring"><capability>urn:ietf:params:restconf:capability:defaults:1.0?basic-mode=explicit</capability><capability>urn:ietf:params:restconf:capability:depth</capability>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Restconf direct start/stop using RPC (as alternative to systemd or other)
|
# Restconf direct start/stop using RPC and config enable flag (as alternative to systemd or other)
|
||||||
# Also try ip netns
|
# 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)
|
# Magic line must be first in script (see README.md)
|
||||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
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
|
APPNAME=example
|
||||||
|
|
||||||
cfg=$dir/conf.xml
|
cfg=$dir/conf.xml
|
||||||
|
startupdb=$dir/startup_db
|
||||||
# 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
|
|
||||||
|
|
||||||
cat <<EOF > $cfg
|
cat <<EOF > $cfg
|
||||||
<clixon-config xmlns="http://clicon.org/config">
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
|
<CLICON_FEATURE>ietf-netconf:startup</CLICON_FEATURE>
|
||||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||||
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
||||||
<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>
|
<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>
|
||||||
|
|
@ -31,7 +32,7 @@ cat <<EOF > $cfg
|
||||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
|
||||||
<CLICON_MODULE_LIBRARY_RFC7895>true</CLICON_MODULE_LIBRARY_RFC7895>
|
<CLICON_MODULE_LIBRARY_RFC7895>true</CLICON_MODULE_LIBRARY_RFC7895>
|
||||||
<!-- start restconf from backend -->
|
<!-- start restconf from backend -->
|
||||||
<CLICON_BACKEND_RESTCONF_PROCESS>true</CLICON_BACKEND_RESTCONF_PROCESS>
|
<CLICON_BACKEND_RESTCONF_PROCESS>true</CLICON_BACKEND_RESTCONF_PROCESS>
|
||||||
|
|
@ -39,6 +40,72 @@ cat <<EOF > $cfg
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
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<<EOF
|
||||||
|
<rpc $DEFAULTNS>
|
||||||
|
<process-control xmlns="http://clicon.org/lib">
|
||||||
|
<name>restconf</name>
|
||||||
|
<operation>$operation</operation>
|
||||||
|
</process-control>
|
||||||
|
</rpc>]]>]]>
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
expect1="<rpc-reply $DEFAULTNS><pid xmlns=\"http://clicon.org/lib\">"
|
||||||
|
match=$(echo "$ret" | grep --null -Go "$expect1")
|
||||||
|
if [ -z "$match" ]; then
|
||||||
|
err "$expect1" "$ret"
|
||||||
|
fi
|
||||||
|
|
||||||
|
expect2="</pid></rpc-reply>]]>]]>"
|
||||||
|
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<<EOF > $startupdb
|
||||||
|
<config>
|
||||||
|
<restconf xmlns="http://clicon.org/restconf">
|
||||||
|
<enable>true</enable>
|
||||||
|
</restconf>
|
||||||
|
</config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "kill old restconf"
|
||||||
|
stop_restconf_pre
|
||||||
|
|
||||||
new "test params: -f $cfg"
|
new "test params: -f $cfg"
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
new "kill old backend"
|
new "kill old backend"
|
||||||
|
|
@ -46,92 +113,82 @@ if [ $BE -ne 0 ]; then
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
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
|
wait_backend
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "kill old restconf"
|
# Get pid of running process and check return xml
|
||||||
stop_restconf_pre
|
new "Get rpc status"
|
||||||
|
pid0=$(testrpc status 1)
|
||||||
|
if [ $? -ne 0 ]; then exit -1; fi
|
||||||
|
|
||||||
new "1)check no restconf"
|
new "check restconf process running using ps pid0:$pid0"
|
||||||
ps=$(ps aux|grep "$WWWDIR/clixon_restconf" | grep -v grep)
|
ps=$(ps -hp $pid0)
|
||||||
if [ -n "$ps" ]; then
|
|
||||||
err "No restconf running" "$ps"
|
|
||||||
fi
|
|
||||||
|
|
||||||
new "2)check status off"
|
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><process-control xmlns=\"http://clicon.org/lib\"><name>restconf</name><operation>status</operation></process-control></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><status xmlns=\"http://clicon.org/lib\">false</status></rpc-reply>]]>]]>"
|
|
||||||
|
|
||||||
new "start restconf"
|
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><process-control xmlns=\"http://clicon.org/lib\"><name>restconf</name><operation>start</operation></process-control></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>"
|
|
||||||
|
|
||||||
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 "<rpc $DEFAULTNS><process-control xmlns=\"http://clicon.org/lib\"><name>restconf</name><operation>status</operation></process-control></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><status xmlns=\"http://clicon.org/lib\">true</status></rpc-reply>]]>]]>"
|
|
||||||
|
|
||||||
new "stop restconf"
|
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><process-control xmlns=\"http://clicon.org/lib\"><name>restconf</name><operation>stop</operation></process-control></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>"
|
|
||||||
|
|
||||||
new "start restconf again"
|
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><process-control xmlns=\"http://clicon.org/lib\"><name>restconf</name><operation>start</operation></process-control></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>"
|
|
||||||
|
|
||||||
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
|
if [ -z "$ps" ]; then
|
||||||
err "A restconf running"
|
err "A restconf running"
|
||||||
fi
|
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"
|
new "kill restconf"
|
||||||
stop_restconf_pre
|
stop_restconf_pre
|
||||||
|
|
||||||
new "6)check no restconf"
|
new "start restconf RPC"
|
||||||
ps=$(ps aux|grep "$WWWDIR/clixon_restconf" | grep -v grep)
|
pid4=$(testrpc start 1)
|
||||||
if [ -n "$ps" ]; then
|
if [ $? -ne 0 ]; then exit -1; fi
|
||||||
err "No restconf running" "$ps"
|
|
||||||
|
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
|
fi
|
||||||
|
|
||||||
new "restart restconf"
|
#if [ $valgrindtest -eq 0 ]; then # Cant get pgrep to work properly
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><process-control xmlns=\"http://clicon.org/lib\"><name>restconf</name><operation>restart</operation></process-control></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>"
|
# new "check new pid"
|
||||||
|
# sleep $DEMWAIT # Slows the tests down considerably, but needed in eg docker test
|
||||||
new "7)check status on"
|
# pid1=$(pgrep clixon_restconf)
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><process-control xmlns=\"http://clicon.org/lib\"><name>restconf</name><operation>status</operation></process-control></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><status xmlns=\"http://clicon.org/lib\">true</status></rpc-reply>]]>]]>"
|
# if [ -z "$pid0" -o -z "$pid1" ]; then
|
||||||
|
# err "Pids expected" "pid0:$pid0 = pid1:$pid1"
|
||||||
if [ $valgrindtest -eq 0 ]; then # Cant get pgrep to work properly
|
# fi
|
||||||
sleep $DEMWAIT # Slows the tests down considerably, but needed in eg docker test
|
# if [ $pid0 -eq $pid1 ]; then#
|
||||||
fi
|
# err "Different pids" "pid0:$pid0 = pid1:$pid1"
|
||||||
pid0=$(pgrep clixon_restconf)
|
# fi
|
||||||
|
#fi
|
||||||
new "restart restconf"
|
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><process-control xmlns=\"http://clicon.org/lib\"><name>restconf</name><operation>restart</operation></process-control></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>"
|
|
||||||
|
|
||||||
new "8)check status on"
|
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><process-control xmlns=\"http://clicon.org/lib\"><name>restconf</name><operation>status</operation></process-control></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><status xmlns=\"http://clicon.org/lib\">true</status></rpc-reply>]]>]]>"
|
|
||||||
|
|
||||||
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 [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
|
|
@ -142,19 +199,70 @@ if [ $BE -ne 0 ]; then
|
||||||
fi
|
fi
|
||||||
# kill backend
|
# kill backend
|
||||||
stop_backend -f $cfg
|
stop_backend -f $cfg
|
||||||
|
fi
|
||||||
|
|
||||||
# XXX Cant get this to work in docker/alpine
|
# So far, no restconf config enable flag has been true. Now change enable flag.
|
||||||
if false; then
|
|
||||||
new "10)check no restconf"
|
new "ENABLE false"
|
||||||
sleep $DEMWAIT
|
# Second basic operation with restconf enable is false
|
||||||
ps=$(ps aux|grep "$WWWDIR/clixon_restconf" | grep -v grep)
|
cat<<EOF > $startupdb
|
||||||
if [ -n "$ps" ]; then
|
<config>
|
||||||
err "No restconf running" "$ps"
|
<restconf xmlns="http://clicon.org/restconf">
|
||||||
fi
|
<enable>false</enable>
|
||||||
|
</restconf>
|
||||||
|
</config>
|
||||||
|
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
|
fi
|
||||||
|
new "start backend -s startup -f $cfg"
|
||||||
|
start_backend -s startup -f $cfg
|
||||||
|
|
||||||
|
new "waiting"
|
||||||
|
wait_backend
|
||||||
fi
|
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 "<rpc $DEFAULTNS><edit-config><default-operation>merge</default-operation><target><candidate/></target><config><restconf xmlns=\"http://clicon.org/restconf\"><enable>true</enable></restconf></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf commit"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
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 "<rpc $DEFAULTNS><edit-config><default-operation>merge</default-operation><target><candidate/></target><config><restconf xmlns=\"http://clicon.org/restconf\"><enable>false</enable></restconf></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf commit"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
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
|
# Now in a separate network namespace
|
||||||
new "restconf rpc in network namespace"
|
new "restconf rpc in network namespace"
|
||||||
|
|
@ -207,3 +315,4 @@ sudo ip netns delete $netns
|
||||||
fi # namespaces
|
fi # namespaces
|
||||||
|
|
||||||
rm -rf $dir
|
rm -rf $dir
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,7 @@ cat <<EOF > $dir/startup_db
|
||||||
</config>
|
</config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
MODSTATE1='<modules-state xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library"><module-set-id>0</module-set-id><module><name>clixon-lib</name><revision>2020-12-08</revision><namespace>http://clicon.org/lib</namespace></module>'
|
MODSTATE1='<modules-state xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library"><module-set-id>0</module-set-id><module><name>clixon-lib</name><revision>2020-12-30</revision><namespace>http://clicon.org/lib</namespace></module>'
|
||||||
|
|
||||||
MODSTATE2='<module><name>interfaces</name><revision>2018-02-20</revision><namespace>urn:example:interfaces</namespace></module>'
|
MODSTATE2='<module><name>interfaces</name><revision>2018-02-20</revision><namespace>urn:example:interfaces</namespace></module>'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,8 @@ datarootdir = @datarootdir@
|
||||||
# See also OPT_YANG_INSTALLDIR for the standard yang files
|
# See also OPT_YANG_INSTALLDIR for the standard yang files
|
||||||
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
||||||
|
|
||||||
YANGSPECS = clixon-config@2020-11-03.yang
|
YANGSPECS = clixon-config@2020-12-30.yang
|
||||||
YANGSPECS += clixon-lib@2020-12-08.yang
|
YANGSPECS += clixon-lib@2020-12-30.yang
|
||||||
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
||||||
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
||||||
YANGSPECS += clixon-restconf@2020-10-30.yang
|
YANGSPECS += clixon-restconf@2020-10-30.yang
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
clixon-config@2020-10-01.yang
|
clixon-config@2020-12-30.yang
|
||||||
|
|
@ -3,6 +3,9 @@ module clixon-config {
|
||||||
namespace "http://clicon.org/config";
|
namespace "http://clicon.org/config";
|
||||||
prefix cc;
|
prefix cc;
|
||||||
|
|
||||||
|
import clixon-restconf {
|
||||||
|
prefix clrc;
|
||||||
|
}
|
||||||
organization
|
organization
|
||||||
"Clicon / Clixon";
|
"Clicon / Clixon";
|
||||||
|
|
||||||
|
|
@ -40,9 +43,33 @@ module clixon-config {
|
||||||
|
|
||||||
***** END LICENSE BLOCK *****";
|
***** 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 {
|
revision 2020-10-01 {
|
||||||
description
|
description
|
||||||
"Added: CLICON_CONFIGDIR";
|
"Added: CLICON_CONFIGDIR.";
|
||||||
}
|
}
|
||||||
revision 2020-08-17 {
|
revision 2020-08-17 {
|
||||||
description
|
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 clixon-config {
|
||||||
|
container restconf {
|
||||||
|
uses clrc:clixon-restconf;
|
||||||
|
}
|
||||||
leaf-list CLICON_FEATURE {
|
leaf-list CLICON_FEATURE {
|
||||||
description
|
description
|
||||||
"Supported features as used by YANG feature/if-feature
|
"Supported features as used by YANG feature/if-feature
|
||||||
|
|
@ -392,7 +433,8 @@ module clixon-config {
|
||||||
default "/www-data/fastcgi_restconf.sock";
|
default "/www-data/fastcgi_restconf.sock";
|
||||||
description
|
description
|
||||||
"FastCGI unix socket. Should be specified in webserver
|
"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 {
|
leaf CLICON_RESTCONF_PRETTY {
|
||||||
type boolean;
|
type boolean;
|
||||||
|
|
@ -407,58 +449,6 @@ module clixon-config {
|
||||||
Setting this value to false makes restconf return not pretty-printed
|
Setting this value to false makes restconf return not pretty-printed
|
||||||
which may be desirable for performance or tests";
|
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 <port>
|
|
||||||
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 <port>
|
|
||||||
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 {
|
leaf CLICON_CLI_DIR {
|
||||||
type string;
|
type string;
|
||||||
description
|
description
|
||||||
|
|
@ -624,15 +614,15 @@ module clixon-config {
|
||||||
from a spec, such as in the autocli.";
|
from a spec, such as in the autocli.";
|
||||||
}
|
}
|
||||||
leaf CLICON_SOCK_FAMILY {
|
leaf CLICON_SOCK_FAMILY {
|
||||||
type string;
|
type socket_address_family;
|
||||||
default "UNIX";
|
default UNIX;
|
||||||
description
|
description
|
||||||
"Address family for communicating with clixon_backend
|
"Address family for communicating with clixon_backend with one of:
|
||||||
(UNIX|IPv4). IPv6 not yet implemented.
|
Note IPv6 not implemented.
|
||||||
Note that UNIX socket makes credential check as follows:
|
Note that UNIX socket makes credential check as follows:
|
||||||
(1) client needs rw access to the socket
|
(1) client needs rw access to the socket
|
||||||
(2) NACM credentials can be checked according to CLICON_NACM_CREDENTIALS
|
(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 {
|
leaf CLICON_SOCK {
|
||||||
|
|
@ -681,6 +671,20 @@ module clixon-config {
|
||||||
mandatory true;
|
mandatory true;
|
||||||
description "Process-id file of backend daemon";
|
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 {
|
leaf CLICON_AUTOCOMMIT {
|
||||||
type int32;
|
type int32;
|
||||||
default 0;
|
default 0;
|
||||||
183
yang/clixon/clixon-lib@2020-12-30.yang
Normal file
183
yang/clixon/clixon-lib@2020-12-30.yang
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
module clixon-lib {
|
||||||
|
yang-version 1.1;
|
||||||
|
namespace "http://clicon.org/lib";
|
||||||
|
prefix cl;
|
||||||
|
|
||||||
|
organization
|
||||||
|
"Clicon / Clixon";
|
||||||
|
|
||||||
|
contact
|
||||||
|
"Olof Hagsand <olof@hagsand.se>";
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
module clixon-restconf {
|
module clixon-restconf {
|
||||||
yang-version 1.1;
|
yang-version 1.1;
|
||||||
namespace "https://clicon.org/restconf";
|
namespace "http://clicon.org/restconf";
|
||||||
prefix "clrc";
|
prefix "clrc";
|
||||||
|
|
||||||
import ietf-inet-types {
|
import ietf-inet-types {
|
||||||
|
|
@ -124,6 +124,13 @@ module clixon-restconf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
container 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";
|
presence "Enables RESTCONF";
|
||||||
uses clixon-restconf;
|
uses clixon-restconf;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue