optimization

This commit is contained in:
Olof hagsand 2017-12-03 20:22:05 +01:00
parent 14faf93eec
commit 4cb00bedfa
13 changed files with 687 additions and 320 deletions

View file

@ -2,7 +2,9 @@
## 3.4.0 (Upcoming) ## 3.4.0 (Upcoming)
* Datastore cache introduced: cache XML tree in memory for faster get access * Better semantic versioning, eg MAJOR/MINOR/PATCH, where increment in PATCH does not change API.
* Datastore cache introduced: cache XML tree in memory for faster get access. Use CLICON_XMLDB_CACHE configuration option. Default is 1.
* Moved XML_CHILD_HASH to variable instead of constant. * Moved XML_CHILD_HASH to variable instead of constant.

View file

@ -617,6 +617,7 @@ main(int argc, char **argv)
char *sock; char *sock;
int sockfamily; int sockfamily;
char *xmldb_plugin; char *xmldb_plugin;
int xml_cache;
/* In the startup, logs to stderr & syslog and debug flag set later */ /* In the startup, logs to stderr & syslog and debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, CLICON_LOG_STDERR|CLICON_LOG_SYSLOG); clicon_log_init(__PROGRAM__, LOG_INFO, CLICON_LOG_STDERR|CLICON_LOG_SYSLOG);
@ -807,7 +808,8 @@ main(int argc, char **argv)
"or create the group and add the user to it. On linux for example:" "or create the group and add the user to it. On linux for example:"
" sudo groupadd %s\n" " sudo groupadd %s\n"
" sudo usermod -a -G %s user\n", " sudo usermod -a -G %s user\n",
config_group, clicon_configfile(h), config_group, config_group); config_group, clicon_configfile(h),
config_group, config_group);
return -1; return -1;
} }
@ -829,6 +831,9 @@ main(int argc, char **argv)
goto done; goto done;
if (xmldb_setopt(h, "yangspec", clicon_dbspec_yang(h)) < 0) if (xmldb_setopt(h, "yangspec", clicon_dbspec_yang(h)) < 0)
goto done; goto done;
if ((xml_cache = clicon_option_bool(h, "CLICON_XMLDB_CACHE")) >= 0)
if (xmldb_setopt(h, "xml_cache", (void*)xml_cache) < 0)
goto done;
/* If startup mode is not defined, eg via OPTION or -s, assume old method */ /* If startup mode is not defined, eg via OPTION or -s, assume old method */
startup_mode = clicon_startup_mode(h); startup_mode = clicon_startup_mode(h);
if (startup_mode == -1){ /* Old style, fragmented mode, phase out */ if (startup_mode == -1){ /* Old style, fragmented mode, phase out */

View file

@ -837,7 +837,7 @@ save_config_file(clicon_handle h,
clicon_rpc_generate_error("Get configuration", xerr); clicon_rpc_generate_error("Get configuration", xerr);
goto done; goto done;
} }
if ((f = fopen(filename, "wb")) == NULL){ if ((f = fopen(filename, "w")) == NULL){
clicon_err(OE_CFG, errno, "Creating file %s", filename); clicon_err(OE_CFG, errno, "Creating file %s", filename);
goto done; goto done;
} }

View file

@ -356,7 +356,7 @@ main(int argc, char **argv)
clicon_option_str_set(h, "CLICON_CLI_MODE", optarg); clicon_option_str_set(h, "CLICON_CLI_MODE", optarg);
break; break;
case 'q' : /* Quiet mode */ case 'q' : /* Quiet mode */
clicon_option_str_set(h, "CLICON_QUIET", "on"); clicon_quiet_mode_set(h, 1);
break; break;
case 'p' : /* Print spec */ case 'p' : /* Print spec */
printspec++; printspec++;

View file

@ -95,7 +95,7 @@ struct db_element{
* Assumes single backend * Assumes single backend
* Experimental * Experimental
*/ */
static int datastore_cache = 1; static int xmltree_cache = 1;
/*! Check struct magic number for sanity checks /*! Check struct magic number for sanity checks
* return 0 if OK, -1 if fail. * return 0 if OK, -1 if fail.
@ -193,7 +193,7 @@ text_disconnect(xmldb_handle xh)
if (th->th_dbdir) if (th->th_dbdir)
free(th->th_dbdir); free(th->th_dbdir);
if (th->th_dbs){ if (th->th_dbs){
if (datastore_cache){ if (xmltree_cache){
if ((keys = hash_keys(th->th_dbs, &klen)) == NULL) if ((keys = hash_keys(th->th_dbs, &klen)) == NULL)
return 0; return 0;
for(i = 0; i < klen; i++) for(i = 0; i < klen; i++)
@ -264,6 +264,9 @@ text_setopt(xmldb_handle xh,
goto done; goto done;
} }
} }
else if (strcmp(optname, "xml_cache") == 0){
xmltree_cache = (intptr_t)value;
}
else{ else{
clicon_err(OE_PLUGIN, 0, "Option %s not implemented by plugin", optname); clicon_err(OE_PLUGIN, 0, "Option %s not implemented by plugin", optname);
goto done; goto done;
@ -389,21 +392,6 @@ xml_copy_marked(cxobj *x0,
* xpath. * xpath.
* This is a clixon datastore plugin of the the xmldb api * This is a clixon datastore plugin of the the xmldb api
* @see xmldb_get * @see xmldb_get
#ifdef DATASTORE_CACHE
text_get 90%
clixon_xml_parse_file 74% (100x)
xml_parse 70% (100x)
clicon_xml_parseparse 70% (300x)
xml_value_append 13% (800K)
xml_new
xml_purge
clicon_xml_parselex 12% (1M)
clixon_tree_prune_flagged_sub 12% (100x)
xml_purge 12% (58000)
yang_key_match 7% (77000)
yang_arg2cvec
#endif
*
*/ */
int int
text_get(xmldb_handle xh, text_get(xmldb_handle xh,
@ -427,7 +415,7 @@ text_get(xmldb_handle xh,
clicon_err(OE_YANG, ENOENT, "No yang spec"); clicon_err(OE_YANG, ENOENT, "No yang spec");
goto done; goto done;
} }
if (datastore_cache){ if (xmltree_cache){
if ((de = hash_value(th->th_dbs, db, NULL)) != NULL) if ((de = hash_value(th->th_dbs, db, NULL)) != NULL)
xt = de->de_xml; xt = de->de_xml;
} }
@ -471,11 +459,11 @@ text_get(xmldb_handle xh,
if (xvec != NULL) if (xvec != NULL)
for (i=0; i<xlen; i++){ for (i=0; i<xlen; i++){
xml_flag_set(xvec[i], XML_FLAG_MARK); xml_flag_set(xvec[i], XML_FLAG_MARK);
if (datastore_cache) if (xmltree_cache)
xml_apply_ancestor(xvec[i], (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_CHANGE); xml_apply_ancestor(xvec[i], (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_CHANGE);
} }
if (datastore_cache){ if (xmltree_cache){
/* Copy the matching parts of the (relevant) XML tree. /* Copy the matching parts of the (relevant) XML tree.
* If cache was NULL, also write to datastore cache * If cache was NULL, also write to datastore cache
*/ */
@ -852,7 +840,7 @@ text_put(xmldb_handle xh,
xml_name(x1)); xml_name(x1));
goto done; goto done;
} }
if (datastore_cache){ if (xmltree_cache){
if ((de = hash_value(th->th_dbs, db, NULL)) != NULL) if ((de = hash_value(th->th_dbs, db, NULL)) != NULL)
x0 = de->de_xml; x0 = de->de_xml;
} }
@ -921,7 +909,7 @@ text_put(xmldb_handle xh,
goto done; goto done;
/* Write back to datastore cache if first time */ /* Write back to datastore cache if first time */
if (datastore_cache){ if (xmltree_cache){
struct db_element de0 = {0,}; struct db_element de0 = {0,};
if (de != NULL) if (de != NULL)
de0 = *de; de0 = *de;
@ -930,7 +918,28 @@ text_put(xmldb_handle xh,
hash_add(th->th_dbs, db, &de0, sizeof(de0)); hash_add(th->th_dbs, db, &de0, sizeof(de0));
} }
} }
if (dbfile == NULL){
if (text_db2file(th, db, &dbfile) < 0)
goto done;
if (dbfile==NULL){
clicon_err(OE_XML, 0, "dbfile NULL");
goto done;
}
}
#if 1
if (fd != -1)
close(fd);
{
FILE *f;
if ((f = fopen(dbfile, "w")) == NULL){
clicon_err(OE_CFG, errno, "Creating file %s", dbfile);
goto done;
}
if (xml_print(f, x0) < 0)
goto done;
fclose(f);
}
#else
// output: // output:
/* Print out top-level xml tree after modification to file */ /* Print out top-level xml tree after modification to file */
if ((cb = cbuf_new()) == NULL){ if ((cb = cbuf_new()) == NULL){
@ -942,14 +951,6 @@ text_put(xmldb_handle xh,
/* Reopen file in write mode */ /* Reopen file in write mode */
if (fd != -1) if (fd != -1)
close(fd); close(fd);
if (dbfile == NULL){
if (text_db2file(th, db, &dbfile) < 0)
goto done;
if (dbfile==NULL){
clicon_err(OE_XML, 0, "dbfile NULL");
goto done;
}
}
if ((fd = open(dbfile, O_WRONLY | O_TRUNC, S_IRWXU)) < 0) { if ((fd = open(dbfile, O_WRONLY | O_TRUNC, S_IRWXU)) < 0) {
clicon_err(OE_UNIX, errno, "open(%s)", dbfile); clicon_err(OE_UNIX, errno, "open(%s)", dbfile);
goto done; goto done;
@ -958,6 +959,7 @@ text_put(xmldb_handle xh,
clicon_err(OE_UNIX, errno, "write(%s)", dbfile); clicon_err(OE_UNIX, errno, "write(%s)", dbfile);
goto done; goto done;
} }
#endif
retval = 0; retval = 0;
done: done:
if (dbfile) if (dbfile)
@ -966,7 +968,7 @@ text_put(xmldb_handle xh,
close(fd); close(fd);
if (cb) if (cb)
cbuf_free(cb); cbuf_free(cb);
if (!datastore_cache && x0) if (!xmltree_cache && x0)
xml_free(x0); xml_free(x0);
return retval; return retval;
} }
@ -981,23 +983,45 @@ text_put(xmldb_handle xh,
int int
text_copy(xmldb_handle xh, text_copy(xmldb_handle xh,
const char *from, const char *from,
const char *to) const char *to)
{ {
int retval = -1; int retval = -1;
struct text_handle *th = handle(xh); struct text_handle *th = handle(xh);
char *fromfile = NULL; char *fromfile = NULL;
char *tofile = NULL; char *tofile = NULL;
struct db_element *de = NULL; struct db_element *de = NULL;
struct db_element *de2 = NULL;
/* XXX lock */ /* XXX lock */
if (datastore_cache){ if (xmltree_cache){
/* Just invalidate xml if exists in TO */ /* 1. Free xml tree in "to"
*/
if ((de = hash_value(th->th_dbs, to, NULL)) != NULL){ if ((de = hash_value(th->th_dbs, to, NULL)) != NULL){
if (de->de_xml != NULL){ if (de->de_xml != NULL){
xml_free(de->de_xml); xml_free(de->de_xml);
de->de_xml = NULL; de->de_xml = NULL;
} }
} }
/* 2. Copy xml tree from "from" to "to"
* 2a) create "to" if it does not exist
*/
if ((de2 = hash_value(th->th_dbs, from, NULL)) != NULL){
if (de2->de_xml != NULL){
struct db_element de0 = {0,};
cxobj *x, *xcopy;
x = de2->de_xml;
if (de != NULL)
de0 = *de;
if ((xcopy = xml_new(xml_name(x), NULL, xml_spec(x))) == NULL)
goto done;
if (xml_copy(x, xcopy) < 0)
goto done;
de0.de_xml = xcopy;
hash_add(th->th_dbs, to, &de0, sizeof(de0));
}
}
} }
if (text_db2file(th, from, &fromfile) < 0) if (text_db2file(th, from, &fromfile) < 0)
goto done; goto done;
@ -1153,7 +1177,7 @@ text_delete(xmldb_handle xh,
struct db_element *de = NULL; struct db_element *de = NULL;
cxobj *xt = NULL; cxobj *xt = NULL;
if (datastore_cache){ if (xmltree_cache){
if ((de = hash_value(th->th_dbs, db, NULL)) != NULL){ if ((de = hash_value(th->th_dbs, db, NULL)) != NULL){
if ((xt = de->de_xml) != NULL){ if ((xt = de->de_xml) != NULL){
xml_free(xt); xml_free(xt);
@ -1192,7 +1216,7 @@ text_create(xmldb_handle xh,
struct db_element *de = NULL; struct db_element *de = NULL;
cxobj *xt = NULL; cxobj *xt = NULL;
if (datastore_cache){ /* XXX This should nt really happen? */ if (xmltree_cache){ /* XXX This should nt really happen? */
if ((de = hash_value(th->th_dbs, db, NULL)) != NULL){ if ((de = hash_value(th->th_dbs, db, NULL)) != NULL){
if ((xt = de->de_xml) != NULL){ if ((xt = de->de_xml) != NULL){
assert(xt==NULL); /* XXX */ assert(xt==NULL); /* XXX */

View file

@ -74,53 +74,92 @@ enum startup_mode_t{
/* /*
* Prototypes * Prototypes
*/ */
/* Print registry on file. For debugging. */
void clicon_option_dump(clicon_handle h, int dblevel);
/* Initialize options: set defaults, read config-file, etc */ /* Initialize options: set defaults, read config-file, etc */
int clicon_options_main(clicon_handle h); int clicon_options_main(clicon_handle h);
/*! Check if a clicon option has a value */
void clicon_option_dump(clicon_handle h, int dblevel);
int clicon_option_exists(clicon_handle h, const char *name); int clicon_option_exists(clicon_handle h, const char *name);
/* Get a single option via handle */ /* String options, default NULL */
char *clicon_option_str(clicon_handle h, const char *name); char *clicon_option_str(clicon_handle h, const char *name);
int clicon_option_int(clicon_handle h, const char *name);
/* Set a single option via handle */
int clicon_option_str_set(clicon_handle h, const char *name, char *val); int clicon_option_str_set(clicon_handle h, const char *name, char *val);
/* Option values gixen as int, default -1 */
int clicon_option_int(clicon_handle h, const char *name);
int clicon_option_int_set(clicon_handle h, const char *name, int val); int clicon_option_int_set(clicon_handle h, const char *name, int val);
/* Option values gixen as bool, default false */
int clicon_option_bool(clicon_handle h, const char *name);
int clicon_option_bool_set(clicon_handle h, const char *name, int val);
/* Delete a single option via handle */ /* Delete a single option via handle */
int clicon_option_del(clicon_handle h, const char *name); int clicon_option_del(clicon_handle h, const char *name);
char *clicon_configfile(clicon_handle h); /*-- Standard option access functions for YANG options --*/
char *clicon_yang_dir(clicon_handle h); static inline char *clicon_configfile(clicon_handle h){
char *clicon_yang_module_main(clicon_handle h); return clicon_option_str(h, "CLICON_CONFIGFILE");
char *clicon_yang_module_revision(clicon_handle h); }
char *clicon_backend_dir(clicon_handle h); static inline char *clicon_yang_dir(clicon_handle h){
char *clicon_cli_dir(clicon_handle h); return clicon_option_str(h, "CLICON_YANG_DIR");
char *clicon_clispec_dir(clicon_handle h); }
char *clicon_netconf_dir(clicon_handle h); static inline char *clicon_yang_module_main(clicon_handle h){
char *clicon_restconf_dir(clicon_handle h); return clicon_option_str(h, "CLICON_YANG_MODULE_MAIN");
char *clicon_xmldb_plugin(clicon_handle h); }
int clicon_startup_mode(clicon_handle h); static inline char *clicon_yang_module_revision(clicon_handle h){
int clicon_sock_family(clicon_handle h); return clicon_option_str(h, "CLICON_YANG_MODULE_REVISION");
char *clicon_sock(clicon_handle h); }
int clicon_sock_port(clicon_handle h); static inline char *clicon_backend_dir(clicon_handle h){
char *clicon_backend_pidfile(clicon_handle h); return clicon_option_str(h, "CLICON_BACKEND_DIR");
char *clicon_sock_group(clicon_handle h); }
static inline char *clicon_netconf_dir(clicon_handle h){
return clicon_option_str(h, "CLICON_NETCONF_DIR");
}
static inline char *clicon_restconf_dir(clicon_handle h){
return clicon_option_str(h, "CLICON_RESTCONF_DIR");
}
static inline char *clicon_cli_dir(clicon_handle h){
return clicon_option_str(h, "CLICON_CLI_DIR");
}
static inline char *clicon_clispec_dir(clicon_handle h){
return clicon_option_str(h, "CLICON_CLISPEC_DIR");
}
static inline char *clicon_cli_mode(clicon_handle h){
return clicon_option_str(h, "CLICON_CLI_MODE");
}
static inline char *clicon_sock(clicon_handle h){
return clicon_option_str(h, "CLICON_SOCK");
}
static inline char *clicon_sock_group(clicon_handle h){
return clicon_option_str(h, "CLICON_SOCK_GROUP");
}
static inline char *clicon_backend_pidfile(clicon_handle h){
return clicon_option_str(h, "CLICON_BACKEND_PIDFILE");
}
static inline char *clicon_master_plugin(clicon_handle h){
return clicon_option_str(h, "CLICON_MASTER_PLUGIN");
}
static inline char *clicon_xmldb_dir(clicon_handle h){
return clicon_option_str(h, "CLICON_XMLDB_DIR");
}
static inline char *clicon_xmldb_plugin(clicon_handle h){
return clicon_option_str(h, "CLICON_XMLDB_PLUGIN");
}
char *clicon_master_plugin(clicon_handle h); /*-- Specific option access functions for YANG options w type conversion--*/
char *clicon_cli_mode(clicon_handle h);
int clicon_cli_genmodel(clicon_handle h); int clicon_cli_genmodel(clicon_handle h);
int clicon_cli_varonly(clicon_handle h);
int clicon_cli_varonly_set(clicon_handle h, int val);
int clicon_cli_genmodel_completion(clicon_handle h); int clicon_cli_genmodel_completion(clicon_handle h);
char *clicon_xmldb_dir(clicon_handle h);
char *clicon_quiet_mode(clicon_handle h);
enum genmodel_type clicon_cli_genmodel_type(clicon_handle h); enum genmodel_type clicon_cli_genmodel_type(clicon_handle h);
int clicon_cli_varonly(clicon_handle h);
int clicon_sock_family(clicon_handle h);
int clicon_sock_port(clicon_handle h);
int clicon_autocommit(clicon_handle h);
int clicon_startup_mode(clicon_handle h);
int clicon_autocommit(clicon_handle h); /*-- Specific option access functions for non-yang options --*/
int clicon_autocommit_set(clicon_handle h, int val); int clicon_quiet_mode(clicon_handle h);
int clicon_quiet_mode_set(clicon_handle h, int val);
yang_spec * clicon_dbspec_yang(clicon_handle h); yang_spec * clicon_dbspec_yang(clicon_handle h);
int clicon_dbspec_yang_set(clicon_handle h, struct yang_spec *ys); int clicon_dbspec_yang_set(clicon_handle h, struct yang_spec *ys);
@ -128,16 +167,13 @@ int clicon_dbspec_yang_set(clicon_handle h, struct yang_spec *ys);
char *clicon_dbspec_name(clicon_handle h); char *clicon_dbspec_name(clicon_handle h);
int clicon_dbspec_name_set(clicon_handle h, char *name); int clicon_dbspec_name_set(clicon_handle h, char *name);
plghndl_t clicon_xmldb_plugin_get(clicon_handle h);
int clicon_xmldb_plugin_set(clicon_handle h, plghndl_t handle); int clicon_xmldb_plugin_set(clicon_handle h, plghndl_t handle);
plghndl_t clicon_xmldb_plugin_get(clicon_handle h); void *clicon_xmldb_api_get(clicon_handle h);
int clicon_xmldb_api_set(clicon_handle h, void *xa_api); int clicon_xmldb_api_set(clicon_handle h, void *xa_api);
void *clicon_xmldb_api_get(clicon_handle h); void *clicon_xmldb_handle_get(clicon_handle h);
int clicon_xmldb_handle_set(clicon_handle h, void *xh); int clicon_xmldb_handle_set(clicon_handle h, void *xh);
void *clicon_xmldb_handle_get(clicon_handle h);
#endif /* _CLIXON_OPTIONS_H_ */ #endif /* _CLIXON_OPTIONS_H_ */

View file

@ -495,6 +495,49 @@ clicon_option_int_set(clicon_handle h,
return clicon_option_str_set(h, name, s); return clicon_option_str_set(h, name, s);
} }
/*! Get options as bool but stored as string
*
* @param h clicon handle
* @param name name of option
* @retval 0 false, or does not exist, or does not have a boolean value
* @retval 1 true
* @code
* if (clicon_option_exists(h, "X")
* return clicon_option_bool(h, "X");
* else
* return 0; # default false?
* @endcode
* Note that 0 can be both error and false.
* This means that it should be used together with clicon_option_exists() and
* supply a default value as shown in the example.
*/
int
clicon_option_bool(clicon_handle h,
const char *name)
{
char *s;
if ((s = clicon_option_str(h, name)) == NULL)
return 0;
if (strcmp(s,"true")==0)
return 1;
return 0; /* Hopefully false, but anything else than "true" */
}
/*! Set option given as bool
*/
int
clicon_option_bool_set(clicon_handle h,
const char *name,
int val)
{
char s[64];
if (snprintf(s, sizeof(s)-1, "%u", val) < 0)
return -1;
return clicon_option_str_set(h, name, s);
}
/*! Delete option /*! Delete option
*/ */
int int
@ -507,146 +550,18 @@ clicon_option_del(clicon_handle h,
} }
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
* Specific option access functions. * Specific option access functions for YANG configuration variables.
* These should be commonly accessible for all users of clicon lib * Sometimes overridden by command-line options,
* such as -f for CLICON_CONFIGFILE
* @see yang/clixon-config@<date>.yang
* You can always use the basic access functions, such as
* clicon_option_str[_set]
* But sometimes there are type conversions, etc which makes it more
* convenient to make wrapper functions. Or not?
*-----------------------------------------------------------------*/ *-----------------------------------------------------------------*/
char *
clicon_configfile(clicon_handle h)
{
return clicon_option_str(h, "CLICON_CONFIGFILE");
}
/*! YANG database specification directory */
char *
clicon_yang_dir(clicon_handle h)
{
return clicon_option_str(h, "CLICON_YANG_DIR");
}
/*! YANG main module or absolute file name */
char *
clicon_yang_module_main(clicon_handle h)
{
return clicon_option_str(h, "CLICON_YANG_MODULE_MAIN");
}
/*! YANG revision */
char *
clicon_yang_module_revision(clicon_handle h)
{
return clicon_option_str(h, "CLICON_YANG_MODULE_REVISION");
}
/*! Directory of backend plugins. If null, no plugins are loaded */
char *
clicon_backend_dir(clicon_handle h)
{
return clicon_option_str(h, "CLICON_BACKEND_DIR");
}
/* contains .so files CLICON_CLI_DIR */
char *
clicon_cli_dir(clicon_handle h)
{
return clicon_option_str(h, "CLICON_CLI_DIR");
}
/* contains .cli files - CLICON_CLISPEC_DIR */
char *
clicon_clispec_dir(clicon_handle h)
{
return clicon_option_str(h, "CLICON_CLISPEC_DIR");
}
char *
clicon_netconf_dir(clicon_handle h)
{
return clicon_option_str(h, "CLICON_NETCONF_DIR");
}
char *
clicon_restconf_dir(clicon_handle h)
{
return clicon_option_str(h, "CLICON_RESTCONF_DIR");
}
char *
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)
{
char *s;
if ((s = clicon_option_str(h, "CLICON_SOCK_FAMILY")) == NULL)
return AF_UNIX;
else if (strcmp(s, "IPv4")==0)
return AF_INET;
else if (strcmp(s, "IPv6")==0)
return AF_INET6;
else
return AF_UNIX; /* default */
}
/*! Get information about socket: unix domain filepath, or addr:path */
char *
clicon_sock(clicon_handle h)
{
return clicon_option_str(h, "CLICON_SOCK");
}
/*! Get port for backend socket in case of AF_INET or AF_INET6 */
int
clicon_sock_port(clicon_handle h)
{
char *s;
if ((s = clicon_option_str(h, "CLICON_SOCK_PORT")) == NULL)
return -1;
return atoi(s);
}
char *
clicon_backend_pidfile(clicon_handle h)
{
return clicon_option_str(h, "CLICON_BACKEND_PIDFILE");
}
char *
clicon_sock_group(clicon_handle h)
{
return clicon_option_str(h, "CLICON_SOCK_GROUP");
}
char *
clicon_master_plugin(clicon_handle h)
{
return clicon_option_str(h, "CLICON_MASTER_PLUGIN");
}
/*! Return initial clicon cli mode */
char *
clicon_cli_mode(clicon_handle h)
{
return clicon_option_str(h, "CLICON_CLI_MODE");
}
/*! Whether to generate CLIgen syntax from datamodel or not (0 or 1) /*! Whether to generate CLIgen syntax from datamodel or not (0 or 1)
* Must be used with a previous clicon_option_exists(). * Must be used with a previous clicon_option_exists().
* @see clixon-config@<date>.yang CLICON_CLI_GENMODEL
*/ */
int int
clicon_cli_genmodel(clicon_handle h) clicon_cli_genmodel(clicon_handle h)
@ -659,7 +574,23 @@ clicon_cli_genmodel(clicon_handle h)
return 0; return 0;
} }
/*! How to generate and show CLI syntax: VARS|ALL */ /*! Generate code for CLI completion of existing db symbols
* @see clixon-config@<date>.yang CLICON_CLI_GENMODEL_COMPLETION
*/
int
clicon_cli_genmodel_completion(clicon_handle h)
{
char const *opt = "CLICON_CLI_GENMODEL_COMPLETION";
if (clicon_option_exists(h, opt))
return clicon_option_int(h, opt);
else
return 0;
}
/*! How to generate and show CLI syntax: VARS|ALL
* @see clixon-config@<date>.yang CLICON_CLI_GENMODEL_TYPE
*/
enum genmodel_type enum genmodel_type
clicon_cli_genmodel_type(clicon_handle h) clicon_cli_genmodel_type(clicon_handle h)
{ {
@ -683,32 +614,8 @@ clicon_cli_genmodel_type(clicon_handle h)
return gt; return gt;
} }
/*! Get Dont include keys in cvec in cli vars callbacks
/* eg -q option, dont print notifications on stdout */ * @see clixon-config@<date>.yang CLICON_CLI_VARONLY
char *
clicon_quiet_mode(clicon_handle h)
{
return clicon_option_str(h, "CLICON_QUIET");
}
int
clicon_autocommit(clicon_handle h)
{
char const *opt = "CLICON_AUTOCOMMIT";
if (clicon_option_exists(h, opt))
return clicon_option_int(h, opt);
else
return 0;
}
int
clicon_autocommit_set(clicon_handle h, int val)
{
return clicon_option_int_set(h, "CLICON_AUTOCOMMIT", val);
}
/*! Dont include keys in cvec in cli vars callbacks
*/ */
int int
clicon_cli_varonly(clicon_handle h) clicon_cli_varonly(clicon_handle h)
@ -721,16 +628,43 @@ clicon_cli_varonly(clicon_handle h)
return 0; return 0;
} }
/*! Get family of backend socket: AF_UNIX, AF_INET or AF_INET6
* @see clixon-config@<date>.yang CLICON_SOCK_FAMILY
*/
int int
clicon_cli_varonly_set(clicon_handle h, int val) clicon_sock_family(clicon_handle h)
{ {
return clicon_option_int_set(h, "CLICON_CLI_VARONLY", val); char *s;
if ((s = clicon_option_str(h, "CLICON_SOCK_FAMILY")) == NULL)
return AF_UNIX;
else if (strcmp(s, "IPv4")==0)
return AF_INET;
else if (strcmp(s, "IPv6")==0)
return AF_INET6;
else
return AF_UNIX; /* default */
} }
/*! Get port for backend socket in case of AF_INET or AF_INET6
* @see clixon-config@<date>.yang CLICON_SOCK_PORT
*/
int int
clicon_cli_genmodel_completion(clicon_handle h) clicon_sock_port(clicon_handle h)
{ {
char const *opt = "CLICON_CLI_GENMODEL_COMPLETION"; char *s;
if ((s = clicon_option_str(h, "CLICON_SOCK_PORT")) == NULL)
return -1;
return atoi(s);
}
/*! Set if all configuration changes are committed automatically
*/
int
clicon_autocommit(clicon_handle h)
{
char const *opt = "CLICON_AUTOCOMMIT";
if (clicon_option_exists(h, opt)) if (clicon_option_exists(h, opt))
return clicon_option_int(h, opt); return clicon_option_int(h, opt);
@ -738,11 +672,36 @@ clicon_cli_genmodel_completion(clicon_handle h)
return 0; return 0;
} }
/*! Where are "running" and "candidate" databases? */ /*! Which method to boot/start clicon backen
char * */
clicon_xmldb_dir(clicon_handle h) int
clicon_startup_mode(clicon_handle h)
{ {
return clicon_option_str(h, "CLICON_XMLDB_DIR"); char *mode;
if ((mode = clicon_option_str(h, "CLICON_STARTUP_MODE")) == NULL)
return -1;
return clicon_str2int(startup_mode_map, mode);
}
/*---------------------------------------------------------------------
* Specific option access functions for non-yang options
* Typically dynamic values and more complex datatypes,
* Such as handles to plugins, API:s and parsed structures
*--------------------------------------------------------------------*/
/* eg -q option, dont print notifications on stdout */
int
clicon_quiet_mode(clicon_handle h)
{
char *s;
if ((s = clicon_option_str(h, "CLICON_QUIET")) == NULL)
return 0; /* default */
return atoi(s);
}
int
clicon_quiet_mode_set(clicon_handle h, int val)
{
return clicon_option_int_set(h, "CLICON_QUIET", val);
} }
/*! Get YANG specification /*! Get YANG specification
@ -796,6 +755,19 @@ clicon_dbspec_name_set(clicon_handle h, char *name)
return clicon_option_str_set(h, "dbspec_name", name); return clicon_option_str_set(h, "dbspec_name", name);
} }
/*! Get xmldb datastore plugin handle, as used by dlopen/dlsym/dlclose */
plghndl_t
clicon_xmldb_plugin_get(clicon_handle h)
{
clicon_hash_t *cdat = clicon_data(h);
size_t len;
void *p;
if ((p = hash_value(cdat, "xmldb_plugin", &len)) != NULL)
return *(plghndl_t*)p;
return NULL;
}
/*! Set xmldb datastore plugin handle, as used by dlopen/dlsym/dlclose */ /*! Set xmldb datastore plugin handle, as used by dlopen/dlsym/dlclose */
int int
clicon_xmldb_plugin_set(clicon_handle h, clicon_xmldb_plugin_set(clicon_handle h,
@ -808,16 +780,20 @@ clicon_xmldb_plugin_set(clicon_handle h,
return 0; return 0;
} }
/*! Get xmldb datastore plugin handle, as used by dlopen/dlsym/dlclose */ /*! Get XMLDB API struct pointer
plghndl_t * @param[in] h Clicon handle
clicon_xmldb_plugin_get(clicon_handle h) * @retval xa XMLDB API struct
* @note xa is really of type struct xmldb_api*
*/
void *
clicon_xmldb_api_get(clicon_handle h)
{ {
clicon_hash_t *cdat = clicon_data(h); clicon_hash_t *cdat = clicon_data(h);
size_t len; size_t len;
void *p; void *xa;
if ((p = hash_value(cdat, "xmldb_plugin", &len)) != NULL) if ((xa = hash_value(cdat, "xmldb_api", &len)) != NULL)
return *(plghndl_t*)p; return *(void**)xa;
return NULL; return NULL;
} }
@ -840,20 +816,19 @@ clicon_xmldb_api_set(clicon_handle h,
return 0; return 0;
} }
/*! Get XMLDB API struct pointer /*! Get XMLDB storage handle
* @param[in] h Clicon handle * @param[in] h Clicon handle
* @retval xa XMLDB API struct * @retval xh XMLDB storage handle. If not connected return NULL
* @note xa is really of type struct xmldb_api*
*/ */
void * void *
clicon_xmldb_api_get(clicon_handle h) clicon_xmldb_handle_get(clicon_handle h)
{ {
clicon_hash_t *cdat = clicon_data(h); clicon_hash_t *cdat = clicon_data(h);
size_t len; size_t len;
void *xa; void *xh;
if ((xa = hash_value(cdat, "xmldb_api", &len)) != NULL) if ((xh = hash_value(cdat, "xmldb_handle", &len)) != NULL)
return *(void**)xa; return *(void**)xh;
return NULL; return NULL;
} }
@ -873,18 +848,4 @@ clicon_xmldb_handle_set(clicon_handle h,
return 0; return 0;
} }
/*! Get XMLDB storage handle
* @param[in] h Clicon handle
* @retval xh XMLDB storage handle. If not connected return NULL
*/
void *
clicon_xmldb_handle_get(clicon_handle h)
{
clicon_hash_t *cdat = clicon_data(h);
size_t len;
void *xh;
if ((xh = hash_value(cdat, "xmldb_handle", &len)) != NULL)
return *(void**)xh;
return NULL;
}

View file

@ -182,7 +182,7 @@ pidfile_write(char *pidfile)
int retval = -1; int retval = -1;
/* Here, there should be no old agent and no pidfile */ /* Here, there should be no old agent and no pidfile */
if ((f = fopen(pidfile, "wb")) == NULL){ if ((f = fopen(pidfile, "w")) == NULL){
if (errno == EACCES) if (errno == EACCES)
clicon_err(OE_DEMON, errno, "Creating pid-file %s (Try run as root?)", pidfile); clicon_err(OE_DEMON, errno, "Creating pid-file %s (Try run as root?)", pidfile);
else else

View file

@ -69,6 +69,7 @@
* Constants * Constants
*/ */
#define BUFLEN 1024 /* Size of xml read buffer */ #define BUFLEN 1024 /* Size of xml read buffer */
#define XML_INDENT 3 /* maybe we should set this programmatically? */
/* /*
* Types * Types
@ -104,7 +105,7 @@ static const map_str2int xsmap[] = {
}; };
/* Hash for XML trees list entries /* Hash for XML trees list entries
* Experimental * Experimental XXX DOES NOT WORK
*/ */
int xml_child_hash = 0; int xml_child_hash = 0;
@ -442,7 +443,7 @@ xml_child_each(cxobj *xparent,
xn = xparent->x_childvec[i]; xn = xparent->x_childvec[i];
if (xn == NULL) if (xn == NULL)
continue; continue;
if (type != CX_ERROR && xml_type(xn) != type) if (type != CX_ERROR && xn->x_type != type)
continue; continue;
break; /* this is next object after previous */ break; /* this is next object after previous */
} }
@ -931,27 +932,89 @@ xml_free(cxobj *x)
* @param[in] level how many spaces to insert before each line * @param[in] level how many spaces to insert before each line
* @param[in] prettyprint insert \n and spaces tomake the xml more readable. * @param[in] prettyprint insert \n and spaces tomake the xml more readable.
* @see clicon_xml2cbuf * @see clicon_xml2cbuf
* One can use clicon_xml2cbuf to get common code, but using fprintf is
* much faster than using cbuf and then printing that,...
*/ */
int int
clicon_xml2file(FILE *f, clicon_xml2file(FILE *f,
cxobj *xn, cxobj *x,
int level, int level,
int prettyprint) int prettyprint)
{ {
int retval = -1; int retval = -1;
cbuf *cb = NULL; char *name;
char *namespace;
cxobj *xc;
int hasbody;
int haselement;
if ((cb = cbuf_new()) == NULL){ name = xml_name(x);
clicon_err(OE_XML, errno, "cbuf_new"); namespace = xml_namespace(x);
goto done; switch(xml_type(x)){
} case CX_BODY:
if (clicon_xml2cbuf(cb, xn, level, prettyprint) < 0) fprintf(f, "%s", xml_value(x));
goto done; break;
fprintf(f, "%s", cbuf_get(cb)); case CX_ATTR:
fprintf(f, " ");
if (namespace)
fprintf(f, "%s:", namespace);
fprintf(f, "%s=\"%s\"", name, xml_value(x));
break;
case CX_ELMNT:
fprintf(f, "%*s<", prettyprint?(level*XML_INDENT):0, "");
if (namespace)
fprintf(f, "%s:", namespace);
fprintf(f, "%s", name);
hasbody = 0;
haselement = 0;
xc = NULL;
/* print attributes only */
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
switch (xc->x_type){
case CX_ATTR:
if (clicon_xml2file(f, xc, level+1, prettyprint) <0)
goto done;
break;
case CX_BODY:
hasbody=1;
break;
case CX_ELMNT:
haselement=1;
break;
default:
break;
}
}
/* Check for special case <a/> instead of <a></a>:
* Ie, no CX_BODY or CX_ELMNT child.
*/
if (hasbody==0 && haselement==0)
fprintf(f, "/>");
else{
fprintf(f, ">");
if (prettyprint && hasbody == 0)
fprintf(f, "\n");
xc = NULL;
while ((xc = xml_child_each(x, xc, -1)) != NULL) {
if (xml_type(xc) != CX_ATTR)
if (clicon_xml2file(f, xc, level+1, prettyprint) <0)
goto done;
}
if (prettyprint && hasbody==0)
fprintf(f, "%*s", level*XML_INDENT, "");
fprintf(f, "</");
if (namespace)
fprintf(f, "%s:", namespace);
fprintf(f, "%s>", name);
}
if (prettyprint)
fprintf(f, "\n");
break;
default:
break;
}/* switch */
retval = 0; retval = 0;
done: done:
if (cb)
cbuf_free(cb);
return retval; return retval;
} }
@ -971,7 +1034,6 @@ xml_print(FILE *f,
return clicon_xml2file(f, xn, 0, 1); return clicon_xml2file(f, xn, 0, 1);
} }
#define XML_INDENT 3 /* maybe we should set this programmatically? */
/*! Print an XML tree structure to a cligen buffer /*! Print an XML tree structure to a cligen buffer
* *
@ -987,7 +1049,7 @@ xml_print(FILE *f,
* goto err; * goto err;
* cbuf_free(cb); * cbuf_free(cb);
* @endcode * @endcode
* See also clicon_xml2file * @see clicon_xml2file
*/ */
int int
clicon_xml2cbuf(cbuf *cb, clicon_xml2cbuf(cbuf *cb,
@ -995,48 +1057,67 @@ clicon_xml2cbuf(cbuf *cb,
int level, int level,
int prettyprint) int prettyprint)
{ {
int retval = -1;
cxobj *xc; cxobj *xc;
char *name; char *name;
int hasbody;
int haselement;
char *namespace;
name = xml_name(x); name = xml_name(x);
namespace = xml_namespace(x);
switch(xml_type(x)){ switch(xml_type(x)){
case CX_BODY: case CX_BODY:
cprintf(cb, "%s", xml_value(x)); cprintf(cb, "%s", xml_value(x));
break; break;
case CX_ATTR: case CX_ATTR:
cprintf(cb, " "); cprintf(cb, " ");
if (xml_namespace(x)) if (namespace)
cprintf(cb, "%s:", xml_namespace(x)); cprintf(cb, "%s:", namespace);
cprintf(cb, "%s=\"%s\"", name, xml_value(x)); cprintf(cb, "%s=\"%s\"", name, xml_value(x));
break; break;
case CX_ELMNT: case CX_ELMNT:
cprintf(cb, "%*s<", prettyprint?(level*XML_INDENT):0, ""); cprintf(cb, "%*s<", prettyprint?(level*XML_INDENT):0, "");
if (xml_namespace(x)) if (namespace)
cprintf(cb, "%s:", xml_namespace(x)); cprintf(cb, "%s:", namespace);
cprintf(cb, "%s", name); cprintf(cb, "%s", name);
hasbody = 0;
haselement = 0;
xc = NULL; xc = NULL;
/* print attributes only */ /* print attributes only */
while ((xc = xml_child_each(x, xc, CX_ATTR)) != NULL) while ((xc = xml_child_each(x, xc, -1)) != NULL)
clicon_xml2cbuf(cb, xc, level+1, prettyprint); switch (xc->x_type){
case CX_ATTR:
if (clicon_xml2cbuf(cb, xc, level+1, prettyprint) < 0)
goto done;
break;
case CX_BODY:
hasbody=1;
break;
case CX_ELMNT:
haselement=1;
break;
default:
break;
}
/* Check for special case <a/> instead of <a></a> */ /* Check for special case <a/> instead of <a></a> */
if (xml_body(x)==NULL && xml_child_nr_type(x, CX_ELMNT)==0) if (hasbody==0 && haselement==0)
cprintf(cb, "/>"); cprintf(cb, "/>");
else{ else{
cprintf(cb, ">"); cprintf(cb, ">");
if (prettyprint && xml_body(x)==NULL) if (prettyprint && hasbody == 0)
cprintf(cb, "\n"); cprintf(cb, "\n");
xc = NULL; xc = NULL;
while ((xc = xml_child_each(x, xc, -1)) != NULL) { while ((xc = xml_child_each(x, xc, -1)) != NULL)
if (xml_type(xc) == CX_ATTR) if (xml_type(xc) != CX_ATTR)
continue; if (clicon_xml2cbuf(cb, xc, level+1, prettyprint) < 0)
else goto done;
clicon_xml2cbuf(cb, xc, level+1, prettyprint); if (prettyprint && hasbody == 0)
}
if (prettyprint && xml_body(x)==NULL)
cprintf(cb, "%*s", level*XML_INDENT, ""); cprintf(cb, "%*s", level*XML_INDENT, "");
cprintf(cb, "</"); cprintf(cb, "</");
if (xml_namespace(x)) if (namespace)
cprintf(cb, "%s:", xml_namespace(x)); cprintf(cb, "%s:", namespace);
cprintf(cb, "%s>", name); cprintf(cb, "%s>", name);
} }
if (prettyprint) if (prettyprint)
@ -1045,7 +1126,9 @@ clicon_xml2cbuf(cbuf *cb,
default: default:
break; break;
}/* switch */ }/* switch */
return 0; retval = 0;
done:
return retval;
} }
/*! Basic xml parsing function. /*! Basic xml parsing function.

View file

@ -86,18 +86,21 @@ echo "$clixon_netconf -qf $clixon_cf -y $fyang"
new "netconf edit large config" new "netconf edit large config"
expecteof_file "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "$fconfig" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof_file "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "$fconfig" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
echo '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' | $clixon_netconf -qf $clixon_cf -y $fyang #echo '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' | $clixon_netconf -qf $clixon_cf -y $fyang
new "netconf edit large config again" new "netconf edit large config again"
expecteof_file "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "$fconfig" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof_file "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "$fconfig" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
echo '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' | $clixon_netconf -qf $clixon_cf -y $fyang #echo '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' | $clixon_netconf -qf $clixon_cf -y $fyang
rm $fconfig rm $fconfig
new "netconf commit large config" new "netconf commit large config"
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf commit same config again"
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf add one small config" new "netconf add one small config"
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>x</a><b>y</b></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>x</a><b>y</b></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -107,9 +110,6 @@ time -p for (( i=0; i<$req; i++ )); do
echo "<rpc><edit-config><target><candidate/></target><config><x><y><a>$rnd</a><b>$rnd</b></y></x></config></edit-config></rpc>]]>]]>" echo "<rpc><edit-config><target><candidate/></target><config><x><y><a>$rnd</a><b>$rnd</b></y></x></config></edit-config></rpc>]]>]]>"
done | $clixon_netconf -qf $clixon_cf -y $fyang > /dev/null done | $clixon_netconf -qf $clixon_cf -y $fyang > /dev/null
new "netconf commit small config"
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf get large config" new "netconf get large config"
expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>0</a><b>0</b></y><y><a>1</a><b>1</b>" expecteof "time -p $clixon_netconf -qf $clixon_cf -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>0</a><b>0</b></y><y><a>1</a><b>1</b>"

View file

@ -38,7 +38,7 @@ bindir = @bindir@
includedir = @includedir@ includedir = @includedir@
datarootdir = @datarootdir@ datarootdir = @datarootdir@
YANGSPECS = clixon-config@2017-07-02.yang YANGSPECS = clixon-config@2017-12-03.yang
YANGSPECS += ietf-netconf@2011-06-01.yang YANGSPECS += ietf-netconf@2011-06-01.yang
APPNAME = clixon # subdir ehere these files are installed APPNAME = clixon # subdir ehere these files are installed

View file

@ -38,7 +38,7 @@
***** END LICENSE BLOCK *****"; ***** END LICENSE BLOCK *****";
revision 2017-11-12 { revision 2017-07-02 {
description description
"Added startup config"; "Added startup config";
} }

View file

@ -0,0 +1,256 @@
module clixon-config {
prefix cc;
organization
"Clicon / Clixon";
contact
"Olof Hagsand <olof@hagsand.se>";
description
"Clixon configuration file
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2017 Olof Hagsand and Benny Holmgren
This file is part of CLIXON
Licensed under the Apache License, Version 2.0 (the \"License\");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an \"AS IS\" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 3 or later (the \"GPL\"),
in which case the provisions of the GPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of the GPL, and not to allow others to
use your version of this file under the terms of Apache License version 2,
indicate your decision by deleting the provisions above and replace them with
the notice and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the Apache License version 2 or the GPL.
***** END LICENSE BLOCK *****";
revision 2017-12-03 {
description
"Added startup config for Clixon 1.3.3 and xmldb_cache in 1.4.0";
}
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
Typically 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
After reboot if a persistent running db exists";
}
enum startup{
description
"Commit startup configuration into running state
After reboot when no persistent running db exists";
}
}
}
container config {
leaf CLICON_CONFIGFILE{
type string;
description
"Location of configuration-file for default values (this file)";
}
leaf CLICON_YANG_DIR {
type string;
mandatory true;
description
"Location of YANG module and submodule files.";
}
leaf CLICON_YANG_MODULE_MAIN {
type string;
default "clicon";
description
"Option used to construct initial yang file:
<module>[@<revision>]";
}
leaf CLICON_YANG_MODULE_REVISION {
type string;
description
"Option used to construct initial yang file:
<module>[@<revision>]";
}
leaf CLICON_BACKEND_DIR {
type string;
description
"Location of backend .so plugins. Load all .so
plugins in this dir as backend plugins";
}
leaf CLICON_NETCONF_DIR {
type string;
description "Location of netconf (frontend) .so plugins";
}
leaf CLICON_RESTCONF_DIR {
type string;
description
"Location of restconf (frontend) .so plugins. Load all .so
plugins in this dir as restconf code plugins";
}
leaf CLICON_RESTCONF_PATH {
type string;
default "/www-data/fastcgi_restconf.sock";
description
"FastCGI unix socket. Should be specified in webserver
Eg in nginx: fastcgi_pass unix:/www-data/clicon_restconf.sock";
}
leaf CLICON_CLI_DIR {
type string;
description
"Location of cli frontend .so plugins. Load all .so
plugins in this dir as CLI object plugins";
}
leaf CLICON_CLISPEC_DIR {
type string;
description
"Location of frontend .cli cligen spec files. Load all .cli
files in this dir as CLI specification files";
}
leaf CLICON_CLISPEC_FILE {
type string;
description "Specific frontend .cli cligen spec file.";
}
leaf CLICON_CLI_MODE {
type string;
default "base";
description
"Startup CLI mode. This should match a CLICON_MODE set in
one of the clispec files";
}
leaf CLICON_CLI_GENMODEL {
type int32;
default 1;
description
"Generate code for CLI completion of existing db symbols.
Example: Add name=\"myspec\" in datamodel spec and reference
as @myspec";
}
leaf CLICON_CLI_GENMODEL_COMPLETION {
type int32;
default 1;
description "Generate code for CLI completion of existing db symbols";
}
leaf CLICON_CLI_GENMODEL_TYPE {
type string;
default "VARS";
description "How to generate and show CLI syntax: VARS|ALL";
}
leaf CLICON_CLI_VARONLY {
type int32;
default 1;
description
"Dont include keys in cvec in cli vars callbacks,
ie a & k in 'a <b> k <c>' ignored";
}
leaf CLICON_CLI_LINESCROLLING {
type int32;
default 1;
description
"Set to 0 if you want CLI to wrap to next line.
Set to 1 if you want CLI to scroll sideways when approaching
right margin";
}
leaf CLICON_SOCK_FAMILY {
type string;
default "UNIX";
description
"Address family for communicating with clixon_backend
(UNIX|IPv4|IPv6)";
}
leaf CLICON_SOCK {
type string;
mandatory true;
description
"If family above is AF_UNIX: Unix socket for communicating
with clixon_backend. If family is AF_INET: IPv4 address";
}
leaf CLICON_SOCK_PORT {
type int32;
default 4535;
description
"Inet socket port for communicating with clixon_backend
(only IPv4|IPv6)";
}
leaf CLICON_SOCK_GROUP {
type string;
default "clicon";
description "Group membership to access clixon_backend unix socket";
}
leaf CLICON_BACKEND_PIDFILE {
type string;
mandatory true;
description "Process-id file of backend daemon";
}
leaf CLICON_AUTOCOMMIT {
type int32;
default 0;
description
"Set if all configuration changes are committed automatically
on every edit change. Explicit commit commands unnecessary";
}
leaf CLICON_MASTER_PLUGIN {
type string;
default "master";
description
"Name of master plugin (both frontend and backend).
Master plugin has special callbacks for frontends.
See clicon user manual for more info. (Obsolete?)";
}
leaf CLICON_XMLDB_DIR {
type string;
mandatory true;
description
"Directory where \"running\", \"candidate\" and \"startup\" are placed";
}
leaf CLICON_XMLDB_PLUGIN {
type string;
mandatory true;
description
"XMLDB datastore plugin filename
(see datastore/ and clixon_xml_db.[ch])";
}
leaf CLICON_XMLDB_CACHE {
type boolean;
default true;
description
"XMLDB datastore cache.
If set, XML parsed tree is stored in memory";
}
leaf CLICON_USE_STARTUP_CONFIG {
type int32;
default 0;
description
"Enabled uses \"startup\" configuration on boot. It is called
startup_db and exists in XMLDB_DIR.
NOTE: Obsolete with 1.3.3 and CLICON_STARTUP_MODE";
}
leaf CLICON_STARTUP_MODE {
type startup_mode;
description "Which method to boot/start clicon backend";
}
}
}