- Rewrote process control to simpler state model: stopped/running/exiting
- Stricter CLICON_BACKEND_RESTCONF_PROCESS : - if set, restconf daemon queries backend for its config - if not set, restconf daemon reads its config from main config file
This commit is contained in:
parent
9f5176adf5
commit
953326d39f
11 changed files with 517 additions and 310 deletions
|
|
@ -37,8 +37,10 @@ Expected: April
|
||||||
### API changes on existing protocol/config features
|
### API changes on existing protocol/config features
|
||||||
|
|
||||||
* Native RESTCONF mode
|
* Native RESTCONF mode
|
||||||
* Restconf "evhtp" mode MUST use libevhtp from https://github.com/clixon/clixon-libevhtp.git instead from criticalstack
|
* Renamed restconf "evhtp" mode to "native" mode
|
||||||
* To configure native mode use: `configure --with-restconf=native`, changed from: `configure --with-restconf=evhtp`
|
* To configure native mode use: `configure --with-restconf=native`, changed from: `configure --with-restconf=evhtp`
|
||||||
|
* Native mode MUST use libevhtp from https://github.com/clixon/clixon-libevhtp.git instead from criticalstack
|
||||||
|
|
||||||
* NETCONF Hello message semantics has been made stricter according to RFC 6241 Sec 8.1, for example:
|
* NETCONF Hello message semantics has been made stricter according to RFC 6241 Sec 8.1, for example:
|
||||||
* A client MUST send a <hello> element.
|
* A client MUST send a <hello> element.
|
||||||
* Each peer MUST send at least the base NETCONF capability, "urn:ietf:params:netconf:base:1.1" (or 1.0 for RFC 4741)
|
* Each peer MUST send at least the base NETCONF capability, "urn:ietf:params:netconf:base:1.1" (or 1.0 for RFC 4741)
|
||||||
|
|
@ -46,6 +48,7 @@ Expected: April
|
||||||
* You can set `CLICON_NETCONF_HELLO_OPTIONAL` to true to use the old behavior of essentially ignoring hellos.
|
* You can set `CLICON_NETCONF_HELLO_OPTIONAL` to true to use the old behavior of essentially ignoring hellos.
|
||||||
* New clixon-lib@2020-03-08.yang revision
|
* New clixon-lib@2020-03-08.yang revision
|
||||||
* Changed: RPC process-control output to choice with status fields
|
* Changed: RPC process-control output to choice with status fields
|
||||||
|
* The fields are: active, description, command, status, starttime, pid (or just ok).
|
||||||
* New clixon-config@2020-03-08.yang revision
|
* New clixon-config@2020-03-08.yang revision
|
||||||
* Added: `CLICON_NETCONF_HELLO_OPTIONAL`
|
* Added: `CLICON_NETCONF_HELLO_OPTIONAL`
|
||||||
* Added: `CLICON_CLI_AUTOCLI_EXCLUDE`
|
* Added: `CLICON_CLI_AUTOCLI_EXCLUDE`
|
||||||
|
|
|
||||||
|
|
@ -238,12 +238,14 @@ restconf_pseudo_process_commit(clicon_handle h,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xtarget;
|
cxobj *xtarget;
|
||||||
|
cxobj *xsource;
|
||||||
cxobj *cx;
|
cxobj *cx;
|
||||||
int enabled = 0;
|
int enabled = 0;
|
||||||
cxobj *xb;
|
cxobj *xb;
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
xtarget = transaction_target(td);
|
xtarget = transaction_target(td);
|
||||||
|
xsource = transaction_src(td);
|
||||||
if (xpath_first(xtarget, NULL, "/restconf[enable='true']") != NULL)
|
if (xpath_first(xtarget, NULL, "/restconf[enable='true']") != NULL)
|
||||||
enabled++;
|
enabled++;
|
||||||
/* Get debug flag of restconf config, set the restconf start -D daemon flag according
|
/* Get debug flag of restconf config, set the restconf start -D daemon flag according
|
||||||
|
|
@ -271,10 +273,18 @@ restconf_pseudo_process_commit(clicon_handle h,
|
||||||
/* A restart can terminate a restconf connection (cut the tree limb you are sitting on)
|
/* A restart can terminate a restconf connection (cut the tree limb you are sitting on)
|
||||||
* Specifically, the socket is terminated where the reply is sent, which will
|
* Specifically, the socket is terminated where the reply is sent, which will
|
||||||
* cause the curl to fail.
|
* cause the curl to fail.
|
||||||
|
* Note that it should really be a START if the process is stopped, but the
|
||||||
|
* commit code need not know any of that
|
||||||
*/
|
*/
|
||||||
if (clixon_process_operation(h, RESTCONF_PROCESS, PROC_OP_RESTART, 0) < 0)
|
if (clixon_process_operation(h, RESTCONF_PROCESS, PROC_OP_RESTART, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
else if ((cx = xpath_first(xsource, NULL, "/restconf")) != NULL &&
|
||||||
|
xml_flag(cx, XML_FLAG_CHANGE|XML_FLAG_DEL)){
|
||||||
|
/* Or something deleted */
|
||||||
|
if (clixon_process_operation(h, RESTCONF_PROCESS, PROC_OP_RESTART, 0) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
|
||||||
|
|
@ -431,15 +431,17 @@ main(int argc,
|
||||||
if (clixon_plugin_start_all(h) < 0)
|
if (clixon_plugin_start_all(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* First try to get restconf config from local config-file */
|
if (clicon_option_bool(h, "CLICON_BACKEND_RESTCONF_PROCESS") == 0){
|
||||||
if ((xrestconf1 = clicon_conf_restconf(h)) != NULL){
|
/* If not read from backend, try to get restconf config from local config-file */
|
||||||
if ((ret = restconf_config_init(h, xrestconf1)) < 0)
|
if ((xrestconf1 = clicon_conf_restconf(h)) != NULL){
|
||||||
goto done;
|
if ((ret = restconf_config_init(h, xrestconf1)) < 0)
|
||||||
if (ret == 1)
|
goto done;
|
||||||
configure_done = 1;
|
if (ret == 1)
|
||||||
|
configure_done = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* If no local config, or it is disabled, try to query backend of config. */
|
/* If no local config, or it is disabled, try to query backend of config. */
|
||||||
if (!configure_done){
|
else {
|
||||||
/* Loop to wait for backend starting, try again if not done */
|
/* Loop to wait for backend starting, try again if not done */
|
||||||
while (1){
|
while (1){
|
||||||
if (clicon_hello_req(h, &id) < 0){
|
if (clicon_hello_req(h, &id) < 0){
|
||||||
|
|
|
||||||
|
|
@ -1610,24 +1610,25 @@ restconf_clixon_init(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_nsctx_global_set(h, nsctx_global) < 0)
|
if (clicon_nsctx_global_set(h, nsctx_global) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* First try to get restconf config from local config-file */
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if ((xrestconf = clicon_conf_restconf(h)) != NULL){
|
if (clicon_option_bool(h, "CLICON_BACKEND_RESTCONF_PROCESS") == 0){
|
||||||
/*! Basic config init, set auth-type, pretty, etc ret 0 means disabled */
|
/* If not read from backend, try to get restconf config from local config-file */
|
||||||
if ((ret = restconf_config_init(h, xrestconf)) < 0)
|
if ((xrestconf = clicon_conf_restconf(h)) != NULL){
|
||||||
goto done;
|
/*! Basic config init, set auth-type, pretty, etc ret 0 means disabled */
|
||||||
/* ret == 1 means this config is OK */
|
if ((ret = restconf_config_init(h, xrestconf)) < 0)
|
||||||
if (ret == 0){
|
|
||||||
xrestconf = NULL; /* Dont free since it is part of conf tree */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if ((*xrestconfp = xml_dup(xrestconf)) == NULL)
|
|
||||||
goto done;
|
goto done;
|
||||||
|
/* ret == 1 means this config is OK */
|
||||||
|
if (ret == 0){
|
||||||
|
xrestconf = NULL; /* Dont free since it is part of conf tree */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ((*xrestconfp = xml_dup(xrestconf)) == NULL)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* If no local config, or it is disabled, try to query backend of config. */
|
/* If no local config, or it is disabled, try to query backend of config.
|
||||||
if (ret == 0){
|
*/
|
||||||
assert(*xrestconfp == NULL);
|
else {
|
||||||
if ((ret = restconf_clixon_backend(h, xrestconfp)) < 0)
|
if ((ret = restconf_clixon_backend(h, xrestconfp)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
|
|
|
||||||
|
|
@ -34,20 +34,48 @@
|
||||||
***** END LICENSE BLOCK *****
|
***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
* Processes daemons
|
* Processes daemons
|
||||||
* States of processes:
|
|
||||||
A description of process states.
|
A description of process states.
|
||||||
It starts in a STOPPED state. On operation "start" or "restart" it gets a pid and goes into RUNNING:
|
An entity is a process_entry_t with a unique name. pids are created for "active" processes.
|
||||||
STOPPED --(re)start--> RUNNING
|
States:
|
||||||
In RUNNING several things can happen:
|
STOPPED: pid=0, No process running
|
||||||
- It is killed externally: the process then gets a SIGCHLD which triggers a wait and it goes into STOPPED:
|
RUNNING: pid set, Process started and believed to be running
|
||||||
RUNNING --sigchld/wait--> STOPPED
|
EXITING: pid set, Process is killed by parent but not waited for
|
||||||
It is stopped due to an rpc or by config commit removing the config. In that case the parent
|
|
||||||
process kills the process and enters into EXITING waiting for a SIGCHLD that triggers a wait:
|
Operations:
|
||||||
RUNNING --stop--> EXITING --sigchld/wait--> STOPPED
|
start, stop, restart
|
||||||
It is restarted due to an rpc or config change (eg a server is added, a key modified, etc). Then
|
|
||||||
a new process is started which enters RUNNING, while the old process (the dying clone) enters EXITING:
|
Transitions:
|
||||||
STOPPED --restart--> RUNNING(newpid)
|
Process struct created by calling clixon_process_register() with static info such as name,
|
||||||
RUNNING --stop--> EXITING --sigchld/wait--> REMOVED (oldpid/clone)
|
description, namespace, start arguments, etc. Starts in STOPPED state:
|
||||||
|
--> STOPPED
|
||||||
|
|
||||||
|
On operation "start" or "restart" it gets a pid and goes into RUNNING state:
|
||||||
|
STOPPED -- (re)start --> RUNNING(pid)
|
||||||
|
|
||||||
|
When running, several things may happen:
|
||||||
|
1. It is killed externally: the process gets a SIGCHLD triggers a wait and it goes to STOPPED:
|
||||||
|
RUNNING --sigchld/wait--> STOPPED
|
||||||
|
|
||||||
|
2. It is stopped due to a rpc or configuration remove:
|
||||||
|
The parent kills the process and enters EXITING waiting for a SIGCHLD that triggers a wait,
|
||||||
|
therafter it goes to STOPPED
|
||||||
|
RUNNING --stop--> EXITING --sigchld/wait--> STOPPED
|
||||||
|
|
||||||
|
3. It is restarted due to rpc or config change (eg a server is added, a key modified, etc).
|
||||||
|
The parent kills the process and enters EXITING waiting for a SIGCHLD that triggers a wait,
|
||||||
|
therafter a new process is started and it goes to RUNNING with a new pid
|
||||||
|
|
||||||
|
RUNNING --restart--> EXITING --sigchld/wait + restart --> RUNNING(pid)
|
||||||
|
|
||||||
|
A complete state diagram is:
|
||||||
|
|
||||||
|
STOPPED --(re)start--> RUNNING(pid)
|
||||||
|
^ <--1.wait(kill)--- | ^
|
||||||
|
| stop/| |
|
||||||
|
| restart| | restart
|
||||||
|
| v |
|
||||||
|
wait(stop) ------- EXITING(dying pid)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
|
|
@ -98,6 +126,14 @@
|
||||||
/*
|
/*
|
||||||
* Types
|
* Types
|
||||||
*/
|
*/
|
||||||
|
/* Process state
|
||||||
|
*/
|
||||||
|
enum proc_state {
|
||||||
|
PROC_STATE_STOPPED,
|
||||||
|
PROC_STATE_RUNNING,
|
||||||
|
PROC_STATE_EXITING
|
||||||
|
};
|
||||||
|
typedef enum proc_state proc_state_t;
|
||||||
|
|
||||||
/* Process entry list */
|
/* Process entry list */
|
||||||
struct process_entry_t {
|
struct process_entry_t {
|
||||||
|
|
@ -108,10 +144,9 @@ struct process_entry_t {
|
||||||
char **pe_argv; /* argv with command as element 0 and NULL-terminated */
|
char **pe_argv; /* argv with command as element 0 and NULL-terminated */
|
||||||
int pe_argc; /* Length of argc */
|
int pe_argc; /* Length of argc */
|
||||||
pid_t pe_pid; /* Running process id (state) or 0 if dead (pid is set if exiting=1) */
|
pid_t pe_pid; /* Running process id (state) or 0 if dead (pid is set if exiting=1) */
|
||||||
int pe_exiting; /* If set process is in the process of dying needs reaping */
|
proc_operation pe_operation;/* Pending operation: stop/start/restart */
|
||||||
int pe_clone; /* Duplicate when restarting, delete when reaped */
|
proc_state_t pe_state; /* stopped, running, exiting */
|
||||||
pid_t pe_status; /* Status on exit as defined in waitpid */
|
pid_t pe_exit_status;/* Status on exit as defined in waitpid */
|
||||||
proc_operation pe_op; /* Operation pending? */
|
|
||||||
struct timeval pe_starttime; /* Start time */
|
struct timeval pe_starttime; /* Start time */
|
||||||
proc_cb_t *pe_callback; /* Wrapper function, may be called from process_operation */
|
proc_cb_t *pe_callback; /* Wrapper function, may be called from process_operation */
|
||||||
};
|
};
|
||||||
|
|
@ -307,14 +342,21 @@ clixon_proc_background(char **argv,
|
||||||
* Process management: start/stop registered processes for internal use
|
* Process management: start/stop registered processes for internal use
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static const map_str2int proc_state_map[] = {
|
||||||
|
{"stopped", PROC_STATE_STOPPED},
|
||||||
|
{"running", PROC_STATE_RUNNING},
|
||||||
|
{"exiting", PROC_STATE_EXITING},
|
||||||
|
{NULL, -1}
|
||||||
|
};
|
||||||
|
|
||||||
/* Process operations
|
/* Process operations
|
||||||
*/
|
*/
|
||||||
static const map_str2int proc_operation_map[] = {
|
static const map_str2int proc_operation_map[] = {
|
||||||
{"none", PROC_OP_NONE},
|
{"none", PROC_OP_NONE}, /* Not state transition operator */
|
||||||
{"start", PROC_OP_START},
|
{"start", PROC_OP_START}, /* State transition operator */
|
||||||
{"stop", PROC_OP_STOP},
|
{"stop", PROC_OP_STOP}, /* State transition operator */
|
||||||
{"restart", PROC_OP_RESTART},
|
{"restart", PROC_OP_RESTART},/* State transition operator */
|
||||||
{"status", PROC_OP_STATUS},
|
{"status", PROC_OP_STATUS}, /* Not state transition operator */
|
||||||
{NULL, -1}
|
{NULL, -1}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -356,6 +398,7 @@ clixon_process_argv_get(clicon_handle h,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NYI
|
||||||
/*! Make a copy of process-entry struct
|
/*! Make a copy of process-entry struct
|
||||||
*
|
*
|
||||||
* @param[in] pe0 Original process-entry
|
* @param[in] pe0 Original process-entry
|
||||||
|
|
@ -415,6 +458,7 @@ clixon_process_register_dup(process_entry_t *pe0,
|
||||||
/* dealloc pe1 on error */
|
/* dealloc pe1 on error */
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*! Register an internal process
|
/*! Register an internal process
|
||||||
*
|
*
|
||||||
|
|
@ -480,6 +524,11 @@ clixon_process_register(clicon_handle h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pe->pe_callback = callback;
|
pe->pe_callback = callback;
|
||||||
|
clicon_debug(1, "%s %s ----> %s", __FUNCTION__,
|
||||||
|
pe->pe_name,
|
||||||
|
clicon_int2str(proc_state_map, PROC_STATE_STOPPED)
|
||||||
|
);
|
||||||
|
pe->pe_state = PROC_STATE_STOPPED;
|
||||||
ADDQ(pe, _proc_entry_list);
|
ADDQ(pe, _proc_entry_list);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -557,7 +606,7 @@ proc_op_run(pid_t pid0,
|
||||||
*
|
*
|
||||||
* @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, restart, status
|
* @param[in] op0 start, stop, restart, status
|
||||||
* @param[in] wrapit If set, call potential callback, if false, dont call it
|
* @param[in] wrapit If set, call potential callback, if false, dont call it
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
|
|
@ -570,11 +619,12 @@ proc_op_run(pid_t pid0,
|
||||||
int
|
int
|
||||||
clixon_process_operation(clicon_handle h,
|
clixon_process_operation(clicon_handle h,
|
||||||
const char *name,
|
const char *name,
|
||||||
proc_operation op,
|
proc_operation op0,
|
||||||
int wrapit)
|
int wrapit)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
process_entry_t *pe;
|
process_entry_t *pe;
|
||||||
|
proc_operation op;
|
||||||
int sched = 0; /* If set, process action should be scheduled, register a timeout */
|
int sched = 0; /* If set, process action should be scheduled, register a timeout */
|
||||||
|
|
||||||
clicon_debug(1, "%s name:%s op:%s", __FUNCTION__, name, clicon_int2str(proc_operation_map, op));
|
clicon_debug(1, "%s name:%s op:%s", __FUNCTION__, name, clicon_int2str(proc_operation_map, op));
|
||||||
|
|
@ -583,17 +633,22 @@ 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){
|
||||||
/* Call wrapper function that eg changes op based on config */
|
/* Call wrapper function that eg changes op1 based on config */
|
||||||
|
op = op0;
|
||||||
if (wrapit && pe->pe_callback != NULL)
|
if (wrapit && pe->pe_callback != NULL)
|
||||||
if (pe->pe_callback(h, pe, &op) < 0)
|
if (pe->pe_callback(h, pe, &op) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_debug(1, "%s name: %s pid:%d op: %s", __FUNCTION__,
|
|
||||||
name, pe->pe_pid, clicon_int2str(proc_operation_map, op));
|
|
||||||
if (op == PROC_OP_START || op == PROC_OP_STOP || op == PROC_OP_RESTART){
|
if (op == PROC_OP_START || op == PROC_OP_STOP || op == PROC_OP_RESTART){
|
||||||
pe->pe_op = op;
|
pe->pe_operation = op;
|
||||||
clicon_debug(1, "%s scheduling %s pid:%d", __FUNCTION__, name, pe->pe_pid);
|
clicon_debug(1, "%s scheduling name: %s pid:%d op: %s", __FUNCTION__,
|
||||||
|
name, pe->pe_pid,
|
||||||
|
clicon_int2str(proc_operation_map, pe->pe_operation));
|
||||||
sched++;
|
sched++;
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
clicon_debug(1, "%s name:%s op %s cancelled by wrwap", __FUNCTION__, name, clicon_int2str(proc_operation_map, op0));
|
||||||
|
}
|
||||||
break; /* hit break here */
|
break; /* hit break here */
|
||||||
}
|
}
|
||||||
pe = NEXTQ(process_entry_t *, pe);
|
pe = NEXTQ(process_entry_t *, pe);
|
||||||
|
|
@ -632,8 +687,6 @@ clixon_process_status(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){
|
||||||
if (pe->pe_clone)
|
|
||||||
continue; /* this may be a dying duplicate */
|
|
||||||
/* Check if running */
|
/* Check if running */
|
||||||
run = 0;
|
run = 0;
|
||||||
if (pe->pe_pid && proc_op_run(pe->pe_pid, &run) < 0)
|
if (pe->pe_pid && proc_op_run(pe->pe_pid, &run) < 0)
|
||||||
|
|
@ -642,8 +695,6 @@ clixon_process_status(clicon_handle h,
|
||||||
NETCONF_BASE_NAMESPACE, CLIXON_LIB_NS, run?"true":"false");
|
NETCONF_BASE_NAMESPACE, CLIXON_LIB_NS, run?"true":"false");
|
||||||
if (pe->pe_description)
|
if (pe->pe_description)
|
||||||
cprintf(cbret, "<description xmlns=\"%s\">%s</description>", CLIXON_LIB_NS, pe->pe_description);
|
cprintf(cbret, "<description xmlns=\"%s\">%s</description>", CLIXON_LIB_NS, pe->pe_description);
|
||||||
if (pe->pe_pid)
|
|
||||||
cprintf(cbret, "<pid xmlns=\"%s\">%u</pid>", CLIXON_LIB_NS, pe->pe_pid);
|
|
||||||
cprintf(cbret, "<command xmlns=\"%s\">", CLIXON_LIB_NS);
|
cprintf(cbret, "<command xmlns=\"%s\">", CLIXON_LIB_NS);
|
||||||
for (i=0; i<pe->pe_argc-1; i++){
|
for (i=0; i<pe->pe_argc-1; i++){
|
||||||
if (i)
|
if (i)
|
||||||
|
|
@ -651,13 +702,17 @@ clixon_process_status(clicon_handle h,
|
||||||
cprintf(cbret, "%s", pe->pe_argv[i]);
|
cprintf(cbret, "%s", pe->pe_argv[i]);
|
||||||
}
|
}
|
||||||
cprintf(cbret, "</command>");
|
cprintf(cbret, "</command>");
|
||||||
if (run && timerisset(&pe->pe_starttime)){
|
cprintf(cbret, "<status xmlns=\"%s\">%s</status>", CLIXON_LIB_NS,
|
||||||
|
clicon_int2str(proc_state_map, pe->pe_state));
|
||||||
|
if (timerisset(&pe->pe_starttime)){
|
||||||
if (time2str(pe->pe_starttime, timestr, sizeof(timestr)) < 0){
|
if (time2str(pe->pe_starttime, timestr, sizeof(timestr)) < 0){
|
||||||
clicon_err(OE_UNIX, errno, "time2str");
|
clicon_err(OE_UNIX, errno, "time2str");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
cprintf(cbret, "<starttime xmlns=\"%s\">%s</starttime>", CLIXON_LIB_NS, timestr);
|
cprintf(cbret, "<starttime xmlns=\"%s\">%s</starttime>", CLIXON_LIB_NS, timestr);
|
||||||
}
|
}
|
||||||
|
if (pe->pe_pid)
|
||||||
|
cprintf(cbret, "<pid xmlns=\"%s\">%u</pid>", CLIXON_LIB_NS, pe->pe_pid);
|
||||||
cprintf(cbret, "</rpc-reply>");
|
cprintf(cbret, "</rpc-reply>");
|
||||||
break; /* hit break here */
|
break; /* hit break here */
|
||||||
}
|
}
|
||||||
|
|
@ -694,7 +749,7 @@ clixon_process_start_all(clicon_handle h)
|
||||||
if (pe->pe_callback(h, pe, &op) < 0)
|
if (pe->pe_callback(h, pe, &op) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (op == PROC_OP_START){
|
if (op == PROC_OP_START){
|
||||||
pe->pe_op = op;
|
pe->pe_operation = op;
|
||||||
sched++;
|
sched++;
|
||||||
}
|
}
|
||||||
pe = NEXTQ(process_entry_t *, pe);
|
pe = NEXTQ(process_entry_t *, pe);
|
||||||
|
|
@ -723,73 +778,90 @@ clixon_process_sched(int fd,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
process_entry_t *pe;
|
process_entry_t *pe;
|
||||||
process_entry_t *pe1;
|
int isrunning; /* Process is actually running */
|
||||||
proc_operation op;
|
|
||||||
pid_t newpid;
|
|
||||||
int run;
|
|
||||||
|
|
||||||
clicon_debug(1, "%s",__FUNCTION__);
|
clicon_debug(1, "%s",__FUNCTION__);
|
||||||
if (_proc_entry_list == NULL)
|
if (_proc_entry_list == NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
pe = _proc_entry_list;
|
pe = _proc_entry_list;
|
||||||
do {
|
do {
|
||||||
clicon_debug(1, "%s name: %s pid:%d op: %s", __FUNCTION__,
|
clicon_debug(1, "%s name: %s pid:%d %s --op:%s-->", __FUNCTION__,
|
||||||
pe->pe_name, pe->pe_pid, clicon_int2str(proc_operation_map, pe->pe_op));
|
pe->pe_name, pe->pe_pid, clicon_int2str(proc_state_map, pe->pe_state), clicon_int2str(proc_operation_map, pe->pe_operation));
|
||||||
/* Execute pending operations and not already exiting */
|
/* Execute pending operations and not already exiting */
|
||||||
if ((op = pe->pe_op) != PROC_OP_NONE &&
|
if (pe->pe_operation != PROC_OP_NONE){
|
||||||
pe->pe_exiting == 0){
|
switch (pe->pe_state){
|
||||||
/* Check if running */
|
case PROC_STATE_EXITING:
|
||||||
run = 0;
|
break; /* only clixon_process_waitpid can change state in exiting */
|
||||||
if (proc_op_run(pe->pe_pid, &run) < 0)
|
case PROC_STATE_STOPPED:
|
||||||
goto done;
|
switch (pe->pe_operation){
|
||||||
switch (op){
|
case PROC_OP_RESTART: /* stopped -> restart can happen if its externall stopped */
|
||||||
case PROC_OP_STOP:
|
case PROC_OP_START:
|
||||||
clicon_debug(1, "%s stop pid:%d", __FUNCTION__, pe->pe_pid);
|
/* Check if actual running using kill(0) */
|
||||||
case PROC_OP_RESTART:
|
isrunning = 0;
|
||||||
if (run){
|
if (proc_op_run(pe->pe_pid, &isrunning) < 0)
|
||||||
clicon_log(LOG_NOTICE, "Killing old process %s with pid: %d", pe->pe_name, pe->pe_pid);
|
goto done;
|
||||||
kill(pe->pe_pid, SIGTERM);
|
if (!isrunning)
|
||||||
/* Cant wait here because it would block the backend and terminating may involve
|
if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &pe->pe_pid) < 0)
|
||||||
* some protocol handling, instead SIGCHLD is receoved and
|
goto done;
|
||||||
* clixon_process_waitpid is called that for waits/reaps the dead process */
|
clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__,
|
||||||
pe->pe_exiting = 1;
|
pe->pe_name, pe->pe_pid,
|
||||||
}
|
clicon_int2str(proc_state_map, pe->pe_state),
|
||||||
if (op == PROC_OP_STOP)
|
clicon_int2str(proc_operation_map, pe->pe_operation),
|
||||||
|
clicon_int2str(proc_state_map, PROC_STATE_RUNNING)
|
||||||
|
);
|
||||||
|
pe->pe_state = PROC_STATE_RUNNING;
|
||||||
|
gettimeofday(&pe->pe_starttime, NULL);
|
||||||
|
pe->pe_operation = PROC_OP_NONE;
|
||||||
break;
|
break;
|
||||||
if (!run){
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PROC_STATE_RUNNING:
|
||||||
|
/* Check if actual running using kill(0) */
|
||||||
|
isrunning = 0;
|
||||||
|
if (proc_op_run(pe->pe_pid, &isrunning) < 0)
|
||||||
|
goto done;
|
||||||
|
switch (pe->pe_operation){
|
||||||
|
case PROC_OP_STOP:
|
||||||
|
clicon_debug(1, "%s stop pid:%d", __FUNCTION__, pe->pe_pid);
|
||||||
|
case PROC_OP_RESTART:
|
||||||
|
if (isrunning){
|
||||||
|
clicon_log(LOG_NOTICE, "Killing old process %s with pid: %d", pe->pe_name, pe->pe_pid);
|
||||||
|
kill(pe->pe_pid, SIGTERM);
|
||||||
|
/* Cant wait here because it would block the backend and terminating may involve
|
||||||
|
* some protocol handling, instead SIGCHLD is receoved and
|
||||||
|
* clixon_process_waitpid is called that for waits/reaps the dead process */
|
||||||
|
}
|
||||||
|
clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__,
|
||||||
|
pe->pe_name, pe->pe_pid,
|
||||||
|
clicon_int2str(proc_state_map, pe->pe_state),
|
||||||
|
clicon_int2str(proc_operation_map, pe->pe_operation),
|
||||||
|
clicon_int2str(proc_state_map, PROC_STATE_EXITING)
|
||||||
|
);
|
||||||
|
pe->pe_state = PROC_STATE_EXITING; /* Keep operation stop/restart */
|
||||||
|
break;
|
||||||
|
case PROC_OP_START:
|
||||||
|
if (isrunning) /* Already runs */
|
||||||
|
break;
|
||||||
if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &pe->pe_pid) < 0)
|
if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &pe->pe_pid) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__,
|
||||||
|
pe->pe_name, pe->pe_pid,
|
||||||
|
clicon_int2str(proc_state_map, pe->pe_state),
|
||||||
|
clicon_int2str(proc_operation_map, pe->pe_operation),
|
||||||
|
clicon_int2str(proc_state_map, PROC_STATE_RUNNING)
|
||||||
|
);
|
||||||
gettimeofday(&pe->pe_starttime, NULL);
|
gettimeofday(&pe->pe_starttime, NULL);
|
||||||
clicon_debug(1, "%s started pid:%d", __FUNCTION__, pe->pe_pid);
|
pe->pe_operation = PROC_OP_NONE;
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* This is the case where there is an existing process running.
|
|
||||||
* it was killed above but still runs and needs to be reaped */
|
|
||||||
if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &newpid) < 0)
|
|
||||||
goto done;
|
|
||||||
gettimeofday(&pe->pe_starttime, NULL);
|
|
||||||
clicon_debug(1, "%s restart pid:%d -> %d", __FUNCTION__, pe->pe_pid, newpid);
|
|
||||||
/* Create a new pe */
|
|
||||||
if (clixon_process_register_dup(pe, &pe1) < 0)
|
|
||||||
goto done;
|
|
||||||
pe->pe_clone = 1; /* Delete when reaped */
|
|
||||||
pe1->pe_op = PROC_OP_NONE; /* Dont restart again */
|
|
||||||
pe1->pe_pid = newpid;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PROC_OP_START:
|
|
||||||
if (run) /* Already runs */
|
|
||||||
break;
|
break;
|
||||||
if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &pe->pe_pid) < 0)
|
default:
|
||||||
goto done;
|
break;
|
||||||
gettimeofday(&pe->pe_starttime, NULL);
|
}/* switch pe_state */
|
||||||
clicon_debug(1, "%s started pid:%d", __FUNCTION__, pe->pe_pid);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
} /* switch pe_state */
|
||||||
}
|
}
|
||||||
pe->pe_op = PROC_OP_NONE;
|
|
||||||
pe = NEXTQ(process_entry_t *, pe);
|
pe = NEXTQ(process_entry_t *, pe);
|
||||||
} while (pe != _proc_entry_list);
|
} while (pe != _proc_entry_list);
|
||||||
ok:
|
ok:
|
||||||
|
|
@ -841,18 +913,50 @@ clixon_process_waitpid(clicon_handle h)
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
pe = _proc_entry_list;
|
pe = _proc_entry_list;
|
||||||
do {
|
do {
|
||||||
if (pe->pe_pid != 0){
|
clicon_debug(1, "%s %s(%d) %s op:%s", __FUNCTION__,
|
||||||
clicon_debug(1, "%s waitpid(%d)", __FUNCTION__, pe->pe_pid);
|
pe->pe_name, pe->pe_pid,
|
||||||
|
clicon_int2str(proc_state_map, pe->pe_state),
|
||||||
|
clicon_int2str(proc_operation_map, pe->pe_operation));
|
||||||
|
if (pe->pe_pid != 0
|
||||||
|
&& (pe->pe_state == PROC_STATE_RUNNING || pe->pe_state == PROC_STATE_EXITING)
|
||||||
|
// && (pe->pe_operation == PROC_OP_STOP || pe->pe_operation == PROC_OP_RESTART)
|
||||||
|
){
|
||||||
|
clicon_debug(1, "%s %s waitpid(%d)", __FUNCTION__, pe->pe_name, pe->pe_pid);
|
||||||
if ((wpid = waitpid(pe->pe_pid, &status, WNOHANG)) == pe->pe_pid){
|
if ((wpid = waitpid(pe->pe_pid, &status, WNOHANG)) == pe->pe_pid){
|
||||||
clicon_debug(1, "%s waitpid(%d) waited", __FUNCTION__, pe->pe_pid);
|
clicon_debug(1, "%s waitpid(%d) waited", __FUNCTION__, pe->pe_pid);
|
||||||
pe->pe_exiting = 0;
|
pe->pe_exit_status = status;
|
||||||
pe->pe_pid = 0; /* mark as dead */
|
switch (pe->pe_operation){
|
||||||
pe->pe_status = status;
|
case PROC_OP_NONE: /* Spontaneous / External termination */
|
||||||
if (pe->pe_clone){
|
case PROC_OP_STOP:
|
||||||
/* Delete it */
|
clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__,
|
||||||
DELQ(pe, _proc_entry_list, process_entry_t *);
|
pe->pe_name, pe->pe_pid,
|
||||||
clixon_process_delete_only(pe);
|
clicon_int2str(proc_state_map, pe->pe_state),
|
||||||
|
clicon_int2str(proc_operation_map, pe->pe_operation),
|
||||||
|
clicon_int2str(proc_state_map, PROC_STATE_STOPPED)
|
||||||
|
);
|
||||||
|
pe->pe_state = PROC_STATE_STOPPED;
|
||||||
|
pe->pe_pid = 0;
|
||||||
|
timerclear(&pe->pe_starttime);
|
||||||
|
break;
|
||||||
|
case PROC_OP_RESTART:
|
||||||
|
/* This is the case where there is an existing process running.
|
||||||
|
* it was killed above but still runs and needs to be reaped */
|
||||||
|
if (clixon_proc_background(pe->pe_argv, pe->pe_netns, &pe->pe_pid) < 0)
|
||||||
|
goto done;
|
||||||
|
gettimeofday(&pe->pe_starttime, NULL);
|
||||||
|
clicon_debug(1, "%s %s(%d) %s --%s--> %s", __FUNCTION__,
|
||||||
|
pe->pe_name, pe->pe_pid,
|
||||||
|
clicon_int2str(proc_state_map, pe->pe_state),
|
||||||
|
clicon_int2str(proc_operation_map, pe->pe_operation),
|
||||||
|
clicon_int2str(proc_state_map, PROC_STATE_RUNNING)
|
||||||
|
);
|
||||||
|
pe->pe_state = PROC_STATE_RUNNING;
|
||||||
|
gettimeofday(&pe->pe_starttime, NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
pe->pe_operation = PROC_OP_NONE;
|
||||||
break; /* pid is unique */
|
break; /* pid is unique */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -861,7 +965,7 @@ clixon_process_waitpid(clicon_handle h)
|
||||||
pe = NEXTQ(process_entry_t *, pe);
|
pe = NEXTQ(process_entry_t *, pe);
|
||||||
} while (pe != _proc_entry_list);
|
} while (pe != _proc_entry_list);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
// done:
|
done:
|
||||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
23
test/lib.sh
23
test/lib.sh
|
|
@ -72,8 +72,12 @@ testname=
|
||||||
# eg logging to a file: RCLOG="-l f/www-data/restconf.log"
|
# eg logging to a file: RCLOG="-l f/www-data/restconf.log"
|
||||||
: ${RCLOG:=}
|
: ${RCLOG:=}
|
||||||
|
|
||||||
|
# Namespace: netconf base
|
||||||
BASENS='urn:ietf:params:xml:ns:netconf:base:1.0'
|
BASENS='urn:ietf:params:xml:ns:netconf:base:1.0'
|
||||||
|
|
||||||
|
# Namespace: Clixon lib
|
||||||
|
LIBNS='xmlns="http://clicon.org/lib"'
|
||||||
|
|
||||||
# Default netconf namespace statement, typically as placed on top-level <rpc xmlns=""
|
# Default netconf namespace statement, typically as placed on top-level <rpc xmlns=""
|
||||||
DEFAULTONLY="xmlns=\"$BASENS\""
|
DEFAULTONLY="xmlns=\"$BASENS\""
|
||||||
|
|
||||||
|
|
@ -230,6 +234,7 @@ fi
|
||||||
# error and exit,
|
# error and exit,
|
||||||
# arg1: expected
|
# arg1: expected
|
||||||
# arg2: errmsg[optional]
|
# arg2: errmsg[optional]
|
||||||
|
# Assumes: $dir and $expect are set
|
||||||
function err(){
|
function err(){
|
||||||
echo -e "\e[31m\nError in Test$testnr [$testname]:"
|
echo -e "\e[31m\nError in Test$testnr [$testname]:"
|
||||||
if [ $# -gt 0 ]; then
|
if [ $# -gt 0 ]; then
|
||||||
|
|
@ -248,6 +253,20 @@ function err(){
|
||||||
exit -1 #$testnr
|
exit -1 #$testnr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Dont print diffs
|
||||||
|
function err1(){
|
||||||
|
echo -e "\e[31m\nError in Test$testnr [$testname]:"
|
||||||
|
if [ $# -gt 0 ]; then
|
||||||
|
echo "Expected: $1"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
if [ $# -gt 1 ]; then
|
||||||
|
echo "Received: $2"
|
||||||
|
fi
|
||||||
|
echo -e "\e[0m"
|
||||||
|
exit -1 #$testnr
|
||||||
|
}
|
||||||
|
|
||||||
# Test is previous test had valgrind errors if so quit
|
# Test is previous test had valgrind errors if so quit
|
||||||
function checkvalgrind(){
|
function checkvalgrind(){
|
||||||
if [ -f $valgrindfile ]; then
|
if [ -f $valgrindfile ]; then
|
||||||
|
|
@ -318,7 +337,7 @@ function start_restconf(){
|
||||||
echo "sudo -u $wwwstartuser -s $clixon_restconf $RCLOG -D $DBG $*"
|
echo "sudo -u $wwwstartuser -s $clixon_restconf $RCLOG -D $DBG $*"
|
||||||
sudo -u $wwwstartuser -s $clixon_restconf $RCLOG -D $DBG $* &
|
sudo -u $wwwstartuser -s $clixon_restconf $RCLOG -D $DBG $* &
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err
|
err1 "expected 0" "$?"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -352,7 +371,7 @@ function wait_restconf(){
|
||||||
while [[ $hdr != *"200 OK"* ]]; do
|
while [[ $hdr != *"200 OK"* ]]; do
|
||||||
# echo "wait_restconf $i"
|
# echo "wait_restconf $i"
|
||||||
if [ $i -ge $DEMLOOP ]; then
|
if [ $i -ge $DEMLOOP ]; then
|
||||||
err "restconf timeout $DEMWAIT seconds"
|
err1 "restconf timeout $DEMWAIT seconds"
|
||||||
fi
|
fi
|
||||||
sleep $DEMSLEEP
|
sleep $DEMSLEEP
|
||||||
hdr=$(curl $CURLOPTS $* $RCPROTO://localhost/restconf 2> /dev/null)
|
hdr=$(curl $CURLOPTS $* $RCPROTO://localhost/restconf 2> /dev/null)
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,11 @@ if [ "${WITH_RESTCONF}" = "native" ]; then
|
||||||
# Create server certs and CA
|
# Create server certs and CA
|
||||||
cacerts $cakey $cacert
|
cacerts $cakey $cacert
|
||||||
servercerts $cakey $cacert $srvkey $srvcert
|
servercerts $cakey $cacert $srvkey $srvcert
|
||||||
|
USEBACKEND=true
|
||||||
else
|
else
|
||||||
# Define default restconfig config: RESTCONFIG
|
# Define default restconfig config: RESTCONFIG
|
||||||
RESTCONFIG=$(restconf_config none false)
|
RESTCONFIG=$(restconf_config none false)
|
||||||
|
USEBACKEND=false
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# This is a fixed 'state' implemented in routing_backend. It is assumed to be always there
|
# This is a fixed 'state' implemented in routing_backend. It is assumed to be always there
|
||||||
|
|
@ -111,6 +113,7 @@ cat <<EOF > $cfg
|
||||||
<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>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||||
<CLICON_MODULE_LIBRARY_RFC7895>true</CLICON_MODULE_LIBRARY_RFC7895>
|
<CLICON_MODULE_LIBRARY_RFC7895>true</CLICON_MODULE_LIBRARY_RFC7895>
|
||||||
|
<CLICON_BACKEND_RESTCONF_PROCESS>$USEBACKEND</CLICON_BACKEND_RESTCONF_PROCESS>
|
||||||
$RESTCONFIG <!-- only fcgi -->
|
$RESTCONFIG <!-- only fcgi -->
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,8 @@
|
||||||
# - on enable change, make the state as configured
|
# - on enable change, make the state as configured
|
||||||
# - No restconf config means enable: false (extra rule)
|
# - No restconf config means enable: false (extra rule)
|
||||||
# See test_restconf_netns for network namespaces
|
# See test_restconf_netns for network namespaces
|
||||||
|
# See test_restconf_internal_cases for some special use-cases
|
||||||
# XXX Lots of sleeps to remove race conditions. I am sure there are others way to fix this
|
# XXX Lots of sleeps to remove race conditions. I am sure there are others way to fix this
|
||||||
# XXX It is wrong to use $RESTCONF in clixon-config when using CLICON_BACKEND_RESTCONF_PROCESS
|
|
||||||
# XXX the tests should be rewritten to use running datastore
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|
@ -19,14 +18,21 @@ APPNAME=example
|
||||||
cfg=$dir/conf.xml
|
cfg=$dir/conf.xml
|
||||||
startupdb=$dir/startup_db
|
startupdb=$dir/startup_db
|
||||||
|
|
||||||
# Define default restconfig config: RESTCONFIG
|
# Restconf debug
|
||||||
RESTCONFIG=$(restconf_config none false)
|
RESTCONFDBG=$DBG
|
||||||
|
RCPROTO=http # no ssl here
|
||||||
|
|
||||||
|
if [ "${WITH_RESTCONF}" = "fcgi" ]; then
|
||||||
|
EXTRACONF="<CLICON_FEATURE>clixon-restconf:fcgi</CLICON_FEATURE>"
|
||||||
|
else
|
||||||
|
EXTRACONF=""
|
||||||
|
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_FEATURE>ietf-netconf:startup</CLICON_FEATURE>
|
||||||
<CLICON_FEATURE>clixon-restconf:allow-auth-none</CLICON_FEATURE> <!-- Use auth-type=none -->
|
<CLICON_FEATURE>clixon-restconf:allow-auth-none</CLICON_FEATURE> <!-- Use auth-type=none -->
|
||||||
|
$EXTRACONF
|
||||||
<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>
|
||||||
|
|
@ -42,7 +48,6 @@ cat <<EOF > $cfg
|
||||||
<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>
|
||||||
$RESTCONFIG
|
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
@ -58,65 +63,89 @@ module example {
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Subroutine send a process control RPC and tricks to echo process-id returned
|
# Subroutine send a process control RPC and tricks to echo process-id returned
|
||||||
# Args:
|
# Args, expected values of:
|
||||||
# 1: operation
|
# 0: ACTIVE: true or false
|
||||||
# 2: expectret 0: means expect pi 0 as return, else something else
|
# 1: STATUS: stopped/running/exiting
|
||||||
function testrpc()
|
# retvalue:
|
||||||
|
# $pid
|
||||||
|
function rpcstatus()
|
||||||
{
|
{
|
||||||
operation=$1
|
if [ $# -ne 2 ]; then
|
||||||
expectret=$2
|
err1 "rpcstatus: # arguments: 2" "$#"
|
||||||
|
fi
|
||||||
|
active=$1
|
||||||
|
status=$2
|
||||||
|
|
||||||
sleep $DEMSLEEP
|
sleep $DEMSLEEP
|
||||||
new "send rpc $operation"
|
new "send rpc status"
|
||||||
ret=$($clixon_netconf -qf $cfg<<EOF
|
ret=$($clixon_netconf -qf $cfg<<EOF
|
||||||
$DEFAULTHELLO
|
$DEFAULTHELLO
|
||||||
<rpc $DEFAULTNS>
|
<rpc $DEFAULTNS>
|
||||||
<process-control xmlns="http://clicon.org/lib">
|
<process-control xmlns="http://clicon.org/lib">
|
||||||
<name>restconf</name>
|
<name>restconf</name>
|
||||||
<operation>$operation</operation>
|
<operation>status</operation>
|
||||||
</process-control>
|
</process-control>
|
||||||
</rpc>]]>]]>
|
</rpc>]]>]]>
|
||||||
EOF
|
EOF
|
||||||
)
|
)
|
||||||
|
# Check pid
|
||||||
# >&2 echo "ret:$ret" # debug
|
expect="<pid xmlns=\"http://clicon.org/lib\">[0-9]*</pid>"
|
||||||
|
match=$(echo "$ret" | grep --null -Go "$expect")
|
||||||
expect1="<pid xmlns=\"http://clicon.org/lib\">[0-9]*</pid>"
|
|
||||||
match=$(echo "$ret" | grep --null -Go "$expect1")
|
|
||||||
# >&2 echo "match:$match" # debug
|
|
||||||
if [ -z "$match" ]; then
|
if [ -z "$match" ]; then
|
||||||
pid=0
|
pid=0
|
||||||
else
|
else
|
||||||
pid=$(echo "$match" | awk -F'[<>]' '{print $3}')
|
pid=$(echo "$match" | awk -F'[<>]' '{print $3}')
|
||||||
fi
|
fi
|
||||||
>&2 echo "pid:$pid" # debug
|
|
||||||
|
|
||||||
if [ -z "$pid" ]; then
|
if [ -z "$pid" ]; then
|
||||||
err "Running process" "$ret"
|
err "No pid return value" "$ret"
|
||||||
fi
|
fi
|
||||||
|
if $active; then
|
||||||
|
expect="^<rpc-reply $DEFAULTNS><active $LIBNS>$active</active><description $LIBNS>Clixon RESTCONF process</description><command $LIBNS>/www-data/clixon_restconf -f $cfg -D [0-9]</command><status $LIBNS>$status</status><starttime $LIBNS>20[0-9][0-9]\-[0-9][0-9]\-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\.[0-9]*Z</starttime><pid $LIBNS>$pid</pid></rpc-reply>]]>]]>$"
|
||||||
|
else
|
||||||
|
# inactive, no startime or pid
|
||||||
|
expect="^<rpc-reply $DEFAULTNS><active $LIBNS>$active</active><description $LIBNS>Clixon RESTCONF process</description><command $LIBNS>/www-data/clixon_restconf -f $cfg -D [0-9]</command><status $LIBNS>$status</status></rpc-reply>]]>]]>$"
|
||||||
|
fi
|
||||||
|
match=$(echo "$ret" | grep --null -Go "$expect")
|
||||||
|
if [ -z "$match" ]; then
|
||||||
|
err "$expect" "$ret"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Subroutine send a process control RPC and tricks to echo process-id returned
|
||||||
|
# Args:
|
||||||
|
# 1: operation One of stop/start/restart
|
||||||
|
function rpcoperation()
|
||||||
|
{
|
||||||
|
operation=$1
|
||||||
|
|
||||||
|
sleep $DEMSLEEP
|
||||||
|
new "send rpc $operation"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><process-control xmlns=\"http://clicon.org/lib\"><name>restconf</name><operation>$operation</operation></process-control></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok xmlns=\"http://clicon.org/lib\"/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "check restconf retvalue"
|
|
||||||
if [ $operation = "status" ]; then
|
|
||||||
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
|
|
||||||
echo "$pid" # cant use return that only uses 0-255
|
|
||||||
fi
|
|
||||||
sleep $DEMSLEEP
|
sleep $DEMSLEEP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This test is confusing:
|
||||||
|
# The whole restconf config is in clixon-config wich binds 0.0.0.0:80 which will be the only
|
||||||
|
# config the restconf daemon ever reads.
|
||||||
|
# However, enable (and debug) flag is stored in running db but only backend will ever read that.
|
||||||
|
# It just controls how restconf is started, but thereafter the restconf daemon reads the static db in clixon-config file
|
||||||
|
|
||||||
new "ENABLE true"
|
new "ENABLE true"
|
||||||
# First basic operation with restconf enable is true
|
# First basic operation with restconf enable is true
|
||||||
cat<<EOF > $startupdb
|
cat<<EOF > $startupdb
|
||||||
<${DATASTORE_TOP}>
|
<${DATASTORE_TOP}>
|
||||||
<restconf xmlns="http://clicon.org/restconf">
|
<restconf xmlns="http://clicon.org/restconf">
|
||||||
<enable>true</enable>
|
<enable>true</enable>
|
||||||
|
<auth-type>none</auth-type>
|
||||||
|
<pretty>false</pretty>
|
||||||
|
<debug>$RESTCONFDBG</debug>
|
||||||
|
<socket>
|
||||||
|
<namespace>default</namespace>
|
||||||
|
<address>0.0.0.0</address>
|
||||||
|
<port>80</port>
|
||||||
|
<ssl>false</ssl>
|
||||||
|
</socket>
|
||||||
</restconf>
|
</restconf>
|
||||||
</${DATASTORE_TOP}>
|
</${DATASTORE_TOP}>
|
||||||
EOF
|
EOF
|
||||||
|
|
@ -134,18 +163,19 @@ if [ $BE -ne 0 ]; then
|
||||||
|
|
||||||
new "start backend -s startup -f $cfg"
|
new "start backend -s startup -f $cfg"
|
||||||
start_backend -s startup -f $cfg
|
start_backend -s startup -f $cfg
|
||||||
|
|
||||||
new "wait backend"
|
|
||||||
wait_backend
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
new "wait backend"
|
||||||
|
wait_backend
|
||||||
|
|
||||||
# For debug
|
# For debug
|
||||||
#>&2 echo "curl $CURLOPTS -X POST -H \"Content-Type: application/yang-data+json\" $RCPROTO://localhost/restconf/operations/clixon-lib:process-control -d '{\"clixon-lib:input\":{\"name\":\"restconf\",\"operation\":\"status\"}}'"
|
#>&2 echo "curl $CURLOPTS -X POST -H \"Content-Type: application/yang-data+json\" $RCPROTO://localhost/restconf/operations/clixon-lib:process-control -d '{\"clixon-lib:input\":{\"name\":\"restconf\",\"operation\":\"status\"}}'"
|
||||||
|
|
||||||
# Get pid of running process and check return xml
|
# Get pid of running process and check return xml
|
||||||
new "1. Get rpc status"
|
new "1. Get rpc status"
|
||||||
pid0=$(testrpc status 1) # Save pid0
|
rpcstatus true running
|
||||||
if [ $? -ne 0 ]; then echo "$pid0";exit -1; fi
|
pid0=$pid # Save pid0
|
||||||
|
if [ $pid0 -eq 0 ]; then err "Pid" 0; fi
|
||||||
|
|
||||||
new "check restconf process runnng using ps pid:$pid0"
|
new "check restconf process runnng using ps pid:$pid0"
|
||||||
ps=$(ps -hp $pid0)
|
ps=$(ps -hp $pid0)
|
||||||
|
|
@ -167,8 +197,9 @@ new "try restconf rpc status"
|
||||||
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/operations/clixon-lib:process-control -d '{"clixon-lib:input":{"name":"restconf","operation":"status"}}')" 0 "HTTP/1.1 200 OK" '{"clixon-lib:output":' '"active":' '"pid":'
|
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/operations/clixon-lib:process-control -d '{"clixon-lib:input":{"name":"restconf","operation":"status"}}')" 0 "HTTP/1.1 200 OK" '{"clixon-lib:output":' '"active":' '"pid":'
|
||||||
|
|
||||||
new "2. Get status"
|
new "2. Get status"
|
||||||
pid1=$(testrpc status 1)
|
rpcstatus true running
|
||||||
if [ $? -ne 0 ]; then echo "$pid1";exit -1; fi
|
pid1=$pid
|
||||||
|
if [ $pid1 -eq 0 ]; then err "pid" 0; fi
|
||||||
|
|
||||||
new "Check same pid"
|
new "Check same pid"
|
||||||
if [ "$pid0" -ne "$pid1" ]; then
|
if [ "$pid0" -ne "$pid1" ]; then
|
||||||
|
|
@ -179,29 +210,31 @@ new "try restconf rpc restart"
|
||||||
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/operations/clixon-lib:process-control -d '{"clixon-lib:input":{"name":"restconf","operation":"restart"}}')" 0 "HTTP/1.1 204 No Content"
|
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/operations/clixon-lib:process-control -d '{"clixon-lib:input":{"name":"restconf","operation":"restart"}}')" 0 "HTTP/1.1 204 No Content"
|
||||||
|
|
||||||
new "3. Get status"
|
new "3. Get status"
|
||||||
pid1=$(testrpc status 1)
|
rpcstatus true running
|
||||||
if [ $? -ne 0 ]; then echo "$pid1";exit -1; fi
|
pid1=$pid
|
||||||
|
if [ $pid1 -eq 0 ]; then err "Pid" 0; fi
|
||||||
|
|
||||||
new "check different pids"
|
new "check different pids"
|
||||||
if [ "$pid0" -eq "$pid1" ]; then
|
if [ "$pid0" -eq "$pid1" ]; then
|
||||||
err "not $pid0"
|
err1 "not $pid0" "$pid1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "4. stop restconf RPC"
|
new "4. stop restconf RPC"
|
||||||
testrpc stop 0
|
rpcoperation stop
|
||||||
if [ $? -ne 0 ]; then exit -1; fi
|
if [ $? -ne 0 ]; then exit -1; fi
|
||||||
|
|
||||||
new "5. Get rpc status stopped"
|
new "5. Get rpc status stopped"
|
||||||
pid=$(testrpc status 0)
|
rpcstatus false stopped
|
||||||
if [ $? -ne 0 ]; then echo "$pid";exit -1; fi
|
if [ $pid -ne 0 ]; then err "Pid" "$pid"; fi
|
||||||
|
|
||||||
new "6. Start rpc again"
|
new "6. Start rpc again"
|
||||||
testrpc start 0
|
rpcoperation start
|
||||||
if [ $? -ne 0 ]; then exit -1; fi
|
if [ $? -ne 0 ]; then exit -1; fi
|
||||||
|
|
||||||
new "7. Get rpc status"
|
new "7. Get rpc status"
|
||||||
pid3=$(testrpc status 1)
|
rpcstatus true running
|
||||||
if [ $? -ne 0 ]; then echo "$pid3";exit -1; fi
|
pid3=$pid
|
||||||
|
if [ $pid3 -eq 0 ]; then err "Pid" 0; fi
|
||||||
|
|
||||||
new "check restconf process running using ps"
|
new "check restconf process running using ps"
|
||||||
ps=$(ps -hp $pid3)
|
ps=$(ps -hp $pid3)
|
||||||
|
|
@ -210,30 +243,32 @@ if [ -z "$ps" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $pid0 -eq $pid3 ]; then
|
if [ $pid0 -eq $pid3 ]; then
|
||||||
err "A different pid" "same pid: $pid3"
|
err1 "A different pid" "same pid: $pid3"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "kill restconf"
|
new "kill restconf"
|
||||||
stop_restconf_pre
|
stop_restconf_pre
|
||||||
|
|
||||||
new "8. start restconf RPC"
|
new "8. start restconf RPC"
|
||||||
testrpc start 0
|
rpcoperation start
|
||||||
if [ $? -ne 0 ]; then exit -1; fi
|
if [ $? -ne 0 ]; then exit -1; fi
|
||||||
|
|
||||||
new "9. check status RPC on"
|
new "9. check status RPC on"
|
||||||
pid5=$(testrpc status 1) # Save pid5
|
rpcstatus true running
|
||||||
if [ $? -ne 0 ]; then echo "$pid5";exit -1; fi
|
pid5=$pid
|
||||||
|
if [ $pid5 -eq 0 ]; then err "Pid" 0; fi
|
||||||
|
|
||||||
new "10. restart restconf RPC"
|
new "10. restart restconf RPC"
|
||||||
testrpc restart 0
|
rpcoperation restart
|
||||||
if [ $? -ne 0 ]; then exit -1; fi
|
if [ $? -ne 0 ]; then exit -1; fi
|
||||||
|
|
||||||
new "11. Get restconf status rpc"
|
new "11. Get restconf status rpc"
|
||||||
pid7=$(testrpc status 1) # Save pid7
|
rpcstatus true running
|
||||||
if [ $? -ne 0 ]; then echo "$pid7";exit -1; fi
|
pid7=$pid
|
||||||
|
if [ $pid7 -eq 0 ]; then err "Pid" 0; fi
|
||||||
|
|
||||||
if [ $pid5 -eq $pid7 ]; then
|
if [ $pid5 -eq $pid7 ]; then
|
||||||
err "A different pid" "samepid: $pid7"
|
err1 "A different pid" "samepid: $pid7"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
|
|
@ -261,14 +296,17 @@ if [ $BE -ne 0 ]; then
|
||||||
new "start backend -s none -f $cfg"
|
new "start backend -s none -f $cfg"
|
||||||
start_backend -s none -f $cfg
|
start_backend -s none -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
new "wait backend"
|
||||||
wait_backend
|
wait_backend
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "12. Get restconf (running) after restart"
|
new "wait restconf"
|
||||||
pid=$(testrpc status 1)
|
wait_restconf
|
||||||
if [ valgrindtest -ne 2 ]; then # XXX does not work w backend valgrind test
|
|
||||||
if [ $? -ne 0 ]; then echo "$pid"; exit -1; fi
|
if [ $valgrindtest -ne 2 ]; then # Restart with same restconf pid does not work w backend valgrind test
|
||||||
|
new "12. Get restconf (running) after restart"
|
||||||
|
rpcstatus true running
|
||||||
|
if [ $pid -eq 0 ]; then err "Pid" 0; fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
|
|
@ -283,14 +321,23 @@ if [ $BE -ne 0 ]; then
|
||||||
fi
|
fi
|
||||||
#--------------------------
|
#--------------------------
|
||||||
|
|
||||||
# So far, restconf config enable flag has been true. Now change enable flag.
|
# Now start with enable=false
|
||||||
|
|
||||||
new "ENABLE false"
|
new "enable false"
|
||||||
# Second basic operation with restconf enable is false
|
# Second basic operation with restconf enable is false
|
||||||
cat<<EOF > $startupdb
|
cat<<EOF > $startupdb
|
||||||
<${DATASTORE_TOP}>
|
<${DATASTORE_TOP}>
|
||||||
<restconf xmlns="http://clicon.org/restconf">
|
<restconf xmlns="http://clicon.org/restconf">
|
||||||
<enable>false</enable>
|
<enable>false</enable>
|
||||||
|
<auth-type>none</auth-type>
|
||||||
|
<pretty>false</pretty>
|
||||||
|
<debug>$RESTCONFDBG</debug>
|
||||||
|
<socket>
|
||||||
|
<namespace>default</namespace>
|
||||||
|
<address>0.0.0.0</address>
|
||||||
|
<port>80</port>
|
||||||
|
<ssl>false</ssl>
|
||||||
|
</socket>
|
||||||
</restconf>
|
</restconf>
|
||||||
</${DATASTORE_TOP}>
|
</${DATASTORE_TOP}>
|
||||||
EOF
|
EOF
|
||||||
|
|
@ -307,68 +354,74 @@ if [ $BE -ne 0 ]; then
|
||||||
fi
|
fi
|
||||||
new "start backend -s startup -f $cfg"
|
new "start backend -s startup -f $cfg"
|
||||||
start_backend -s startup -f $cfg
|
start_backend -s startup -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
|
||||||
wait_backend
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
new "wait backend"
|
||||||
|
wait_backend
|
||||||
|
|
||||||
new "13. check status RPC off"
|
new "13. check status RPC off"
|
||||||
pid=$(testrpc status 0)
|
rpcstatus false stopped
|
||||||
if [ $? -ne 0 ]; then echo "$pid";exit -1; fi
|
if [ $pid -ne 0 ]; then err "Pid" "$pid"; fi
|
||||||
|
|
||||||
new "14. start restconf RPC"
|
new "14. start restconf RPC (but disabled)"
|
||||||
testrpc start 0
|
rpcoperation start
|
||||||
if [ $? -ne 0 ]; then exit -1; fi
|
if [ $? -ne 0 ]; then exit -1; fi
|
||||||
|
|
||||||
new "15. check status RPC off"
|
new "15. check status RPC still off"
|
||||||
pid=$(testrpc status 0)
|
rpcstatus false stopped
|
||||||
if [ $? -ne 0 ]; then echo "$pid";exit -1; fi
|
if [ $pid -ne 0 ]; then err "Pid" "$pid"; fi
|
||||||
|
|
||||||
new "Enable restconf"
|
new "Enable restconf"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<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>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><default-operation>merge</default-operation><target><candidate/></target><config><restconf xmlns=\"http://clicon.org/restconf\"><enable>true</enable><debug>$RESTCONFDBG</debug></restconf></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf commit"
|
new "commit enable"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
sleep $DEMSLEEP
|
|
||||||
|
|
||||||
new "16. check status RPC on"
|
new "16. check status RPC on"
|
||||||
pid=$(testrpc status 1)
|
rpcstatus true running
|
||||||
if [ $? -ne 0 ]; then echo "$pid";exit -1; fi
|
pid1=$pid
|
||||||
|
if [ $pid1 -eq 0 ]; then err "Pid" 0; fi
|
||||||
|
|
||||||
# Edit a field, eg debug
|
new "wait restconf"
|
||||||
new "Edit a restconf field via restconf"
|
wait_restconf
|
||||||
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/clixon-restconf:restconf/debug -d '{"clixon-restconf:debug":1}' )" 0 "HTTP/1.1 201 Created"
|
|
||||||
|
# Edit a field, eg pretty to trigger a restart
|
||||||
|
new "Edit a restconf field via restconf" # XXX fcgi fails here
|
||||||
|
expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/clixon-restconf:restconf/pretty -d '{"clixon-restconf:pretty":true}' )" 0 "HTTP/1.1 204 No Content"
|
||||||
|
|
||||||
new "check status RPC new pid"
|
new "check status RPC new pid"
|
||||||
pid1=$(testrpc status 1)
|
rpcstatus true running
|
||||||
|
pid2=$pid
|
||||||
|
if [ $pid2 -eq 0 ]; then err "Pid" 0; fi
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then echo "$pid1";exit -1; fi
|
if [ $pid1 -eq $pid2 ]; then
|
||||||
if [ $pid -eq $pid1 ]; then
|
err1 "A different pid" "$pid1"
|
||||||
err "A different pid" "Same pid: $pid"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sleep $DEMSLEEP
|
new "wait restconf"
|
||||||
|
wait_restconf
|
||||||
|
|
||||||
new "Edit a non-restconf field via restconf"
|
new "Edit a non-restconf field via restconf"
|
||||||
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data -d '{"example:val":"xyz"}' )" 0 "HTTP/1.1 201 Created"
|
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data -d '{"example:val":"xyz"}' )" 0 "HTTP/1.1 201 Created"
|
||||||
|
|
||||||
new "check status RPC same pid"
|
new "17. check status RPC same pid"
|
||||||
pid2=$(testrpc status 1)
|
rpcstatus true running
|
||||||
if [ $? -ne 0 ]; then echo "$pid2";exit -1; fi
|
pid3=$pid
|
||||||
if [ $pid1 -ne $pid2 ]; then
|
if [ $pid3 -eq 0 ]; then err "Pid" 0; fi
|
||||||
err "Same pid $pid1" "$pid2"
|
|
||||||
|
if [ $pid2 -ne $pid3 ]; then
|
||||||
|
err1 "Same pid $pid2" "$pid3"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "Disable restconf"
|
new "Disable restconf"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<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>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<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"
|
new "commit disable"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "17. check status RPC off"
|
new "17. check status RPC off"
|
||||||
pid=$(testrpc status 0)
|
rpcstatus false stopped
|
||||||
if [ $? -ne 0 ]; then echo "$pid";exit -1; fi
|
if [ $pid -ne 0 ]; then err "Pid" "$pid"; fi
|
||||||
|
|
||||||
# Negative validation checks of clixon-restconf / socket
|
# Negative validation checks of clixon-restconf / socket
|
||||||
|
|
||||||
|
|
@ -400,6 +453,8 @@ endtest
|
||||||
|
|
||||||
# Set by restconf_config
|
# Set by restconf_config
|
||||||
unset RESTCONFIG
|
unset RESTCONFIG
|
||||||
|
unset RESTCONFDBG
|
||||||
|
unset RCPROTO
|
||||||
|
|
||||||
rm -rf $dir
|
rm -rf $dir
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Send restconf rpc:s when starting from backend
|
# Send restconf rpc:s when starting from backend
|
||||||
# Two specific usecases that have been problematic are tested here
|
# Two specific usecases that have been problematic are tested here
|
||||||
# In comparison test_restconf_rpc.sh:
|
# In comparison test_restconf_internal.sh:
|
||||||
# - uses externally started restconf, here started by backend
|
# - uses externally started restconf, here started by backend
|
||||||
# - generic tests, here specific
|
# - generic tests, here specific
|
||||||
# The first usecases is: empty status message
|
# The first usecases is: empty status message
|
||||||
|
|
@ -26,14 +26,21 @@ cfg=$dir/conf.xml
|
||||||
startupdb=$dir/startup_db
|
startupdb=$dir/startup_db
|
||||||
|
|
||||||
# Restconf debug
|
# Restconf debug
|
||||||
RESTCONFDBG=0
|
RESTCONFDBG=$DBG
|
||||||
RCPROTO=http # no ssl here
|
RCPROTO=http # no ssl here
|
||||||
|
|
||||||
|
if [ "${WITH_RESTCONF}" = "fcgi" ]; then
|
||||||
|
EXTRACONF="<CLICON_FEATURE>clixon-restconf:fcgi</CLICON_FEATURE>"
|
||||||
|
else
|
||||||
|
EXTRACONF=""
|
||||||
|
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_FEATURE>ietf-netconf:startup</CLICON_FEATURE>
|
||||||
<CLICON_FEATURE>clixon-restconf:allow-auth-none</CLICON_FEATURE> <!-- Use auth-type=none -->
|
<CLICON_FEATURE>clixon-restconf:allow-auth-none</CLICON_FEATURE> <!-- Use auth-type=none -->
|
||||||
|
$EXTRACONF
|
||||||
<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>
|
||||||
|
|
@ -63,54 +70,54 @@ module example {
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
function testrpc()
|
# Subroutine send a process control RPC and tricks to echo process-id returned
|
||||||
|
# Args, expected values of:
|
||||||
|
# 0: ACTIVE: true or false
|
||||||
|
# 1: STATUS: stopped/running/exiting
|
||||||
|
# retvalue:
|
||||||
|
# $pid
|
||||||
|
# See also in test_restconf_internal.sh
|
||||||
|
function rpcstatus()
|
||||||
{
|
{
|
||||||
operation=$1
|
if [ $# -ne 2 ]; then
|
||||||
expectret=$2
|
err1 "rpcstatus: # arguments: 2" "$#"
|
||||||
|
fi
|
||||||
|
active=$1
|
||||||
|
status=$2
|
||||||
|
|
||||||
sleep $DEMSLEEP
|
sleep $DEMSLEEP
|
||||||
new "send rpc $operation"
|
new "send rpc status"
|
||||||
ret=$($clixon_netconf -qf $cfg<<EOF
|
ret=$($clixon_netconf -qf $cfg<<EOF
|
||||||
$DEFAULTHELLO
|
$DEFAULTHELLO
|
||||||
<rpc $DEFAULTNS>
|
<rpc $DEFAULTNS>
|
||||||
<process-control xmlns="http://clicon.org/lib">
|
<process-control xmlns="http://clicon.org/lib">
|
||||||
<name>restconf</name>
|
<name>restconf</name>
|
||||||
<operation>$operation</operation>
|
<operation>status</operation>
|
||||||
</process-control>
|
</process-control>
|
||||||
</rpc>]]>]]>
|
</rpc>]]>]]>
|
||||||
EOF
|
EOF
|
||||||
)
|
)
|
||||||
|
# Check pid
|
||||||
# >&2 echo "ret:$ret" # debug
|
expect="<pid xmlns=\"http://clicon.org/lib\">[0-9]*</pid>"
|
||||||
|
match=$(echo "$ret" | grep --null -Go "$expect")
|
||||||
expect1="<pid xmlns=\"http://clicon.org/lib\">[0-9]*</pid>"
|
|
||||||
match=$(echo "$ret" | grep --null -Go "$expect1")
|
|
||||||
# >&2 echo "match:$match" # debug
|
|
||||||
if [ -z "$match" ]; then
|
if [ -z "$match" ]; then
|
||||||
pid=0
|
pid=0
|
||||||
else
|
else
|
||||||
pid=$(echo "$match" | awk -F'[<>]' '{print $3}')
|
pid=$(echo "$match" | awk -F'[<>]' '{print $3}')
|
||||||
fi
|
fi
|
||||||
# >&2 echo "pid:$pid" # debug
|
|
||||||
|
|
||||||
if [ -z "$pid" ]; then
|
if [ -z "$pid" ]; then
|
||||||
err "Running process" "$ret"
|
err "No pid return value" "$ret"
|
||||||
fi
|
fi
|
||||||
|
if $active; then
|
||||||
new "check restconf retvalue"
|
expect="^<rpc-reply $DEFAULTNS><active $LIBNS>$active</active><description $LIBNS>Clixon RESTCONF process</description><command $LIBNS>/www-data/clixon_restconf -f $cfg -D [0-9]</command><status $LIBNS>$status</status><starttime $LIBNS>20[0-9][0-9]\-[0-9][0-9]\-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\.[0-9]*Z</starttime><pid $LIBNS>$pid</pid></rpc-reply>]]>]]>$"
|
||||||
if [ $operation = "status" ]; then
|
else
|
||||||
if [ $expectret -eq 0 ]; then
|
# inactive, no startime or pid
|
||||||
if [ $pid -ne 0 ]; then
|
expect="^<rpc-reply $DEFAULTNS><active $LIBNS>$active</active><description $LIBNS>Clixon RESTCONF process</description><command $LIBNS>/www-data/clixon_restconf -f $cfg -D [0-9]</command><status $LIBNS>$status</status></rpc-reply>]]>]]>$"
|
||||||
err "No process" "$pid"
|
fi
|
||||||
fi
|
match=$(echo "$ret" | grep --null -Go "$expect")
|
||||||
else
|
if [ -z "$match" ]; then
|
||||||
if [ $pid -eq 0 ]; then
|
err "$expect" "$ret"
|
||||||
err "Running process"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
echo "$pid" # cant use return that only uses 0-255
|
|
||||||
fi
|
fi
|
||||||
sleep $DEMSLEEP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# FIRST usecase
|
# FIRST usecase
|
||||||
|
|
@ -127,7 +134,6 @@ if [ $BE -ne 0 ]; then
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg"
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg
|
||||||
fi
|
fi
|
||||||
|
|
@ -142,53 +148,33 @@ RESTCONFIG1=$(cat <<EOF
|
||||||
EOF
|
EOF
|
||||||
)
|
)
|
||||||
|
|
||||||
LIBNS='xmlns="http://clicon.org/lib"'
|
new "1. get status"
|
||||||
|
rpcstatus false stopped
|
||||||
new "get status 1"
|
if [ $pid -ne 0 ]; then err "Pid" "$pid"; fi
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><process-control xmlns=\"http://clicon.org/lib\"><name>restconf</name><operation>status</operation></process-control></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><active $LIBNS>false</active><description $LIBNS>Clixon RESTCONF process</description><command $LIBNS>/www-data/clixon_restconf -f $cfg -D $RESTCONFDBG</command></rpc-reply>]]>]]>$"
|
|
||||||
|
|
||||||
new "enable minimal restconf, no server"
|
new "enable minimal restconf, no server"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config>$RESTCONFIG1</config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config>$RESTCONFIG1</config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf commit"
|
new "commit minimal server"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
# Get pid2
|
new "2. get status, get pid1"
|
||||||
new "get pid"
|
rpcstatus true running
|
||||||
pid2=$(testrpc status 1)
|
pid1=$pid
|
||||||
echo "pid2:$pid2"
|
if [ $pid1 -eq 0 ]; then err "Pid" 0; fi
|
||||||
|
|
||||||
new "get status 2"
|
new "kill $pid1 externally"
|
||||||
ret=$($clixon_netconf -qf $cfg<<EOF
|
sudo kill $pid1
|
||||||
$DEFAULTHELLO
|
|
||||||
<rpc $DEFAULTNS>
|
|
||||||
<process-control xmlns="http://clicon.org/lib">
|
|
||||||
<name>restconf</name>
|
|
||||||
<operation>status</operation>
|
|
||||||
</process-control>
|
|
||||||
</rpc>]]>]]>
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
expect="^<rpc-reply $DEFAULTNS><active $LIBNS>true</active><description $LIBNS>Clixon RESTCONF process</description><pid $LIBNS>$pid2</pid><command $LIBNS>/www-data/clixon_restconf -f $cfg -D $RESTCONFDBG</command><starttime $LIBNS>20[0-9][0-9]\-[0-9][0-9]\-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\.[0-9]*Z</starttime>"
|
|
||||||
match=$(echo "$ret" | grep --null -Go "$expect")
|
|
||||||
if [ -z "$match" ]; then
|
|
||||||
err "$expect" "$ret"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Kill it
|
|
||||||
new "kill $pid2"
|
|
||||||
sudo kill $pid2
|
|
||||||
sleep $DEMSLEEP
|
sleep $DEMSLEEP
|
||||||
|
|
||||||
# Why kill it twice?
|
# Why kill it twice? it happens in docker somethimes but is not the aim of the test
|
||||||
# I should really debug this,... it happens in docker somethimes but its not the aim of the test
|
new "kill $pid1 again"
|
||||||
new "kill $pid2 again"
|
sudo kill $pid1 2> /dev/null
|
||||||
sudo kill $pid2
|
|
||||||
sleep $DEMSLEEP
|
sleep $DEMSLEEP
|
||||||
|
|
||||||
new "Check killed"
|
new "3. get status: Check killed"
|
||||||
# Ensure no pid
|
rpcstatus false stopped
|
||||||
testrpc status 0 > /dev/null
|
if [ $pid -ne 0 ]; then err "Pid" "$pid"; fi
|
||||||
|
|
||||||
RESTCONFIG2=$(cat <<EOF
|
RESTCONFIG2=$(cat <<EOF
|
||||||
<restconf xmlns="http://clicon.org/restconf">
|
<restconf xmlns="http://clicon.org/restconf">
|
||||||
|
|
@ -196,16 +182,15 @@ RESTCONFIG2=$(cat <<EOF
|
||||||
</restconf>
|
</restconf>
|
||||||
EOF
|
EOF
|
||||||
)
|
)
|
||||||
new "create a server"
|
new "create server"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config>$RESTCONFIG2</config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config>$RESTCONFIG2</config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf commit"
|
new "commit create server"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
# 3. get status
|
new "4. get status"
|
||||||
|
rpcstatus true running
|
||||||
new "get status 3"
|
if [ $pid -eq 0 ]; then err "Pid" 0; fi
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><process-control xmlns=\"http://clicon.org/lib\"><name>restconf</name><operation>status</operation></process-control></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><active $LIBNS>true</active><description $LIBNS>Clixon RESTCONF process</description><pid $LIBNS>"
|
|
||||||
|
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
|
|
@ -238,8 +223,9 @@ fi
|
||||||
new "wait backend"
|
new "wait backend"
|
||||||
wait_backend
|
wait_backend
|
||||||
|
|
||||||
new "get status 1"
|
new "5. get status not started"
|
||||||
testrpc status 0 > /dev/null
|
rpcstatus false stopped
|
||||||
|
if [ $pid -ne 0 ]; then err "Pid" "$pid"; fi
|
||||||
|
|
||||||
RESTCONFIG1=$(cat <<EOF
|
RESTCONFIG1=$(cat <<EOF
|
||||||
<restconf xmlns="http://clicon.org/restconf">
|
<restconf xmlns="http://clicon.org/restconf">
|
||||||
|
|
@ -255,7 +241,7 @@ EOF
|
||||||
new "Create server with invalid address"
|
new "Create server with invalid address"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config>$RESTCONFIG1</config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config>$RESTCONFIG1</config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf commit"
|
new "commit invalid server"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
sleep $DEMSLEEP
|
sleep $DEMSLEEP
|
||||||
|
|
@ -285,6 +271,9 @@ if [ -n "$ret" ]; then
|
||||||
err "No zombie process" "$ret"
|
err "No zombie process" "$ret"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# THIRD usecase
|
||||||
|
# NOTE this does not apply for fcgi where servers cant be "removed"
|
||||||
|
if [ "${WITH_RESTCONF}" != "fcgi" ]; then
|
||||||
new "3. restconf not removed"
|
new "3. restconf not removed"
|
||||||
|
|
||||||
new "kill old restconf"
|
new "kill old restconf"
|
||||||
|
|
@ -304,8 +293,9 @@ fi
|
||||||
new "wait backend"
|
new "wait backend"
|
||||||
wait_backend
|
wait_backend
|
||||||
|
|
||||||
new "get status 1"
|
new "6. get status stopped"
|
||||||
testrpc status 0 > /dev/null
|
rpcstatus false stopped
|
||||||
|
if [ $pid -ne 0 ]; then err "Pid" "$pid"; fi
|
||||||
|
|
||||||
RESTCONFIG1=$(cat <<EOF
|
RESTCONFIG1=$(cat <<EOF
|
||||||
<restconf xmlns="http://clicon.org/restconf">
|
<restconf xmlns="http://clicon.org/restconf">
|
||||||
|
|
@ -325,12 +315,14 @@ new "commit create"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
# pid
|
# pid
|
||||||
pid1=$(testrpc status 1)
|
new "7. get status, get pid1"
|
||||||
|
rpcstatus true running
|
||||||
|
pid1=$pid
|
||||||
|
if [ $pid1 -eq 0 ]; then err "Pid" 0; fi
|
||||||
sleep $DEMSLEEP
|
sleep $DEMSLEEP
|
||||||
|
|
||||||
new "Get restconf config 1"
|
new "Get restconf config 1"
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/clixon-restconf:restconf)" 0 "HTTP/1.1 200 OK" "<restconf xmlns=\"http://clicon.org/restconf\"><enable>true</enable><auth-type>none</auth-type><debug>0</debug><pretty>false</pretty><socket><namespace>default</namespace><address>0.0.0.0</address><port>80</port><ssl>false</ssl></socket></restconf>"
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/clixon-restconf:restconf)" 0 "HTTP/1.1 200 OK" "<restconf xmlns=\"http://clicon.org/restconf\"><enable>true</enable><auth-type>none</auth-type><debug>$RESTCONFDBG</debug><pretty>false</pretty><socket><namespace>default</namespace><address>0.0.0.0</address><port>80</port><ssl>false</ssl></socket></restconf>"
|
||||||
|
|
||||||
# remove it
|
# remove it
|
||||||
new "Delete server"
|
new "Delete server"
|
||||||
|
|
@ -339,15 +331,21 @@ expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS xmlns:nc=\"
|
||||||
new "commit delete"
|
new "commit delete"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "Get restconf config 2"
|
# Here restconf should have been restarted with no listener, the process is up but does not
|
||||||
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/clixon-restconf:restconf)" 0 "HTTP/1.1 200 OK" "<restconf xmlns=\"http://clicon.org/restconf\"><enable>true</enable><auth-type>none</auth-type><debug>0</debug><pretty>false</pretty></restconf>"
|
# reply on restconf
|
||||||
|
|
||||||
pid2=$(testrpc status 1)
|
new "8. get status, get different pid2"
|
||||||
|
rpcstatus true running
|
||||||
|
pid2=$pid
|
||||||
|
if [ $pid1 -eq 0 ]; then err "Pid" 0; fi
|
||||||
|
|
||||||
if [ $pid1 -ne $pid2 ]; then
|
if [ $pid1 -eq $pid2 ]; then
|
||||||
err "Same pid:$pid1" "$pid2"
|
err1 "A different pid" "same pid: $pid1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
new "Get restconf config 2: no server"
|
||||||
|
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/clixon-restconf:restconf 2>&1)" 7 "Failed to connect" "Connection refused"
|
||||||
|
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
|
|
@ -359,6 +357,8 @@ if [ $BE -ne 0 ]; then
|
||||||
stop_backend -f $cfg
|
stop_backend -f $cfg
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
fi # "${WITH_RESTCONF}" != "fcgi"
|
||||||
|
|
||||||
new "endtest"
|
new "endtest"
|
||||||
endtest
|
endtest
|
||||||
|
|
||||||
|
|
@ -726,6 +726,8 @@ module clixon-config {
|
||||||
description
|
description
|
||||||
"If set, enable process-control of restconf daemon, ie start/stop restconf
|
"If set, enable process-control of restconf daemon, ie start/stop restconf
|
||||||
daemon internally from backend daemon.
|
daemon internally from backend daemon.
|
||||||
|
Also, if set, restconf daemon queries backend for its config
|
||||||
|
if not set, restconf daemon reads its config from main config file
|
||||||
It uses clixon-restconf.yang for config and clixon-lib.yang for RPC
|
It uses clixon-restconf.yang for config and clixon-lib.yang for RPC
|
||||||
Process control of restconf daemon is as follows:
|
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 start, if enable is true, start the service, if false, error or ignore it
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,10 @@ module clixon-lib {
|
||||||
leaf active {
|
leaf active {
|
||||||
description
|
description
|
||||||
"True if process is running, false if not.
|
"True if process is running, false if not.
|
||||||
More specifically, there is a process-id and it exists (in Linux: kill(pid,0)";
|
More specifically, there is a process-id and it exists (in Linux: kill(pid,0).
|
||||||
|
Note that this is actual state and status is administrative state,
|
||||||
|
which means that changing the administrative state, eg stopped->running
|
||||||
|
may not immediately switch active to true.";
|
||||||
type boolean;
|
type boolean;
|
||||||
}
|
}
|
||||||
leaf description {
|
leaf description {
|
||||||
|
|
@ -196,8 +199,13 @@ module clixon-lib {
|
||||||
description "Start command with arguments";
|
description "Start command with arguments";
|
||||||
}
|
}
|
||||||
leaf status {
|
leaf status {
|
||||||
description "Exit Status as defined by waitpid() - if exited";
|
description
|
||||||
type int32;
|
"Administrative status (except on external kill where it enters stopped
|
||||||
|
directly from running):
|
||||||
|
stopped: pid=0, No process running
|
||||||
|
running: pid set, Process started and believed to be running
|
||||||
|
exiting: pid set, Process is killed by parent but not waited for";
|
||||||
|
type string;
|
||||||
}
|
}
|
||||||
leaf starttime {
|
leaf starttime {
|
||||||
description "Time of starting process UTC";
|
description "Time of starting process UTC";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue