Backend daemon startup modes

This commit is contained in:
Olof hagsand 2017-11-19 11:52:30 +01:00
parent 23e40384f7
commit 496d676ad3
26 changed files with 769 additions and 280 deletions

View file

@ -1,7 +1,15 @@
# Clixon CHANGELOG
# 3.3.3 (Upcoming)
## 3.3.3 Upcoming
### Known issues
### Major changes:
* Introducing backend daemon startup modes. The flags -IRCr and option CLICON_USE_STARTUP_CONFIG are replaced with command-line option -s <mode> and option CLICON_STARTUP_MODE. You need to replace the starting of clixon_backend as follows:
-I replace with "init" (as -s command line option or CLICON_STARTUP_MODE option)
-CIr replace with "running"
null replace with "none"
CLICON_USE_STARTUP_CONFIG=1 replace with "startup"
Backward compatibility is enabled by defining BACKEND_STARTUP_BACKWARD_COMPAT in include/clixon_custom.h
### Minor changes:
* When user callbacks such as statedata() call returns -1, clixon_backend no
longer silently exits. Instead a log is printed and an RPC error is returned.
* Added Floating point and negative number support to JSON
@ -45,7 +53,7 @@ clixon_cli -f /usr/local/etc/routing.conf -1x
* Support for non-line scrolling in CLI, eg wrap lines. Set with:
CLICON_CLI_LINESCROLLING 0
## 3.3.2 Aug 27 2017
# 3.3.2 (Aug 27 2017)
### Known issues
* Please use text datastore, key-value datastore no up-to-date
@ -138,7 +146,7 @@ If you submit "nopresence" without a leaf, it will automatically be removed:
* Restconf GET will return state data also, if defined.
* You need to define state data in a backend callback. See the example and documentation for more details.
### Minor changes:
### Minor Changes
* Added xpath support for predicate: current(), eg /interface[name=current()/../name]
* Added prefix parsing of xpath, allowing eg /p:x/p:y, but prefix ignored.
* Corrected Yang union CLI generation and type validation. Recursive unions did not work.
@ -154,7 +162,7 @@ If you submit "nopresence" without a leaf, it will automatically be removed:
* Removed vector return values from xmldb_get()
* Generalized yang type resolution to all included (sub)modules not just the topmost
## 3.3.1 June 7 2017
# 3.3.1 (June 7 2017)
* Fixed yang leafref cli completion for absolute paths.
@ -162,9 +170,7 @@ If you submit "nopresence" without a leaf, it will automatically be removed:
* Strings in xmldb_put not properly encoded, eg eth/0 became eth.00000
## 3.3.0
May 2017
# 3.3.0 (May 2017)
* Datastore text module is now default.
@ -205,7 +211,7 @@ May 2017
Instead use the rpc calls in clixon_proto_client.[ch]
In clients (eg cli/netconf) replace xmldb_get() in client code with
clicon_rpc_get_config().
If you use the vector arguments of xmldb_get(), replace as follows:
pIf you use the vector arguments of xmldb_get(), replace as follows:
xmldb_get(h, db, api_path, &xt, &xvec, &xlen);
with
clicon_rpc_get_config(h, dbstr, api_path, &xt);
@ -273,7 +279,9 @@ May 2017
* Added union type check for non-cli (eg xml) input
* Empty yang type. Relaxed yang types for unions, eg two strings with different length.
Dec 2016: Dual license: both GPLv3 and APLv2
# (Dec 2016)
* Dual license: both GPLv3 and APLv2
Feb 2016: Forked new clixon repository from clicon
# (Feb 2016)
* Forked new clixon repository from clicon

View file

@ -73,7 +73,11 @@
#include "backend_handle.h"
/* Command line options to be passed to getopt(3) */
#define BACKEND_OPTS "hD:f:d:b:Fzu:P:1IRCc:rg:py:x:"
#ifdef BACKEND_STARTUP_BACKWARD_COMPAT
#define BACKEND_OPTS "hD:f:d:b:Fzu:P:1s:c:IRCrg:py:x:" /* substitute s: for IRCc:r */
#else
#define BACKEND_OPTS "hD:f:d:b:Fzu:P:1s:c:g:py:x:" /* substitute s: for IRCc:r */
#endif
/*! Terminate. Cannot use h after this */
static int
@ -114,8 +118,7 @@ backend_sig_term(int arg)
clicon_exit_set(); /* checked in event_loop() */
}
/*
* usage
/*! usage
*/
static void
usage(char *argv0, clicon_handle h)
@ -137,11 +140,14 @@ usage(char *argv0, clicon_handle h)
" -1\t\tRun once and then quit (dont wait for events)\n"
" -u <path>\tConfig UNIX domain path / ip address (default: %s)\n"
" -P <file>\tPid filename (default: %s)\n"
" -s <mode>\tSpecify backend startup mode: none|startup|running|init (replaces -IRCc:r:\n"
" -c <file>\tLoad extra xml configuration, but don't commit.\n"
#ifdef BACKEND_STARTUP_BACKWARD_COMPAT
" -I\t\tInitialize running state database\n"
" -R\t\tCall plugin_reset() in plugins to reset system state in running db (use with -I)\n"
" -C\t\tCall plugin_reset() in plugins to reset system state in candidate db (use with -I)\n"
" -c <file>\tLoad specified application config.\n"
" -r\t\tReload running database\n"
#endif /* BACKEND_STARTUP_BACKWARD_COMPAT */
" -p \t\tPrint database yang specification\n"
" -g <group>\tClient membership required to this group (default: %s)\n"
" -y <file>\tOverride yang spec file (dont include .yang suffix)\n"
@ -166,69 +172,26 @@ db_reset(clicon_handle h,
return 0;
}
/*! Initialize running-config from file application configuration
*
* @param[in] h clicon handle
* @param[in] app_config_file clicon application configuration file
* @param[in] running_db Name of running db
* @retval 0 OK
* @retval -1 Error. clicon_err set
/*! Merge db1 into db2 without commit
*/
static int
rundb_main(clicon_handle h,
char *app_config_file)
db_merge(clicon_handle h,
const char *db1,
const char *db2)
{
int retval = -1;
int fd = -1;
cxobj *xt = NULL;
cxobj *xn;
if (xmldb_create(h, "tmp") < 0)
/* Get data as xml from db1 */
if (xmldb_get(h, (char*)db1, NULL, 1, &xt) < 0)
goto done;
if (xmldb_copy(h, "running", "tmp") < 0){
clicon_err(OE_UNIX, errno, "file copy");
goto done;
}
if ((fd = open(app_config_file, O_RDONLY)) < 0){
clicon_err(OE_UNIX, errno, "open(%s)", app_config_file);
goto done;
}
if (clicon_xml_parse_file(fd, &xt, "</clicon>") < 0)
goto done;
if ((xn = xml_child_i(xt, 0)) != NULL)
if (xmldb_put(h, "tmp", OP_MERGE, xn) < 0)
goto done;
if (candidate_commit(h, "tmp") < 0)
goto done;
if (xmldb_delete(h, "tmp") < 0)
goto done;
retval = 0;
done:
if (xt)
xml_free(xt);
if (fd != -1)
close(fd);
return retval;
}
static int
candb_reset(clicon_handle h)
{
int retval = -1;
if (xmldb_copy(h, "running", "tmp") < 0){
clicon_err(OE_UNIX, errno, "file copy");
goto done;
}
/* Request plugins to reset system state, eg initiate running from system
* -R
*/
if (plugin_reset_state(h, "tmp") < 0)
goto done;
if (candidate_commit(h, "tmp") < 0)
/* Merge xml into db2. WIthout commit */
if (xmldb_put(h, (char*)db2, OP_MERGE, xt) < 0)
goto done;
retval = 0;
done:
if (xt)
xml_free(xt);
return retval;
}
@ -291,6 +254,337 @@ backend_log_cb(int level,
return retval;
}
/*! Call plugin_start with -- user options */
static int
plugin_start_useroptions(clicon_handle h,
char *argv0,
int argc,
char **argv)
{
char *tmp;
tmp = *(argv-1);
*(argv-1) = argv0;
if (plugin_start_argv(h, argc+1, argv-1) < 0)
return -1;
*(argv-1) = tmp;
return 0;
}
#ifdef BACKEND_STARTUP_BACKWARD_COMPAT
/*! Initialize running-config from file application configuration
*
* @param[in] h clicon handle
* @param[in] extraxml_file clicon application configuration file
* @param[in] running_db Name of running db
* @retval 0 OK
* @retval -1 Error. clicon_err set
*/
static int
rundb_main(clicon_handle h,
char *extraxml_file)
{
int retval = -1;
int fd = -1;
cxobj *xt = NULL;
cxobj *xn;
if (xmldb_create(h, "tmp") < 0)
goto done;
if (xmldb_copy(h, "running", "tmp") < 0)
goto done;
if ((fd = open(extraxml_file, O_RDONLY)) < 0){
clicon_err(OE_UNIX, errno, "open(%s)", extraxml_file);
goto done;
}
if (clicon_xml_parse_file(fd, &xt, "</clicon>") < 0)
goto done;
if ((xn = xml_child_i(xt, 0)) != NULL)
if (xmldb_put(h, "tmp", OP_MERGE, xn) < 0)
goto done;
if (candidate_commit(h, "tmp") < 0)
goto done;
if (xmldb_delete(h, "tmp") < 0)
goto done;
retval = 0;
done:
if (xt)
xml_free(xt);
if (fd != -1)
close(fd);
return retval;
}
static int
candb_reset(clicon_handle h)
{
int retval = -1;
if (xmldb_copy(h, "running", "tmp") < 0)
goto done;
/* Request plugins to reset system state, eg initiate running from system
* -R
*/
if (plugin_reset_state(h, "tmp") < 0)
goto done;
if (candidate_commit(h, "tmp") < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Legacy (old-style) startup mode where flags -IRCcr was used
*/
static int
fragmented_startup_mode(clicon_handle h,
char *argv0,
int argc,
char *argv[],
int reload_running,
int init_rundb,
int reset_state_candidate,
int reset_state_running,
char *extraxml_file)
{
int retval = -1;
/* First check for startup config */
if (clicon_option_int(h, "CLICON_USE_STARTUP_CONFIG") > 0){
if (xmldb_exists(h, "startup") == 1){
/* copy startup config -> running */
if (xmldb_copy(h, "startup", "running") < 0)
goto done;
}
else
if (db_reset(h, "running") < 0)
goto done;
if (xmldb_create(h, "candidate") < 0)
goto done;
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
}
/* If running exists and reload_running set, make a copy to candidate */
if (reload_running){
if (xmldb_exists(h, "running") != 1){
clicon_log(LOG_NOTICE, "%s: -r (reload running) option given but no running_db found, proceeding without", __PROGRAM__);
reload_running = 0; /* void it, so we dont commit candidate below */
}
else
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
}
/* Init running db
* -I or if it isnt there
*/
if (init_rundb || xmldb_exists(h, "running") != 1){
if (db_reset(h, "running") < 0)
goto done;
}
/* If candidate does not exist, create it from running */
if (xmldb_exists(h, "candidate") != 1){
if (xmldb_create(h, "candidate") < 0)
goto done;
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
}
/* Load plugins and call plugin_init() */
if (plugin_initiate(h) != 0)
goto done;
if (reset_state_candidate){
if (candb_reset(h) < 0)
goto done;
}
else
if (reset_state_running){
if (plugin_reset_state(h, "running") < 0)
goto done;
}
if (plugin_start_useroptions(h, argv0, argc, argv) <0)
goto done;
if (reload_running){
/* This could be a failed validation, and we should not fail for that */
(void)candidate_commit(h, "candidate");
}
/* Have we specified a config file to load? eg
* -c [<file>]
*/
if (extraxml_file)
if (rundb_main(h, extraxml_file) < 0)
goto done;
/* Initiate the shared candidate. */
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
retval = 0;
done:
return retval;
}
#endif /* BACKEND_STARTUP_BACKWARD_COMPAT */
/*! Merge xml in filename into database
*/
static int
load_extraxml(clicon_handle h,
char *filename,
const char *db)
{
int retval = -1;
cxobj *xt = NULL;
int fd = -1;
if (filename == NULL)
return 0;
if ((fd = open(filename, O_RDONLY)) < 0){
clicon_err(OE_UNIX, errno, "open(%s)", filename);
goto done;
}
if (clicon_xml_parse_file(fd, &xt, "</config>") < 0)
goto done;
/* Replace parent w first child */
if (xml_rootchild(xt, 0, &xt) < 0)
goto done;
/* Merge user reset state */
if (xmldb_put(h, (char*)db, OP_MERGE, xt) < 0)
goto done;
retval = 0;
done:
if (fd != -1)
close(fd);
if (xt)
xml_free(xt);
return retval;
}
/*! Clixon none startup modes Do not touch running state
*/
static int
startup_mode_none(clicon_handle h)
{
int retval = -1;
/* If it is not there, create candidate from running */
if (xmldb_exists(h, "candidate") != 1)
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
/* Load plugins and call plugin_init() */
if (plugin_initiate(h) != 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Clixon init startup modes Start with a completely clean running state
*/
static int
startup_mode_init(clicon_handle h)
{
int retval = -1;
/* Reset running, regardless */
if (db_reset(h, "running") < 0)
goto done;
/* If it is not there, create candidate from running */
if (xmldb_exists(h, "candidate") != 1)
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
/* Load plugins and call plugin_init() */
if (plugin_initiate(h) != 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Clixon running startup mode: Commit running db configuration into running
*
copy reset commit merge
running----+ |--------------------+-----+------>
\ / /
candidate +--------------------+ /
/
tmp |-------+-----+---------+
reset extra file
*/
static int
startup_mode_running(clicon_handle h,
char *extraxml_file)
{
int retval = -1;
/* Stash original running to candidate for later commit */
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
/* Load plugins and call plugin_init() */
if (plugin_initiate(h) != 0)
goto done;
/* Clear tmp db */
if (db_reset(h, "tmp") < 0)
goto done;
/* Application may define extra xml in its reset function*/
if (plugin_reset_state(h, "tmp") < 0)
goto done;
/* Get application extra xml from file */
if (load_extraxml(h, extraxml_file, "tmp") < 0)
goto done;
/* Commit original running */
if (candidate_commit(h, "candidate") < 0)
goto done;
/* Merge user reset state and extra xml file (no commit) */
if (db_merge(h, "tmp", "running") < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Clixon startup startup mode: Commit startup configuration into running state
reset commit merge
running |--------------------+-----+------>
/ /
startup --------------------+ /
/
tmp |-------+-----+---------+
reset extra file
*/
static int
startup_mode_startup(clicon_handle h,
char *extraxml_file)
{
int retval = -1;
/* If startup does not exist, clear it */
if (xmldb_exists(h, "startup") != 1) /* diff */
if (xmldb_create(h, "startup") < 0) /* diff */
return -1;
/* Load plugins and call plugin_init() */
if (plugin_initiate(h) != 0)
goto done;
/* Clear tmp db */
if (db_reset(h, "tmp") < 0)
goto done;
/* Application may define extra xml in its reset function*/
if (plugin_reset_state(h, "tmp") < 0)
goto done;
/* Get application extra xml from file */
if (load_extraxml(h, extraxml_file, "tmp") < 0)
goto done;
/* Commit startup */
if (candidate_commit(h, "startup") < 0) /* diff */
goto done;
/* Merge user reset state and extra xml file (no commit) */
if (db_merge(h, "tmp", "running") < 0)
goto done;
retval = 0;
done:
return retval;
}
int
main(int argc, char **argv)
{
@ -298,14 +592,16 @@ main(int argc, char **argv)
int zap;
int foreground;
int once;
int init_rundb;
int reload_running;
int reset_state_running;
int reset_state_candidate;
char *app_config_file = NULL;
enum startup_mode_t startup_mode;
#ifdef BACKEND_STARTUP_BACKWARD_COMPAT
int init_rundb = 0;
int reset_state_running = 0;
int reset_state_candidate = 0;
int reload_running = 0;
#endif
char *extraxml_file;
char *config_group;
char *argv0 = argv[0];
char *tmp;
struct stat st;
clicon_handle h;
int help = 0;
@ -317,7 +613,6 @@ main(int argc, char **argv)
char *xmldb_plugin;
/* In the startup, logs to stderr & syslog and debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, CLICON_LOG_STDERR|CLICON_LOG_SYSLOG);
/* Initiate CLICON handle */
if ((h = backend_handle_init()) == NULL)
@ -327,10 +622,7 @@ main(int argc, char **argv)
foreground = 0;
once = 0;
zap = 0;
init_rundb = 0;
reload_running = 0;
reset_state_running = 0;
reset_state_candidate = 0;
extraxml_file = NULL;
/*
* Command-line options for help, debug, and config-file
@ -410,6 +702,17 @@ main(int argc, char **argv)
case 'P': /* pidfile */
clicon_option_str_set(h, "CLICON_BACKEND_PIDFILE", optarg);
break;
case 's' : /* startup mode */
clicon_option_str_set(h, "CLICON_STARTUP_MODE", optarg);
if (clicon_startup_mode(h) < 0){
fprintf(stderr, "Invalid startup mode: %s\n", optarg);
usage(argv[0], h);
}
break;
case 'c': /* Load application config */
extraxml_file = optarg;
break;
#ifdef BACKEND_STARTUP_BACKWARD_COMPAT
case 'I': /* Initiate running db */
init_rundb++;
break;
@ -419,12 +722,10 @@ main(int argc, char **argv)
case 'C': /* Reset state into candidate and then commit it */
reset_state_candidate++;
break;
case 'c': /* Load application config */
app_config_file = optarg;
break;
case 'r': /* Reload running */
reload_running++;
break;
#endif /* BACKEND_STARTUP_BACKWARD_COMPAT */
case 'g': /* config socket group */
clicon_option_str_set(h, "CLICON_SOCK_GROUP", optarg);
break;
@ -522,87 +823,52 @@ main(int argc, char **argv)
goto done;
if (xmldb_setopt(h, "yangspec", clicon_dbspec_yang(h)) < 0)
goto done;
/* First check for startup config
XXX the options below have become out-of-hand.
Too complex, need to simplify*/
if (clicon_option_int(h, "CLICON_USE_STARTUP_CONFIG") > 0){
if (xmldb_exists(h, "startup") == 1){
/* copy startup config -> running */
if (xmldb_copy(h, "startup", "running") < 0)
/* If startup mode is not defined, eg via OPTION or -s, assume old method */
startup_mode = clicon_startup_mode(h);
if (startup_mode == -1){ /* Old style, fragmented mode, phase out */
#ifdef BACKEND_STARTUP_BACKWARD_COMPAT
if (fragmented_startup_mode(h,
argv0, argc, argv,
reload_running, init_rundb,
reset_state_candidate, reset_state_running,
extraxml_file
) < 0)
goto done;
#else
clicon_log(LOG_ERR, "Startup mode indefined. Specify option CLICON_STARTUP_MODE or specify -s option to clicon_backend.\n");
#endif
}
else
if (db_reset(h, "running") < 0)
goto done;
if (xmldb_create(h, "candidate") < 0)
goto done;
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
}
/* If running exists and reload_running set, make a copy to candidate */
if (reload_running){
if (xmldb_exists(h, "running") != 1){
clicon_log(LOG_NOTICE, "%s: -r (reload running) option given but no running_db found, proceeding without", __PROGRAM__);
reload_running = 0; /* void it, so we dont commit candidate below */
}
else
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
}
/* Init running db
* -I or if it isnt there
else {
/* Init running db if it is not there
*/
if (init_rundb || xmldb_exists(h, "running") != 1){
if (db_reset(h, "running") < 0)
if (xmldb_exists(h, "running") != 1)
if (xmldb_create(h, "running") < 0)
return -1;
switch (startup_mode){
case SM_NONE:
if (startup_mode_none(h) < 0)
goto done;
break;
case SM_INIT: /* -I */
if (startup_mode_init(h) < 0)
goto done;
break;
case SM_RUNNING: /* -CIr */
if (startup_mode_running(h, extraxml_file) < 0)
goto done;
break;
case SM_STARTUP: /* startup configuration */
if (startup_mode_startup(h, extraxml_file) < 0)
goto done;
break;
}
/* If candidate does not exist, create it from running */
if (xmldb_exists(h, "candidate") != 1){
if (xmldb_create(h, "candidate") < 0)
goto done;
/* Initiate the shared candidate. */
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
}
/* Initialize plugins
(also calls plugin_init() and plugin_start(argc,argv) in each plugin */
if (plugin_initiate(h) != 0)
goto done;
if (reset_state_candidate){
if (candb_reset(h) < 0)
/* Call plugin_start with user -- options */
if (plugin_start_useroptions(h, argv0, argc, argv) <0)
goto done;
}
else
if (reset_state_running){
if (plugin_reset_state(h, "running") < 0)
goto done;
}
/* Call plugin_start */
tmp = *(argv-1);
*(argv-1) = argv0;
if (plugin_start_hooks(h, argc+1, argv-1) < 0)
goto done;
*(argv-1) = tmp;
if (reload_running){
/* This could be a failed validation, and we should not fail for that */
(void)candidate_commit(h, "candidate");
}
/* Have we specified a config file to load? eg
* -c [<file>]
*/
if (app_config_file)
if (rundb_main(h, app_config_file) < 0)
goto done;
/* Initiate the shared candidate. Maybe we should not do this?
* Too strict access
*/
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
if (once)
goto done;

View file

@ -71,7 +71,7 @@
* @note the following should match the prototypes in clixon_backend.h
*/
#define PLUGIN_RESET "plugin_reset"
typedef int (plgreset_t)(clicon_handle h, char *dbname); /* Reset system status */
typedef int (plgreset_t)(clicon_handle h, const char *db); /* Reset system status */
/*! Plugin callback, if defined called to get state data from plugin
* @param[in] h Clicon handle
@ -254,18 +254,17 @@ backend_plugin_load (clicon_handle h,
*/
int
plugin_reset_state(clicon_handle h,
char *dbname)
const char *db)
{
int i;
struct plugin *p;
for (i = 0; i < _nplugins; i++) {
p = &_plugins[i];
if (p->p_reset) {
clicon_debug(1, "Calling plugin_reset() for %s\n",
p->p_name);
if (((p->p_reset)(h, dbname)) < 0) {
if (((p->p_reset)(h, db)) < 0) {
clicon_err(OE_FATAL, 0, "plugin_reset() failed for %s\n",
p->p_name);
return -1;
@ -283,7 +282,7 @@ plugin_reset_state(clicon_handle h,
* @retval -1 Error
*/
int
plugin_start_hooks(clicon_handle h,
plugin_start_argv(clicon_handle h,
int argc,
char **argv)
{

View file

@ -66,8 +66,8 @@ int backend_plugin_init(clicon_handle h);
int plugin_initiate(clicon_handle h);
int plugin_finish(clicon_handle h);
int plugin_reset_state(clicon_handle h, char *dbname);
int plugin_start_hooks(clicon_handle h, int argc, char **argv);
int plugin_reset_state(clicon_handle h, const char *db);
int plugin_start_argv(clicon_handle h, int argc, char **argv);
int backend_statedata_call(clicon_handle h, char *xpath, cxobj *xml);

View file

@ -70,7 +70,7 @@ int plugin_exit(clicon_handle h);
/*! Reset system state to original state. Eg at reboot before running thru config.
* @see plgreset_t
*/
int plugin_reset(clicon_handle h, char *dbname);
int plugin_reset(clicon_handle h, const char *db);
/*! Retreive statedata, add statedata to XML tree
* @see plgstatedata_ t

View file

@ -150,7 +150,7 @@ static int _startup_locked = 0;
*/
static int
kv_db2file(struct kv_handle *kh,
char *db,
const char *db,
char **filename)
{
int retval = -1;
@ -565,7 +565,7 @@ kv_setopt(xmldb_handle xh,
*/
int
kv_get(xmldb_handle xh,
char *db,
const char *db,
char *xpath,
int config,
cxobj **xtop)
@ -783,7 +783,7 @@ put(char *dbfile,
*/
int
kv_put(xmldb_handle xh,
char *db,
const char *db,
enum operation_type op,
cxobj *xt)
{
@ -836,8 +836,8 @@ kv_put(xmldb_handle xh,
*/
int
kv_copy(xmldb_handle xh,
char *from,
char *to)
const char *from,
const char *to)
{
int retval = -1;
struct kv_handle *kh = handle(xh);
@ -869,7 +869,7 @@ kv_copy(xmldb_handle xh,
*/
int
kv_lock(xmldb_handle xh,
char *db,
const char *db,
int pid)
{
int retval = -1;
@ -900,7 +900,7 @@ kv_lock(xmldb_handle xh,
*/
int
kv_unlock(xmldb_handle xh,
char *db)
const char *db)
{
int retval = -1;
// struct kv_handle *kh = handle(xh);
@ -949,7 +949,7 @@ kv_unlock_all(xmldb_handle xh,
*/
int
kv_islocked(xmldb_handle xh,
char *db)
const char *db)
{
int retval = -1;
// struct kv_handle *kh = handle(xh);
@ -974,7 +974,7 @@ kv_islocked(xmldb_handle xh,
*/
int
kv_exists(xmldb_handle xh,
char *db)
const char *db)
{
int retval = -1;
struct kv_handle *kh = handle(xh);
@ -1001,7 +1001,7 @@ kv_exists(xmldb_handle xh,
*/
int
kv_delete(xmldb_handle xh,
char *db)
const char *db)
{
int retval = -1;
struct kv_handle *kh = handle(xh);
@ -1026,7 +1026,7 @@ kv_delete(xmldb_handle xh,
*/
int
kv_create(xmldb_handle xh,
char *db)
const char *db)
{
int retval = -1;
struct kv_handle *kh = handle(xh);

View file

@ -39,16 +39,16 @@
/*
* Prototypes
*/
int kv_get(xmldb_handle h, char *db, char *xpath, int config, cxobj **xtop);
int kv_put(xmldb_handle h, char *db, enum operation_type op, cxobj *xt);
int kv_get(xmldb_handle h, const char *db, char *xpath, int config, cxobj **xtop);
int kv_put(xmldb_handle h, const char *db, enum operation_type op, cxobj *xt);
int kv_dump(FILE *f, char *dbfilename, char *rxkey);
int kv_copy(xmldb_handle h, char *from, char *to);
int kv_lock(xmldb_handle h, char *db, int pid);
int kv_unlock(xmldb_handle h, char *db);
int kv_copy(xmldb_handle h, const char *from, const char *to);
int kv_lock(xmldb_handle h, const char *db, int pid);
int kv_unlock(xmldb_handle h, const char *db);
int kv_unlock_all(xmldb_handle h, int pid);
int kv_islocked(xmldb_handle h, char *db);
int kv_exists(xmldb_handle h, char *db);
int kv_delete(xmldb_handle h, char *db);
int kv_init(xmldb_handle h, char *db);
int kv_islocked(xmldb_handle h, const char *db);
int kv_exists(xmldb_handle h, const char *db);
int kv_delete(xmldb_handle h, const char *db);
int kv_init(xmldb_handle h, const char *db);
#endif /* _CLIXON_KEYVALUE_H */

View file

@ -99,7 +99,7 @@ text_handle_check(xmldb_handle xh)
*/
static int
text_db2file(struct text_handle *th,
char *db,
const char *db,
char **filename)
{
int retval = -1;
@ -281,7 +281,7 @@ singleconfigroot(cxobj *xt,
*/
int
text_get(xmldb_handle xh,
char *db,
const char *db,
char *xpath,
int config,
cxobj **xtop)
@ -681,7 +681,7 @@ xml_container_presence(cxobj *x,
*/
int
text_put(xmldb_handle xh,
char *db,
const char *db,
enum operation_type op,
cxobj *x1)
{
@ -807,8 +807,8 @@ text_put(xmldb_handle xh,
*/
int
text_copy(xmldb_handle xh,
char *from,
char *to)
const char *from,
const char *to)
{
int retval = -1;
struct text_handle *th = handle(xh);
@ -840,7 +840,7 @@ text_copy(xmldb_handle xh,
*/
int
text_lock(xmldb_handle xh,
char *db,
const char *db,
int pid)
{
struct text_handle *th = handle(xh);
@ -860,7 +860,7 @@ text_lock(xmldb_handle xh,
*/
int
text_unlock(xmldb_handle xh,
char *db)
const char *db)
{
struct text_handle *th = handle(xh);
int zero = 0;
@ -905,7 +905,7 @@ text_unlock_all(xmldb_handle xh,
*/
int
text_islocked(xmldb_handle xh,
char *db)
const char *db)
{
struct text_handle *th = handle(xh);
size_t vlen;
@ -926,7 +926,7 @@ text_islocked(xmldb_handle xh,
*/
int
text_exists(xmldb_handle xh,
char *db)
const char *db)
{
int retval = -1;
@ -954,7 +954,7 @@ text_exists(xmldb_handle xh,
*/
int
text_delete(xmldb_handle xh,
char *db)
const char *db)
{
int retval = -1;
char *filename = NULL;
@ -974,6 +974,7 @@ text_delete(xmldb_handle xh,
}
/*! Create / init database
* If it exists dont change.
* @param[in] xh XMLDB handle
* @param[in] db Database
* @retval 0 OK
@ -981,7 +982,7 @@ text_delete(xmldb_handle xh,
*/
int
text_create(xmldb_handle xh,
char *db)
const char *db)
{
int retval = -1;
struct text_handle *th = handle(xh);

View file

@ -39,16 +39,16 @@
/*
* Prototypes
*/
int text_get(xmldb_handle h, char *db, char *xpath, int config, cxobj **xtop);
int text_put(xmldb_handle h, char *db, enum operation_type op, cxobj *xt);
int text_get(xmldb_handle h, const char *db, char *xpath, int config, cxobj **xtop);
int text_put(xmldb_handle h, const char *db, enum operation_type op, cxobj *xt);
int text_dump(FILE *f, char *dbfilename, char *rxkey);
int text_copy(xmldb_handle h, char *from, char *to);
int text_lock(xmldb_handle h, char *db, int pid);
int text_unlock(xmldb_handle h, char *db);
int text_copy(xmldb_handle h, const char *from, const char *to);
int text_lock(xmldb_handle h, const char *db, int pid);
int text_unlock(xmldb_handle h, const char *db);
int text_unlock_all(xmldb_handle h, int pid);
int text_islocked(xmldb_handle h, char *db);
int text_exists(xmldb_handle h, char *db);
int text_delete(xmldb_handle h, char *db);
int text_init(xmldb_handle h, char *db);
int text_islocked(xmldb_handle h, const char *db);
int text_exists(xmldb_handle h, const char *db);
int text_delete(xmldb_handle h, const char *db);
int text_init(xmldb_handle h, const char *db);
#endif /* _CLIXON_XMLDB_TEXT_H */

View file

@ -23,8 +23,8 @@ APIs. There are currently plugins for: CLI, Netconf, Restconf, the datastore an
Clixon is written in C. The plugins are written in C. The CLI
specification uses cligen (http://cligen.se)
There is a project for writing plugins in Python. It is reasonable
simple to spawn an external script from a backend.
It is possible ro write plugins in Python. It is reasonable
simple to spawn an external script from a backend (but needs to be done).
## How to best understand Clixon?
Run the ietf yang routing example, in the example directory.

View file

@ -179,8 +179,10 @@ plugin_statedata(clicon_handle h,
return retval;
}
/*
* Plugin initialization
/*! Plugin initialization. Create rpc callbacks
* plugin_init is called as soon as the plugin has been loaded and is
* assumed initialize the plugin's internal state if any as well as register
* any callbacks, configuration dependencies.
*/
int
plugin_init(clicon_handle h)
@ -205,3 +207,57 @@ plugin_init(clicon_handle h)
return retval;
}
/*! Plugin state reset. Add xml or set state in backend machine.
* Called in each backend plugin. plugin_reset is called after all plugins
* have been initialized. This give the application a chance to reset
* system state back to a base state.
* This is generally done when a system boots up to
* make sure the initial system state is well defined. This can be creating
* default configuration files for various daemons, set interface flags etc.
* @param[in] h Clicon handle
* @param[in] db Name of database. Not may be other than "running"
* In this example, a loopback interface is added
*/
int
plugin_reset(clicon_handle h,
const char *db)
{
int retval = -1;
cxobj *xt = NULL;
if (clicon_xml_parse_str("<config><interfaces><interface>"
"<name>lo</name><type>local</type>"
"</interface></interfaces></config>", &xt) < 0)
goto done;
/* Replace parent w fiorst child */
if (xml_rootchild(xt, 0, &xt) < 0)
goto done;
/* Merge user reset state */
if (xmldb_put(h, (char*)db, OP_MERGE, xt) < 0)
goto done;
retval = 0;
done:
if (xt != NULL)
free(xt);
return retval;
}
/*! Plugin start.
* @param[in] h Clicon handle
* @param[in] argc Argument vector length (args after -- to backend_main)
* @param[in] argv Argument vector
*
* plugin_start is called once everything has been initialized, right before
* the main event loop is entered. Command line options can be passed to the
* plugins by using "-- <args>" where <args> is any choice of
* options specific to the application. These options are passed to the
* plugin_start function via the argc and argv arguments which
* can be processed with the standard getopt(3).
*/
int
plugin_start(clicon_handle h,
int argc,
char **argv)
{
return 0;
}

View file

@ -47,3 +47,10 @@ int strverscmp (__const char *__s1, __const char *__s2);
* Experimental
*/
#define XML_CHILD_HASH 1
/* Backward compatible clixon backend daemon startup sequences
* This has been replaced with -s <mode> and CLICON_STARTUP_MODE
* define if enable backward compatible behaviour
* Remove in 3.3.4
*/
#undef BACKEND_STARTUP_BACKWARD_COMPAT

View file

@ -63,6 +63,13 @@ enum genmodel_type{
GT_ALL, /* Keywords on all variables */
};
/*! See clixon-config.yang type startup_mode */
enum startup_mode_t{
SM_NONE=0,
SM_STARTUP,
SM_RUNNING,
SM_INIT
};
/*
* Prototypes
@ -93,6 +100,7 @@ char *clicon_clispec_dir(clicon_handle h);
char *clicon_netconf_dir(clicon_handle h);
char *clicon_restconf_dir(clicon_handle h);
char *clicon_xmldb_plugin(clicon_handle h);
int clicon_startup_mode(clicon_handle h);
int clicon_sock_family(clicon_handle h);
char *clicon_sock(clicon_handle h);
int clicon_sock_port(clicon_handle h);

View file

@ -75,34 +75,34 @@ typedef int (xmldb_getopt_t)(xmldb_handle xh, char *optname, void **value);
typedef int (xmldb_setopt_t)(xmldb_handle xh, char *optname, void *value);
/* Type of xmldb get function */
typedef int (xmldb_get_t)(xmldb_handle xh, char *db, char *xpath, int config, cxobj **xtop);
typedef int (xmldb_get_t)(xmldb_handle xh, const char *db, char *xpath, int config, cxobj **xtop);
/* Type of xmldb put function */
typedef int (xmldb_put_t)(xmldb_handle xh, char *db, enum operation_type op, cxobj *xt);
typedef int (xmldb_put_t)(xmldb_handle xh, const char *db, enum operation_type op, cxobj *xt);
/* Type of xmldb copy function */
typedef int (xmldb_copy_t)(xmldb_handle xh, char *from, char *to);
typedef int (xmldb_copy_t)(xmldb_handle xh, const char *from, const char *to);
/* Type of xmldb lock function */
typedef int (xmldb_lock_t)(xmldb_handle xh, char *db, int pid);
typedef int (xmldb_lock_t)(xmldb_handle xh, const char *db, int pid);
/* Type of xmldb unlock function */
typedef int (xmldb_unlock_t)(xmldb_handle xh, char *db);
typedef int (xmldb_unlock_t)(xmldb_handle xh, const char *db);
/* Type of xmldb unlock_all function */
typedef int (xmldb_unlock_all_t)(xmldb_handle xh, int pid);
/* Type of xmldb islocked function */
typedef int (xmldb_islocked_t)(xmldb_handle xh, char *db);
typedef int (xmldb_islocked_t)(xmldb_handle xh, const char *db);
/* Type of xmldb exists function */
typedef int (xmldb_exists_t)(xmldb_handle xh, char *db);
typedef int (xmldb_exists_t)(xmldb_handle xh, const char *db);
/* Type of xmldb delete function */
typedef int (xmldb_delete_t)(xmldb_handle xh, char *db);
typedef int (xmldb_delete_t)(xmldb_handle xh, const char *db);
/* Type of xmldb init function */
typedef int (xmldb_create_t)(xmldb_handle xh, char *db);
typedef int (xmldb_create_t)(xmldb_handle xh, const char *db);
/* plugin init struct for the api */
struct xmldb_api{
@ -133,20 +133,20 @@ struct xmldb_api{
int xmldb_plugin_load(clicon_handle h, char *filename);
int xmldb_plugin_unload(clicon_handle h);
int xmldb_validate_db(char *db);
int xmldb_validate_db(const char *db);
int xmldb_connect(clicon_handle h);
int xmldb_disconnect(clicon_handle h);
int xmldb_getopt(clicon_handle h, char *optname, void **value);
int xmldb_setopt(clicon_handle h, char *optname, void *value);
int xmldb_get(clicon_handle h, char *db, char *xpath, int config, cxobj **xtop);
int xmldb_put(clicon_handle h, char *db, enum operation_type op, cxobj *xt);
int xmldb_copy(clicon_handle h, char *from, char *to);
int xmldb_lock(clicon_handle h, char *db, int pid);
int xmldb_unlock(clicon_handle h, char *db);
int xmldb_get(clicon_handle h, const char *db, char *xpath, int config, cxobj **xtop);
int xmldb_put(clicon_handle h, const char *db, enum operation_type op, cxobj *xt);
int xmldb_copy(clicon_handle h, const char *from, const char *to);
int xmldb_lock(clicon_handle h, const char *db, int pid);
int xmldb_unlock(clicon_handle h, const char *db);
int xmldb_unlock_all(clicon_handle h, int pid);
int xmldb_islocked(clicon_handle h, char *db);
int xmldb_exists(clicon_handle h, char *db);
int xmldb_delete(clicon_handle h, char *db);
int xmldb_create(clicon_handle h, char *db);
int xmldb_islocked(clicon_handle h, const char *db);
int xmldb_exists(clicon_handle h, const char *db);
int xmldb_delete(clicon_handle h, const char *db);
int xmldb_create(clicon_handle h, const char *db);
#endif /* _CLIXON_XML_DB_H */

View file

@ -185,7 +185,7 @@ quit:
return retval;
}
/*! Make a copy of file src
/*! Make a copy of file src. Overwrite existing
* @retval 0 OK
* @retval -1 Error
*/

View file

@ -58,6 +58,7 @@
/* clicon */
#include "clixon_err.h"
#include "clixon_string.h"
#include "clixon_queue.h"
#include "clixon_hash.h"
#include "clixon_handle.h"
@ -69,6 +70,16 @@
#include "clixon_xsl.h"
#include "clixon_xml_map.h"
/* Mapping between Clicon startup modes string <--> constants,
see clixon-config.yang type startup_mode */
static const map_str2int startup_mode_map[] = {
{"none", SM_NONE},
{"running", SM_RUNNING},
{"startup", SM_STARTUP},
{"init", SM_INIT},
{NULL, -1}
};
/*! Print registry on file. For debugging.
*/
void
@ -332,7 +343,6 @@ clicon_option_sanity(clicon_hash_t *copt)
return retval;
}
/*! Initialize option values
*
* Set default options, Read config-file, Check that all values are set.
@ -387,9 +397,12 @@ clicon_options_main(clicon_handle h)
}
/*! Check if a clicon option has a value
* @param[in] h clicon_handle
* @param[in] name option name
*/
int
clicon_option_exists(clicon_handle h, const char *name)
clicon_option_exists(clicon_handle h,
const char *name)
{
clicon_hash_t *copt = clicon_options(h);
@ -449,7 +462,8 @@ clicon_option_str_set(clicon_handle h,
* supply a defualt value as shown in the example.
*/
int
clicon_option_int(clicon_handle h, const char *name)
clicon_option_int(clicon_handle h,
const char *name)
{
char *s;
@ -461,7 +475,9 @@ clicon_option_int(clicon_handle h, const char *name)
/*! Set option given as int.
*/
int
clicon_option_int_set(clicon_handle h, const char *name, int val)
clicon_option_int_set(clicon_handle h,
const char *name,
int val)
{
char s[64];
@ -473,7 +489,8 @@ clicon_option_int_set(clicon_handle h, const char *name, int val)
/*! Delete option
*/
int
clicon_option_del(clicon_handle h, const char *name)
clicon_option_del(clicon_handle h,
const char *name)
{
clicon_hash_t *copt = clicon_options(h);
@ -550,6 +567,15 @@ clicon_xmldb_plugin(clicon_handle h)
return clicon_option_str(h, "CLICON_XMLDB_PLUGIN");
}
int
clicon_startup_mode(clicon_handle h)
{
char *mode;
if ((mode = clicon_option_str(h, "CLICON_STARTUP_MODE")) == NULL)
return -1;
return clicon_str2int(startup_mode_map, mode);
}
/*! Get family of backend socket: AF_UNIX, AF_INET or AF_INET6 */
int
clicon_sock_family(clicon_handle h)

View file

@ -175,7 +175,7 @@ xmldb_plugin_unload(clicon_handle h)
* @retval -1 Failed validate, xret set to error
*/
int
xmldb_validate_db(char *db)
xmldb_validate_db(const char *db)
{
if (strcmp(db, "running") != 0 &&
strcmp(db, "candidate") != 0 &&
@ -336,7 +336,7 @@ xmldb_setopt(clicon_handle h,
*/
int
xmldb_get(clicon_handle h,
char *db,
const char *db,
char *xpath,
int config,
cxobj **xtop)
@ -393,7 +393,7 @@ xmldb_get(clicon_handle h,
*/
int
xmldb_put(clicon_handle h,
char *db,
const char *db,
enum operation_type op,
cxobj *xt)
{
@ -439,8 +439,8 @@ xmldb_put(clicon_handle h,
*/
int
xmldb_copy(clicon_handle h,
char *from,
char *to)
const char *from,
const char *to)
{
int retval = -1;
xmldb_handle xh;
@ -472,7 +472,7 @@ xmldb_copy(clicon_handle h,
*/
int
xmldb_lock(clicon_handle h,
char *db,
const char *db,
int pid)
{
int retval = -1;
@ -506,7 +506,7 @@ xmldb_lock(clicon_handle h,
*/
int
xmldb_unlock(clicon_handle h,
char *db)
const char *db)
{
int retval = -1;
xmldb_handle xh;
@ -569,7 +569,7 @@ xmldb_unlock_all(clicon_handle h,
*/
int
xmldb_islocked(clicon_handle h,
char *db)
const char *db)
{
int retval = -1;
xmldb_handle xh;
@ -601,7 +601,7 @@ xmldb_islocked(clicon_handle h,
*/
int
xmldb_exists(clicon_handle h,
char *db)
const char *db)
{
int retval = -1;
xmldb_handle xh;
@ -632,7 +632,7 @@ xmldb_exists(clicon_handle h,
*/
int
xmldb_delete(clicon_handle h,
char *db)
const char *db)
{
int retval = -1;
xmldb_handle xh;
@ -663,7 +663,7 @@ xmldb_delete(clicon_handle h,
*/
int
xmldb_create(clicon_handle h,
char *db)
const char *db)
{
int retval = -1;
xmldb_handle xh;

View file

@ -22,7 +22,7 @@ if [ $? -ne 0 ]; then
fi
new "start backend"
# start new backend
sudo clixon_backend -If $clixon_cf
sudo clixon_backend -s init -f $clixon_cf
if [ $? -ne 0 ]; then
err
fi

View file

@ -55,7 +55,7 @@ fi
new "start backend"
# start new backend
sudo clixon_backend -If $clixon_cf -y /tmp/leafref.yang
sudo clixon_backend -s init -f $clixon_cf -y /tmp/leafref.yang
if [ $? -ne 0 ]; then
err
fi

View file

@ -16,7 +16,7 @@ if [ $? -ne 0 ]; then
fi
new "start backend"
# start new backend
sudo clixon_backend -If $clixon_cf
sudo clixon_backend -s init -f $clixon_cf
if [ $? -ne 0 ]; then
err
fi

View file

@ -50,7 +50,7 @@ fi
new "start backend"
# start new backend
sudo clixon_backend -If $clixon_cf -y $fyang
sudo clixon_backend -s init -f $clixon_cf -y $fyang
if [ $? -ne 0 ]; then
err
fi

View file

@ -12,7 +12,7 @@ if [ $? -ne 0 ]; then
err
fi
new "start backend"
sudo clixon_backend -If $clixon_cf
sudo clixon_backend -s init -f $clixon_cf
if [ $? -ne 0 ]; then
err
fi

90
test/test_startup.sh Executable file
View file

@ -0,0 +1,90 @@
#!/bin/bash
# Startup test: Start clicon daemon in the (four) different startup modes
# and the dbs and files are setup as follows:
# - The example reset_state callback adds "lo" interface
# - An extra xml configuration file starts with an "extra" interface
# - running db starts with a "run" interface
# - startup db starts with a "start" interface
# include err() and new() functions
. ./lib.sh
# For memcheck
# clixon_netconf="valgrind --leak-check=full --show-leak-kinds=all clixon_netconf"
clixon_netconf=clixon_netconf
clixon_cli=clixon_cli
run(){
mode=$1
expect=$2
cat <<EOF > /tmp/db
<config>
<interfaces>
<interface>
<name>run</name>
<type>eth</type>
</interface>
</interfaces>
</config>
EOF
sudo mv /tmp/db /usr/local/var/routing/running_db
cat <<EOF > /tmp/db
<config>
<interfaces>
<interface>
<name>startup</name>
<type>eth</type>
</interface>
</interfaces>
</config>
EOF
sudo mv /tmp/db /usr/local/var/routing/startup_db
cat <<EOF > /tmp/config
<config>
<interfaces>
<interface>
<name>extra</name>
<type>eth</type>
</interface>
</interfaces>
</config>
EOF
# kill old backend (if any)
new "kill old backend"
sudo clixon_backend -zf $clixon_cf $yang
if [ $? -ne 0 ]; then
err
fi
new "start backend"
# start new backend
sudo clixon_backend -f $clixon_cf $yang -s $mode -c /tmp/config
if [ $? -ne 0 ]; then
err
fi
new "Check $mode"
expecteof "$clixon_netconf -qf $clixon_cf $yang" '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' "^<rpc-reply>$expect</rpc-reply>]]>]]>$"
new "Kill backend"
# Check if still alive
pid=`pgrep clixon_backend`
if [ -z "$pid" ]; then
err "backend already dead"
fi
# kill backend
sudo clixon_backend -zf $clixon_cf
if [ $? -ne 0 ]; then
err "kill backend"
fi
}
run init '<data/>'
run none '<data><interfaces><interface><name>run</name><type>eth</type><enabled>true</enabled></interface></interfaces></data>'
run running '<data><interfaces><interface><name>run</name><type>eth</type><enabled>true</enabled></interface><interface><name>lo</name><type>local</type><enabled>true</enabled></interface><interface><name>extra</name><type>eth</type><enabled>true</enabled></interface></interfaces></data>'
run startup '<data><interfaces><interface><name>startup</name><type>eth</type><enabled>true</enabled></interface><interface><name>lo</name><type>local</type><enabled>true</enabled></interface><interface><name>extra</name><type>eth</type><enabled>true</enabled></interface></interfaces></data>'

View file

@ -69,7 +69,7 @@ if [ $? -ne 0 ]; then
fi
new "start backend"
# start new backend
sudo clixon_backend -If $clixon_cf -y /tmp/type.yang
sudo clixon_backend -s init -f $clixon_cf -y /tmp/type.yang
if [ $? -ne 0 ]; then
err
fi

View file

@ -70,7 +70,7 @@ fi
new "start backend"
# start new backend
sudo clixon_backend -If $clixon_cf -y /tmp/test.yang
sudo clixon_backend -s init -f $clixon_cf -y /tmp/test.yang
if [ $? -ne 0 ]; then
err
fi

View file

@ -38,9 +38,32 @@
***** END LICENSE BLOCK *****";
revision 2017-07-02 {
revision 2017-11-12 {
description
"Initial revision";
"Added startup config";
}
typedef startup_mode{
description "Which method to boot/start clicon backend.
The methods differ in how they reach a running state
Which source database to commit from, if any.";
type enumeration{
enum none{
description "Do not touch running state
Typical after crash when running state and db are synched";
}
enum init{
description "Initialize running state.
Start with a completely clean running state";
}
enum running{
description "Commit running db configuration into running state
Usecase: after reboot if a persistent running db exists";
}
enum startup{
description "Commit startup configuration into running state
Usecase: after reboot when no persistent running db exists";
}
}
}
container config {
leaf CLICON_CONFIGFILE{
@ -185,12 +208,17 @@
type int32;
default 0;
description "Enabled uses \"startup\" configuration on boot. It is called
startup_db and exists in XMLDB_DIR";
startup_db and exists in XMLDB_DIR. NOTE: Obsolete with CLICON_STARTUP_MODE";
}
leaf CLICON_XMLDB_PLUGIN {
type string;
mandatory true;
description "XMLDB datastore plugin filename (see datastore/ and clixon_xml_db.[ch])";
}
leaf CLICON_STARTUP_MODE {
type startup_mode;
description "Which method to boot/start clicon backend";
}
}
}