* Configuration directory
* A new configuration option `CLICON_CONFIGDIR` has been added for loading of extra config files
* If not given, only the main configfile is loaded.
* If given, and if the directory exists, the files in this directory will be loaded alphabetically AFTER the main config file in the following way:
* leaf values are overwritten
* leaf-list values are appended
* You can override file setting with `-E <dir>` command-line option.
* New clixon-config@2020-10-01.yang revision
* Added option for configuration directory: `CLICON_CONFIGDIR`
This commit is contained in:
parent
b3545871c0
commit
6f2c4a076d
11 changed files with 1245 additions and 80 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -37,11 +37,20 @@ Expected: 15 October 2020
|
||||||
* Verification of XPath functions is done at startup when yang modules are loaded, not when XPaths are evaluated.
|
* Verification of XPath functions is done at startup when yang modules are loaded, not when XPaths are evaluated.
|
||||||
* Separation of "not found" and "not implemented" XPath functions
|
* Separation of "not found" and "not implemented" XPath functions
|
||||||
* Both give a fatal error (backend does not start).
|
* Both give a fatal error (backend does not start).
|
||||||
|
* Configuration directory
|
||||||
|
* A new configuration option `CLICON_CONFIGDIR` has been added for loading of extra config files
|
||||||
|
* If not given, only the main configfile is loaded.
|
||||||
|
* If given, and if the directory exists, the files in this directory will be loaded alphabetically AFTER the main config file in the following way:
|
||||||
|
* leaf values are overwritten
|
||||||
|
* leaf-list values are appended
|
||||||
|
* You can override file setting with `-E <dir>` command-line option.
|
||||||
|
|
||||||
### API changes on existing protocol/config features
|
### API changes on existing protocol/config features
|
||||||
|
|
||||||
Users may have to change how they access the system
|
Users may have to change how they access the system
|
||||||
|
|
||||||
|
* New clixon-config@2020-10-01.yang revision
|
||||||
|
* Added option for configuration directory: `CLICON_CONFIGDIR`
|
||||||
* Not implemented XPath functions will cause a backend exit on startup, instead of being ignored.
|
* Not implemented XPath functions will cause a backend exit on startup, instead of being ignored.
|
||||||
|
|
||||||
### Minor changes
|
### Minor changes
|
||||||
|
|
@ -59,7 +68,7 @@ Users may have to change how they access the system
|
||||||
14 September 2020
|
14 September 2020
|
||||||
|
|
||||||
This release is primarily a bugfix and usability improvement release, no major new features.
|
This release is primarily a bugfix and usability improvement release, no major new features.
|
||||||
ppp
|
|
||||||
### API changes on existing protocol/config features
|
### API changes on existing protocol/config features
|
||||||
|
|
||||||
Users may have to change how they access the system
|
Users may have to change how they access the system
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@
|
||||||
#include "backend_startup.h"
|
#include "backend_startup.h"
|
||||||
|
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* Command line options to be passed to getopt(3) */
|
||||||
#define BACKEND_OPTS "hD:f:l:d:p:b:Fza:u:P:1qs:c:U:g:y:o:"
|
#define BACKEND_OPTS "hD:f:E:l:d:p:b:Fza:u:P:1qs:c:U:g:y:o:"
|
||||||
|
|
||||||
#define BACKEND_LOGFILE "/usr/local/var/clixon_backend.log"
|
#define BACKEND_LOGFILE "/usr/local/var/clixon_backend.log"
|
||||||
|
|
||||||
|
|
@ -402,6 +402,7 @@ usage(clicon_handle h,
|
||||||
"\t-h\t\tHelp\n"
|
"\t-h\t\tHelp\n"
|
||||||
"\t-D <level>\tDebug level\n"
|
"\t-D <level>\tDebug level\n"
|
||||||
"\t-f <file>\tCLICON config file\n"
|
"\t-f <file>\tCLICON config file\n"
|
||||||
|
"\t-E <dir> \tExtra configuration file directory\n"
|
||||||
"\t-l (s|e|o|f<file>) Log on (s)yslog, std(e)rr or std(o)ut (stderr is default) Only valid if -F, if background syslog is on syslog.\n"
|
"\t-l (s|e|o|f<file>) Log on (s)yslog, std(e)rr or std(o)ut (stderr is default) Only valid if -F, if background syslog is on syslog.\n"
|
||||||
"\t-d <dir>\tSpecify backend plugin directory (default: %s)\n"
|
"\t-d <dir>\tSpecify backend plugin directory (default: %s)\n"
|
||||||
"\t-p <dir>\tYang directory path (see CLICON_YANG_DIR)\n"
|
"\t-p <dir>\tYang directory path (see CLICON_YANG_DIR)\n"
|
||||||
|
|
@ -500,6 +501,11 @@ main(int argc,
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'E': /* extra config directory */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv[0]);
|
||||||
|
clicon_option_str_set(h, "CLICON_CONFIGDIR", optarg);
|
||||||
|
break;
|
||||||
case 'l': /* Log destination: s|e|o */
|
case 'l': /* Log destination: s|e|o */
|
||||||
if ((logdst = clicon_log_opt(optarg[0])) < 0)
|
if ((logdst = clicon_log_opt(optarg[0])) < 0)
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
|
|
@ -523,7 +529,7 @@ main(int argc,
|
||||||
if (clicon_options_main(h) < 0){
|
if (clicon_options_main(h) < 0){
|
||||||
if (help)
|
if (help)
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
return -1;
|
goto done;
|
||||||
}
|
}
|
||||||
/* External NACM file? */
|
/* External NACM file? */
|
||||||
nacm_mode = clicon_option_str(h, "CLICON_NACM_MODE");
|
nacm_mode = clicon_option_str(h, "CLICON_NACM_MODE");
|
||||||
|
|
@ -539,6 +545,7 @@ main(int argc,
|
||||||
case 'h' : /* help */
|
case 'h' : /* help */
|
||||||
case 'D' : /* debug */
|
case 'D' : /* debug */
|
||||||
case 'f': /* config file */
|
case 'f': /* config file */
|
||||||
|
case 'E': /* extra config dir */
|
||||||
case 'l' :
|
case 'l' :
|
||||||
break; /* see above */
|
break; /* see above */
|
||||||
case 'd': /* Plugin directory */
|
case 'd': /* Plugin directory */
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@
|
||||||
#include "cli_handle.h"
|
#include "cli_handle.h"
|
||||||
|
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* Command line options to be passed to getopt(3) */
|
||||||
#define CLI_OPTS "hD:f:l:F:1a:u:d:m:qp:GLy:c:U:o:"
|
#define CLI_OPTS "hD:f:E:l:F:1a:u:d:m:qp:GLy:c:U:o:"
|
||||||
|
|
||||||
/*! Check if there is a CLI history file and if so dump the CLI histiry to it
|
/*! Check if there is a CLI history file and if so dump the CLI histiry to it
|
||||||
* Just log if file does not exist or is not readable
|
* Just log if file does not exist or is not readable
|
||||||
|
|
@ -361,6 +361,7 @@ usage(clicon_handle h,
|
||||||
"\t-h \t\tHelp\n"
|
"\t-h \t\tHelp\n"
|
||||||
"\t-D <level> \tDebug level\n"
|
"\t-D <level> \tDebug level\n"
|
||||||
"\t-f <file> \tConfig-file (mandatory)\n"
|
"\t-f <file> \tConfig-file (mandatory)\n"
|
||||||
|
"\t-E <dir> \tExtra configuration file directory\n"
|
||||||
"\t-F <file> \tRead commands from file (default stdin)\n"
|
"\t-F <file> \tRead commands from file (default stdin)\n"
|
||||||
"\t-1\t\tDo not enter interactive mode\n"
|
"\t-1\t\tDo not enter interactive mode\n"
|
||||||
"\t-a UNIX|IPv4|IPv6\tInternal backend socket family\n"
|
"\t-a UNIX|IPv4|IPv6\tInternal backend socket family\n"
|
||||||
|
|
@ -456,6 +457,11 @@ main(int argc,
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'E': /* extra config directory */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv[0]);
|
||||||
|
clicon_option_str_set(h, "CLICON_CONFIGDIR", optarg);
|
||||||
|
break;
|
||||||
case 'l': /* Log destination: s|e|o|f */
|
case 'l': /* Log destination: s|e|o|f */
|
||||||
if ((logdst = clicon_log_opt(optarg[0])) < 0)
|
if ((logdst = clicon_log_opt(optarg[0])) < 0)
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
|
|
@ -476,9 +482,8 @@ main(int argc,
|
||||||
if (clicon_options_main(h) < 0){
|
if (clicon_options_main(h) < 0){
|
||||||
if (help)
|
if (help)
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
return -1;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now rest of options */
|
/* Now rest of options */
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
optind = 1;
|
optind = 1;
|
||||||
|
|
@ -486,6 +491,7 @@ main(int argc,
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'D' : /* debug */
|
case 'D' : /* debug */
|
||||||
case 'f': /* config file */
|
case 'f': /* config file */
|
||||||
|
case 'E': /* extra config dir */
|
||||||
case 'l': /* Log destination */
|
case 'l': /* Log destination */
|
||||||
break; /* see above */
|
break; /* see above */
|
||||||
case 'F': /* read commands from file */
|
case 'F': /* read commands from file */
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
#include "netconf_rpc.h"
|
#include "netconf_rpc.h"
|
||||||
|
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* Command line options to be passed to getopt(3) */
|
||||||
#define NETCONF_OPTS "hD:f:l:qa:u:d:p:y:U:t:eo:"
|
#define NETCONF_OPTS "hD:f:E:l:qa:u:d:p:y:U:t:eo:"
|
||||||
|
|
||||||
#define NETCONF_LOGFILE "/tmp/clixon_netconf.log"
|
#define NETCONF_LOGFILE "/tmp/clixon_netconf.log"
|
||||||
|
|
||||||
|
|
@ -369,6 +369,7 @@ usage(clicon_handle h,
|
||||||
"\t-h\t\tHelp\n"
|
"\t-h\t\tHelp\n"
|
||||||
"\t-D <level>\tDebug level\n"
|
"\t-D <level>\tDebug level\n"
|
||||||
"\t-f <file>\tConfiguration file (mandatory)\n"
|
"\t-f <file>\tConfiguration file (mandatory)\n"
|
||||||
|
"\t-E <dir> \tExtra configuration file directory\n"
|
||||||
"\t-l (e|o|s|f<file>) Log on std(e)rr, std(o)ut, (s)yslog(default), (f)ile\n"
|
"\t-l (e|o|s|f<file>) Log on std(e)rr, std(o)ut, (s)yslog(default), (f)ile\n"
|
||||||
"\t-q\t\tQuiet: dont send hello prompt\n"
|
"\t-q\t\tQuiet: dont send hello prompt\n"
|
||||||
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
|
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
|
||||||
|
|
@ -434,6 +435,11 @@ main(int argc,
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'E': /* extra config directory */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv[0]);
|
||||||
|
clicon_option_str_set(h, "CLICON_CONFIGDIR", optarg);
|
||||||
|
break;
|
||||||
case 'l': /* Log destination: s|e|o */
|
case 'l': /* Log destination: s|e|o */
|
||||||
if ((logdst = clicon_log_opt(optarg[0])) < 0)
|
if ((logdst = clicon_log_opt(optarg[0])) < 0)
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
|
|
@ -452,7 +458,7 @@ main(int argc,
|
||||||
|
|
||||||
/* Find, read and parse configfile */
|
/* Find, read and parse configfile */
|
||||||
if (clicon_options_main(h) < 0)
|
if (clicon_options_main(h) < 0)
|
||||||
return -1;
|
goto done;
|
||||||
|
|
||||||
/* Now rest of options */
|
/* Now rest of options */
|
||||||
optind = 1;
|
optind = 1;
|
||||||
|
|
@ -462,6 +468,7 @@ main(int argc,
|
||||||
case 'h' : /* help */
|
case 'h' : /* help */
|
||||||
case 'D' : /* debug */
|
case 'D' : /* debug */
|
||||||
case 'f': /* config file */
|
case 'f': /* config file */
|
||||||
|
case 'E': /* extra config dir */
|
||||||
case 'l': /* log */
|
case 'l': /* log */
|
||||||
break; /* see above */
|
break; /* see above */
|
||||||
case 'q': /* quiet: dont write hello */
|
case 'q': /* quiet: dont write hello */
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@
|
||||||
#include "restconf_root.h"
|
#include "restconf_root.h"
|
||||||
|
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* Command line options to be passed to getopt(3) */
|
||||||
#define RESTCONF_OPTS "hD:f:l:p:d:y:a:u:ro:scP:"
|
#define RESTCONF_OPTS "hD:f:E:l:p:d:y:a:u:ro:scP:"
|
||||||
|
|
||||||
/* See see listen(5) */
|
/* See see listen(5) */
|
||||||
#define SOCKET_LISTEN_BACKLOG 16
|
#define SOCKET_LISTEN_BACKLOG 16
|
||||||
|
|
@ -594,6 +594,7 @@ usage(clicon_handle h,
|
||||||
"\t-h \t\t Help\n"
|
"\t-h \t\t Help\n"
|
||||||
"\t-D <level>\t Debug level\n"
|
"\t-D <level>\t Debug level\n"
|
||||||
"\t-f <file>\t Configuration file (mandatory)\n"
|
"\t-f <file>\t Configuration file (mandatory)\n"
|
||||||
|
"\t-E <dir> \t Extra configuration file directory\n"
|
||||||
"\t-l <s|f<file>> \t Log on (s)yslog, (f)ile (syslog is default)\n"
|
"\t-l <s|f<file>> \t Log on (s)yslog, (f)ile (syslog is default)\n"
|
||||||
"\t-p <dir>\t Yang directory path (see CLICON_YANG_DIR)\n"
|
"\t-p <dir>\t Yang directory path (see CLICON_YANG_DIR)\n"
|
||||||
"\t-d <dir>\t Specify restconf plugin directory dir (default: %s)\n"
|
"\t-d <dir>\t Specify restconf plugin directory dir (default: %s)\n"
|
||||||
|
|
@ -666,6 +667,11 @@ main(int argc,
|
||||||
usage(h, argv0);
|
usage(h, argv0);
|
||||||
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'E': /* extra config directory */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv[0]);
|
||||||
|
clicon_option_str_set(h, "CLICON_CONFIGDIR", optarg);
|
||||||
|
break;
|
||||||
case 'l': /* Log destination: s|e|o */
|
case 'l': /* Log destination: s|e|o */
|
||||||
if ((logdst = clicon_log_opt(optarg[0])) < 0)
|
if ((logdst = clicon_log_opt(optarg[0])) < 0)
|
||||||
usage(h, argv0);
|
usage(h, argv0);
|
||||||
|
|
@ -715,6 +721,7 @@ main(int argc,
|
||||||
case 'h' : /* help */
|
case 'h' : /* help */
|
||||||
case 'D' : /* debug */
|
case 'D' : /* debug */
|
||||||
case 'f': /* config file */
|
case 'f': /* config file */
|
||||||
|
case 'E': /* extra config dir */
|
||||||
case 'l': /* log */
|
case 'l': /* log */
|
||||||
break; /* see above */
|
break; /* see above */
|
||||||
case 'p' : /* yang dir path */
|
case 'p' : /* yang dir path */
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@
|
||||||
#include "restconf_stream.h"
|
#include "restconf_stream.h"
|
||||||
|
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* Command line options to be passed to getopt(3) */
|
||||||
#define RESTCONF_OPTS "hD:f:l:p:d:y:a:u:ro:"
|
#define RESTCONF_OPTS "hD:f:E:l:p:d:y:a:u:ro:"
|
||||||
|
|
||||||
/*! Convert FCGI parameters to clixon runtime data
|
/*! Convert FCGI parameters to clixon runtime data
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
|
|
@ -172,6 +172,7 @@ usage(clicon_handle h,
|
||||||
"\t-h \t\t Help\n"
|
"\t-h \t\t Help\n"
|
||||||
"\t-D <level>\t Debug level\n"
|
"\t-D <level>\t Debug level\n"
|
||||||
"\t-f <file>\t Configuration file (mandatory)\n"
|
"\t-f <file>\t Configuration file (mandatory)\n"
|
||||||
|
"\t-E <dir> \t Extra configuration file directory\n"
|
||||||
"\t-l <s|f<file>> \t Log on (s)yslog, (f)ile (syslog is default)\n"
|
"\t-l <s|f<file>> \t Log on (s)yslog, (f)ile (syslog is default)\n"
|
||||||
"\t-p <dir>\t Yang directory path (see CLICON_YANG_DIR)\n"
|
"\t-p <dir>\t Yang directory path (see CLICON_YANG_DIR)\n"
|
||||||
"\t-d <dir>\t Specify restconf plugin directory dir (default: %s)\n"
|
"\t-d <dir>\t Specify restconf plugin directory dir (default: %s)\n"
|
||||||
|
|
@ -239,6 +240,11 @@ main(int argc,
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'E': /* extra config directory */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv[0]);
|
||||||
|
clicon_option_str_set(h, "CLICON_CONFIGDIR", optarg);
|
||||||
|
break;
|
||||||
case 'l': /* Log destination: s|e|o */
|
case 'l': /* Log destination: s|e|o */
|
||||||
if ((logdst = clicon_log_opt(optarg[0])) < 0)
|
if ((logdst = clicon_log_opt(optarg[0])) < 0)
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
|
|
@ -281,6 +287,7 @@ main(int argc,
|
||||||
case 'h' : /* help */
|
case 'h' : /* help */
|
||||||
case 'D' : /* debug */
|
case 'D' : /* debug */
|
||||||
case 'f': /* config file */
|
case 'f': /* config file */
|
||||||
|
case 'E': /* extra config dir */
|
||||||
case 'l': /* log */
|
case 'l': /* log */
|
||||||
break; /* see above */
|
break; /* see above */
|
||||||
case 'p' : /* yang dir path */
|
case 'p' : /* yang dir path */
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <libgen.h> /* dirname */
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
@ -65,6 +67,7 @@
|
||||||
#include "clixon_queue.h"
|
#include "clixon_queue.h"
|
||||||
#include "clixon_hash.h"
|
#include "clixon_hash.h"
|
||||||
#include "clixon_handle.h"
|
#include "clixon_handle.h"
|
||||||
|
#include "clixon_file.h"
|
||||||
#include "clixon_log.h"
|
#include "clixon_log.h"
|
||||||
#include "clixon_yang.h"
|
#include "clixon_yang.h"
|
||||||
#include "clixon_xml.h"
|
#include "clixon_xml.h"
|
||||||
|
|
@ -190,51 +193,29 @@ clicon_option_dump(clicon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Read filename and set values to global options registry. XML variant.
|
/*! Open and parse single config file
|
||||||
*
|
* @param[in] filename
|
||||||
|
* @param[in] yspec
|
||||||
* @param[out] xconfig Pointer to xml config tree. Should be freed by caller
|
* @param[out] xconfig Pointer to xml config tree. Should be freed by caller
|
||||||
* @retval 0 OK
|
|
||||||
* @retval -1 Error
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
parse_configfile(clicon_handle h,
|
parse_configfile_one(const char *filename,
|
||||||
const char *filename,
|
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
cxobj **xconfig)
|
cxobj **xconfig)
|
||||||
{
|
{
|
||||||
struct stat st;
|
|
||||||
FILE *f = NULL;
|
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int fd;
|
int fd = -1;
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
cxobj *xc = NULL;
|
|
||||||
cxobj *x = NULL;
|
|
||||||
char *name;
|
|
||||||
char *body;
|
|
||||||
clicon_hash_t *copt = clicon_options(h);
|
|
||||||
cbuf *cbret = NULL;
|
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
|
cxobj *xa;
|
||||||
|
cbuf *cbret = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
cvec *nsc = NULL;
|
|
||||||
|
|
||||||
if (filename == NULL || !strlen(filename)){
|
if ((fd = open(filename, O_RDONLY)) < 0){
|
||||||
clicon_err(OE_UNIX, 0, "Not specified");
|
clicon_err(OE_UNIX, errno, "open configure file: %s", filename);
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (stat(filename, &st) < 0){
|
|
||||||
clicon_err(OE_UNIX, errno, "%s", filename);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (!S_ISREG(st.st_mode)){
|
|
||||||
clicon_err(OE_UNIX, 0, "%s is not a regular file", filename);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((f = fopen(filename, "r")) == NULL) {
|
|
||||||
clicon_err(OE_UNIX, errno, "configure file: %s", filename);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
clicon_debug(2, "%s: Reading config file %s", __FUNCTION__, filename);
|
clicon_debug(2, "%s: Reading config file %s", __FUNCTION__, filename);
|
||||||
fd = fileno(f);
|
|
||||||
if ((ret = clixon_xml_parse_file(fd, yspec?YB_MODULE:YB_NONE, yspec, NULL, &xt, &xerr)) < 0)
|
if ((ret = clixon_xml_parse_file(fd, yspec?YB_MODULE:YB_NONE, yspec, NULL, &xt, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
|
|
@ -248,21 +229,137 @@ parse_configfile(clicon_handle h,
|
||||||
clixon_netconf_error(xerr, NULL, NULL);
|
clixon_netconf_error(xerr, NULL, NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xml_child_nr(xt)==1 && xml_child_nr_type(xt, CX_BODY)==1){
|
/* Ensure a single root */
|
||||||
clicon_err(OE_CFG, 0, "Config file %s: Expected XML but is probably old sh style", filename);
|
if (xt == NULL || xml_child_nr(xt) != 1){
|
||||||
|
clicon_err(OE_CFG, 0, "Config file %s: Lacks single top element", filename);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Hard-coded config for < 3.10 and clixon-config for >= 3.10 */
|
if (xml_rootchild(xt, 0, &xt) < 0)
|
||||||
if ((nsc = xml_nsctx_init(NULL, CLIXON_CONF_NS)) == NULL)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xc = xpath_first(xt, nsc, "clixon-config")) == NULL){
|
/* Check well-formedness */
|
||||||
|
if (strcmp(xml_name(xt), "clixon-config") != 0 ||
|
||||||
|
(xa = xml_find_type(xt, NULL, "xmlns", CX_ATTR)) == NULL ||
|
||||||
|
strcmp(xml_value(xa), CLIXON_CONF_NS) != 0){
|
||||||
clicon_err(OE_CFG, 0, "Config file %s: Lacks top-level \"clixon-config\" element\nClixon config files should begin with: <clixon-config xmlns=\"%s\">", filename, CLIXON_CONF_NS);
|
clicon_err(OE_CFG, 0, "Config file %s: Lacks top-level \"clixon-config\" element\nClixon config files should begin with: <clixon-config xmlns=\"%s\">", filename, CLIXON_CONF_NS);
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xml_default_recurse(xc, 0) < 0)
|
*xconfig = xt;
|
||||||
|
xt = NULL;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (xt)
|
||||||
|
xml_free(xt);
|
||||||
|
if (fd != -1)
|
||||||
|
close(fd);
|
||||||
|
if (cbret)
|
||||||
|
cbuf_free(cbret);
|
||||||
|
if (xerr)
|
||||||
|
xml_free(xerr);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Read filename and set values to global options registry. XML variant.
|
||||||
|
*
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] filename Main configuration file
|
||||||
|
* @param[in] extraconfig0 Override (if set use that, othewrwise get from main file)
|
||||||
|
* @param[in] yspec Yang spec
|
||||||
|
* @param[out] xconfig Pointer to xml config tree. Should be freed by caller
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parse_configfile(clicon_handle h,
|
||||||
|
const char *filename,
|
||||||
|
char *extraconfdir0,
|
||||||
|
yang_stmt *yspec,
|
||||||
|
cxobj **xconfig)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
struct stat st;
|
||||||
|
cxobj *xt = NULL;
|
||||||
|
cxobj *xc = NULL;
|
||||||
|
cxobj *x = NULL;
|
||||||
|
char *name;
|
||||||
|
char *body;
|
||||||
|
clicon_hash_t *copt = clicon_options(h);
|
||||||
|
cbuf *cbret = NULL;
|
||||||
|
cxobj *xerr = NULL;
|
||||||
|
int ret;
|
||||||
|
cvec *nsc = NULL;
|
||||||
|
int i;
|
||||||
|
int ndp;
|
||||||
|
struct dirent *dp = NULL;
|
||||||
|
char filename1[MAXPATHLEN];
|
||||||
|
char *extraconfdir = NULL;
|
||||||
|
cxobj *xe = NULL;
|
||||||
|
cxobj *xec;
|
||||||
|
DIR *dirp;
|
||||||
|
|
||||||
|
if (filename == NULL || !strlen(filename)){
|
||||||
|
clicon_err(OE_UNIX, 0, "Not specified");
|
||||||
goto done;
|
goto done;
|
||||||
if ((ret = xml_yang_validate_add(h, xc, &xerr)) < 0)
|
}
|
||||||
|
if (stat(filename, &st) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "%s", filename);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (!S_ISREG(st.st_mode)){
|
||||||
|
clicon_err(OE_UNIX, 0, "%s is not a regular file", filename);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* Parse main config file */
|
||||||
|
if (parse_configfile_one(filename, yspec, &xt) < 0)
|
||||||
|
goto done;
|
||||||
|
/* xt is a single-rooted: <clixon-config>...</clixon-config>
|
||||||
|
* If no override (eg from command-line)
|
||||||
|
* Bootstrap: Shortcut to read extra confdir inline */
|
||||||
|
if ((extraconfdir = extraconfdir0) == NULL)
|
||||||
|
if ((xc = xpath_first(xt, 0, "CLICON_CONFIGDIR")) != NULL)
|
||||||
|
extraconfdir = xml_body(xc);
|
||||||
|
if (extraconfdir){ /* If extra dir, parse extra config files */
|
||||||
|
/* A check it exists (also done in clicon_file_dirent) */
|
||||||
|
if ((dirp = opendir(extraconfdir)) == NULL) {
|
||||||
|
clicon_err(OE_UNIX, errno, "CLICON_CONFIGDIR: %s opendir", extraconfdir);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
closedir(dirp);
|
||||||
|
if((ndp = clicon_file_dirent(extraconfdir, &dp, NULL, S_IFREG)) < 0) /* Read dir */
|
||||||
|
goto done;
|
||||||
|
/* Loop through files */
|
||||||
|
for (i = 0; i < ndp; i++){
|
||||||
|
snprintf(filename1, sizeof(filename1), "%s/%s", extraconfdir, dp[i].d_name);
|
||||||
|
if (parse_configfile_one(filename1, yspec, &xe) < 0)
|
||||||
|
goto done;
|
||||||
|
/* Drain objects from extrafile and replace/append to main */
|
||||||
|
while ((xec = xml_child_i_type(xe, 0, CX_ELMNT)) != NULL) {
|
||||||
|
name = xml_name(xec);
|
||||||
|
body = xml_body(xec);
|
||||||
|
/* Ignored from file due to bootstrapping */
|
||||||
|
if (strcmp(name,"CLICON_CONFIGFILE")==0)
|
||||||
|
continue;
|
||||||
|
/* List options for configure options that are leaf-lists: append to main */
|
||||||
|
if (strcmp(name,"CLICON_FEATURE")==0 ||
|
||||||
|
strcmp(name,"CLICON_YANG_DIR")==0){
|
||||||
|
if (xml_addsub(xt, xec) < 0)
|
||||||
|
goto done;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Remove existing in master if any */
|
||||||
|
if ((x = xml_find_type(xt, NULL, name, CX_ELMNT)) != NULL)
|
||||||
|
xml_purge(x);
|
||||||
|
/* Append to master (removed from xe) */
|
||||||
|
if (xml_addsub(xt, xec) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (xe)
|
||||||
|
xml_free(xe);
|
||||||
|
xe = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xml_default_recurse(xt, 0) < 0)
|
||||||
|
goto done;
|
||||||
|
if ((ret = xml_yang_validate_add(h, xt, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
if ((cbret = cbuf_new()) ==NULL){
|
if ((cbret = cbuf_new()) ==NULL){
|
||||||
|
|
@ -274,7 +371,8 @@ parse_configfile(clicon_handle h,
|
||||||
clicon_err(OE_CFG, 0, "Config file validation: %s", cbuf_get(cbret));
|
clicon_err(OE_CFG, 0, "Config file validation: %s", cbuf_get(cbret));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
while ((x = xml_child_each(xc, x, CX_ELMNT)) != NULL) {
|
x = NULL;
|
||||||
|
while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) {
|
||||||
name = xml_name(x);
|
name = xml_name(x);
|
||||||
body = xml_body(x);
|
body = xml_body(x);
|
||||||
if (name == NULL || body == NULL){
|
if (name == NULL || body == NULL){
|
||||||
|
|
@ -282,16 +380,17 @@ parse_configfile(clicon_handle h,
|
||||||
__FUNCTION__, name, body);
|
__FUNCTION__, name, body);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* hard-coded exceptions for configure options that are leaf-lists (not leaf)
|
/* Ignored from file due to bootstrapping */
|
||||||
|
if (strcmp(name,"CLICON_CONFIGFILE")==0)
|
||||||
|
continue;
|
||||||
|
/* List options for configure options that are leaf-lists (not leaf)
|
||||||
* They must be accessed directly by looping over clicon_conf_xml(h)
|
* They must be accessed directly by looping over clicon_conf_xml(h)
|
||||||
*/
|
*/
|
||||||
if (strcmp(name,"CLICON_FEATURE")==0)
|
if (strcmp(name,"CLICON_FEATURE")==0)
|
||||||
continue;
|
continue;
|
||||||
if (strcmp(name,"CLICON_YANG_DIR")==0)
|
if (strcmp(name,"CLICON_YANG_DIR")==0)
|
||||||
continue;
|
continue;
|
||||||
/* Used as an arg to this fn */
|
|
||||||
if (strcmp(name,"CLICON_CONFIGFILE")==0)
|
|
||||||
continue;
|
|
||||||
if (clicon_hash_add(copt,
|
if (clicon_hash_add(copt,
|
||||||
name,
|
name,
|
||||||
body,
|
body,
|
||||||
|
|
@ -302,6 +401,8 @@ parse_configfile(clicon_handle h,
|
||||||
*xconfig = xt;
|
*xconfig = xt;
|
||||||
xt = NULL;
|
xt = NULL;
|
||||||
done:
|
done:
|
||||||
|
if (dp)
|
||||||
|
free(dp);
|
||||||
if (nsc)
|
if (nsc)
|
||||||
xml_nsctx_free(nsc);
|
xml_nsctx_free(nsc);
|
||||||
if (cbret)
|
if (cbret)
|
||||||
|
|
@ -310,8 +411,6 @@ parse_configfile(clicon_handle h,
|
||||||
xml_free(xerr);
|
xml_free(xerr);
|
||||||
if (xt)
|
if (xt)
|
||||||
xml_free(xt);
|
xml_free(xt);
|
||||||
if (f)
|
|
||||||
fclose(f);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -375,6 +474,7 @@ clicon_options_main(clicon_handle h)
|
||||||
char xml = 0; /* Configfile is xml, otherwise legacy */
|
char xml = 0; /* Configfile is xml, otherwise legacy */
|
||||||
cxobj *xconfig = NULL;
|
cxobj *xconfig = NULL;
|
||||||
yang_stmt *yspec = NULL;
|
yang_stmt *yspec = NULL;
|
||||||
|
char *extraconfdir = NULL;
|
||||||
|
|
||||||
/* Create configure yang-spec */
|
/* Create configure yang-spec */
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if ((yspec = yspec_new()) == NULL)
|
||||||
|
|
@ -396,20 +496,27 @@ clicon_options_main(clicon_handle h)
|
||||||
clicon_err(OE_CFG, 0, "%s: suffix %s not recognized", configfile, suffix);
|
clicon_err(OE_CFG, 0, "%s: suffix %s not recognized", configfile, suffix);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Read configfile first without yangspec, for bootstrapping, see second
|
|
||||||
* time below with proper yangspec.
|
/* Override extraconfdir */
|
||||||
* (You need to read the config-file to get the YANG_DIR to find the
|
if (clicon_option_str(h, "CLICON_CONFIGDIR") &&
|
||||||
* the clixon yang-spec)
|
(extraconfdir = strdup(clicon_option_str(h, "CLICON_CONFIGDIR"))) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read configfile first without yangspec, and without extra config dir for bootstrapping,
|
||||||
|
* see second time below with proper yangspec and extra config dir
|
||||||
|
* (You need to read the config-file to get the YANG_DIR to find the clixon yang-spec)
|
||||||
* Difference from parsing with yangspec is:
|
* Difference from parsing with yangspec is:
|
||||||
* - no default values
|
* - no default values
|
||||||
* - no sanity checks
|
* - no sanity checks
|
||||||
|
* - no extra config dir
|
||||||
*/
|
*/
|
||||||
if (parse_configfile(h, configfile, NULL, &xconfig) < 0)
|
if (parse_configfile(h, configfile, extraconfdir, NULL, &xconfig) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_rootchild(xconfig, 0, &xconfig) < 0)
|
|
||||||
goto done;
|
|
||||||
/* Set clixon_conf pointer to handle */
|
|
||||||
clicon_conf_xml_set(h, xconfig);
|
clicon_conf_xml_set(h, xconfig);
|
||||||
|
|
||||||
/* Parse clixon yang spec */
|
/* Parse clixon yang spec */
|
||||||
if (yang_spec_parse_module(h, "clixon-config", NULL, yspec) < 0)
|
if (yang_spec_parse_module(h, "clixon-config", NULL, yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -418,10 +525,9 @@ clicon_options_main(clicon_handle h)
|
||||||
xml_free(xconfig);
|
xml_free(xconfig);
|
||||||
xconfig = NULL;
|
xconfig = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read configfile second time now with check yang spec */
|
/* Read configfile second time now with check yang spec */
|
||||||
if (parse_configfile(h, configfile, yspec, &xconfig) < 0)
|
if (parse_configfile(h, configfile, extraconfdir, yspec, &xconfig) < 0)
|
||||||
goto done;
|
|
||||||
if (xml_rootchild(xconfig, 0, &xconfig) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_spec(xconfig) == NULL){
|
if (xml_spec(xconfig) == NULL){
|
||||||
clicon_err(OE_CFG, 0, "Config file %s: did not find corresponding Yang specification\nHint: File does not begin with: <clixon-config xmlns=\"%s\"> or clixon-config.yang not found?", configfile, CLIXON_CONF_NS);
|
clicon_err(OE_CFG, 0, "Config file %s: did not find corresponding Yang specification\nHint: File does not begin with: <clixon-config xmlns=\"%s\"> or clixon-config.yang not found?", configfile, CLIXON_CONF_NS);
|
||||||
|
|
@ -430,12 +536,17 @@ clicon_options_main(clicon_handle h)
|
||||||
/* Set yang config spec (must store to free at exit, since conf_xml below uses it) */
|
/* Set yang config spec (must store to free at exit, since conf_xml below uses it) */
|
||||||
if (clicon_config_yang_set(h, yspec) < 0)
|
if (clicon_config_yang_set(h, yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
yspec = NULL;
|
||||||
/* Set clixon_conf pointer to handle */
|
/* Set clixon_conf pointer to handle */
|
||||||
if (clicon_conf_xml_set(h, xconfig) < 0)
|
if (clicon_conf_xml_set(h, xconfig) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (yspec)
|
||||||
|
ys_free(yspec);
|
||||||
|
if (extraconfdir)
|
||||||
|
free(extraconfdir);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
128
test/test_configdir.sh
Executable file
128
test/test_configdir.sh
Executable file
|
|
@ -0,0 +1,128 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Test config file and extra config dir.
|
||||||
|
# Use clixon_cli and assume clixon_backend/restconf/netconf behaves the same
|
||||||
|
# Start without configdir as baseline
|
||||||
|
# Start with wrong configdir
|
||||||
|
# Start with empty configfile
|
||||||
|
# Start with 1 extra configfile
|
||||||
|
# Start with 2 extra configfiles
|
||||||
|
# Start with 2 extra configfiles + command-line
|
||||||
|
# Two options are used for testing:
|
||||||
|
# CLICON_MODULE_SET_ID is a single var (replaced)
|
||||||
|
# CLICON_FEATURE is a list var (append)
|
||||||
|
#
|
||||||
|
# Magic line must be first in script (see README.md)
|
||||||
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
||||||
|
APPNAME=example
|
||||||
|
|
||||||
|
cfg=$dir/conf_yang.xml
|
||||||
|
cdir=$dir/conf.d
|
||||||
|
cfile1=$cdir/00a.xml
|
||||||
|
cfile2=$cdir/01a.xml
|
||||||
|
|
||||||
|
test -d $cdir || mkdir $cdir
|
||||||
|
|
||||||
|
cat <<EOF > $cfg
|
||||||
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
|
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||||
|
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||||
|
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
|
<CLICON_MODULE_SET_ID>1</CLICON_MODULE_SET_ID>
|
||||||
|
<CLICON_FEATURE>test1</CLICON_FEATURE>
|
||||||
|
</clixon-config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat <<EOF > $cfile1
|
||||||
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
|
<CLICON_MODULE_SET_ID>2</CLICON_MODULE_SET_ID>
|
||||||
|
<CLICON_FEATURE>test2</CLICON_FEATURE>
|
||||||
|
</clixon-config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "Start without configdir as baseline"
|
||||||
|
expectpart "$($clixon_cli -1 -f $cfg show options)" 0 'CLICON_MODULE_SET_ID: "1"' 'CLICON_FEATURE: "test1"' --not-- 'CLICON_FEATURE: "test2"'
|
||||||
|
|
||||||
|
cat <<EOF > $cfg
|
||||||
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
|
<CLICON_CONFIGDIR>$dir/dontexist</CLICON_CONFIGDIR>
|
||||||
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
|
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||||
|
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||||
|
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
|
<CLICON_MODULE_SET_ID>1</CLICON_MODULE_SET_ID>
|
||||||
|
<CLICON_FEATURE>test1</CLICON_FEATURE>
|
||||||
|
</clixon-config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "Start with wrong configdir"
|
||||||
|
expectpart "$($clixon_cli -1 -f $cfg -l o show options)" 255 "UNIX error: CLICON_CONFIGDIR:" "opendir: No such file or directory"
|
||||||
|
|
||||||
|
rm -f $cfile1
|
||||||
|
cat <<EOF > $cfg
|
||||||
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
|
<CLICON_CONFIGDIR>$dir/notexist</CLICON_CONFIGDIR>
|
||||||
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
|
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||||
|
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||||
|
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
|
<CLICON_MODULE_SET_ID>1</CLICON_MODULE_SET_ID>
|
||||||
|
<CLICON_FEATURE>test1</CLICON_FEATURE>
|
||||||
|
</clixon-config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "Start with wrong configdir -E override"
|
||||||
|
expectpart "$($clixon_cli -1 -f $cfg -E $cdir show options)" 0 'CLICON_MODULE_SET_ID: "1"' 'CLICON_FEATURE: "test1"' --not-- 'CLICON_FEATURE: "test2"'
|
||||||
|
|
||||||
|
cat <<EOF > $cfg
|
||||||
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
|
<CLICON_CONFIGDIR>$cdir</CLICON_CONFIGDIR>
|
||||||
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
|
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||||
|
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||||
|
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
|
<CLICON_MODULE_SET_ID>1</CLICON_MODULE_SET_ID>
|
||||||
|
<CLICON_FEATURE>test1</CLICON_FEATURE>
|
||||||
|
</clixon-config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "Start with empty configdir"
|
||||||
|
expectpart "$($clixon_cli -1 -f $cfg -l o show options)" 0 'CLICON_MODULE_SET_ID: "1"' 'CLICON_FEATURE: "test1"' --not-- 'CLICON_FEATURE: "test2"'
|
||||||
|
|
||||||
|
cat <<EOF > $cfile1
|
||||||
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
|
<CLICON_MODULE_SET_ID>2</CLICON_MODULE_SET_ID>
|
||||||
|
<CLICON_FEATURE>test2</CLICON_FEATURE>
|
||||||
|
</clixon-config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "Start with 1 extra configfile"
|
||||||
|
expectpart "$($clixon_cli -1 -f $cfg -l o show options)" 0 'CLICON_MODULE_SET_ID: "2"' 'CLICON_FEATURE: "test1"' 'CLICON_FEATURE: "test2"'
|
||||||
|
|
||||||
|
cat <<EOF > $cfile2
|
||||||
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
|
<CLICON_MODULE_SET_ID>3</CLICON_MODULE_SET_ID>
|
||||||
|
<CLICON_FEATURE>test3</CLICON_FEATURE>
|
||||||
|
</clixon-config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
new "Start with 2 extra configfiles"
|
||||||
|
expectpart "$($clixon_cli -1 -f $cfg -l o show options)" 0 'CLICON_MODULE_SET_ID: "3"' 'CLICON_FEATURE: "test1"' 'CLICON_FEATURE: "test2"' 'CLICON_FEATURE: "test3"'
|
||||||
|
|
||||||
|
new "Start with 2 extra configfiles + command-line"
|
||||||
|
expectpart "$($clixon_cli -1 -f $cfg -o CLICON_MODULE_SET_ID=4 -o CLICON_FEATURE=test4 -l o show options)" 0 'CLICON_MODULE_SET_ID: "4"' 'CLICON_FEATURE: "test1"' 'CLICON_FEATURE: "test2"' 'CLICON_FEATURE: "test3"' 'CLICON_FEATURE: "test4"'
|
||||||
|
|
||||||
|
rm -rf $dir
|
||||||
|
|
@ -42,7 +42,7 @@ datarootdir = @datarootdir@
|
||||||
# See also OPT_YANG_INSTALLDIR for the standard yang files
|
# See also OPT_YANG_INSTALLDIR for the standard yang files
|
||||||
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
||||||
|
|
||||||
YANGSPECS = clixon-config@2020-08-17.yang
|
YANGSPECS = clixon-config@2020-10-01.yang
|
||||||
YANGSPECS += clixon-lib@2020-04-23.yang
|
YANGSPECS += clixon-lib@2020-04-23.yang
|
||||||
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
||||||
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
||||||
|
|
|
||||||
1
yang/clixon/clixon-config.yang
Symbolic link
1
yang/clixon/clixon-config.yang
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
clixon-config@2020-10-01.yang
|
||||||
882
yang/clixon/clixon-config@2020-10-01.yang
Normal file
882
yang/clixon/clixon-config@2020-10-01.yang
Normal file
|
|
@ -0,0 +1,882 @@
|
||||||
|
module clixon-config {
|
||||||
|
yang-version 1.1;
|
||||||
|
namespace "http://clicon.org/config";
|
||||||
|
prefix cc;
|
||||||
|
|
||||||
|
organization
|
||||||
|
"Clicon / Clixon";
|
||||||
|
|
||||||
|
contact
|
||||||
|
"Olof Hagsand <olof@hagsand.se>";
|
||||||
|
|
||||||
|
description
|
||||||
|
"Clixon configuration file
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
Copyright (C) 2009-2019 Olof Hagsand
|
||||||
|
Copyright (C) 2020 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
||||||
|
|
||||||
|
This file is part of CLIXON
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the \"License\");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an \"AS IS\" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
Alternatively, the contents of this file may be used under the terms of
|
||||||
|
the GNU General Public License Version 3 or later (the \"GPL\"),
|
||||||
|
in which case the provisions of the GPL are applicable instead
|
||||||
|
of those above. If you wish to allow use of your version of this file only
|
||||||
|
under the terms of the GPL, and not to allow others to
|
||||||
|
use your version of this file under the terms of Apache License version 2,
|
||||||
|
indicate your decision by deleting the provisions above and replace them with
|
||||||
|
the notice and other provisions required by the GPL. If you do not delete
|
||||||
|
the provisions above, a recipient may use your version of this file under
|
||||||
|
the terms of any one of the Apache License version 2 or the GPL.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****";
|
||||||
|
|
||||||
|
revision 2020-10-01 {
|
||||||
|
description
|
||||||
|
"Added: CLICON_CONFIGDIR";
|
||||||
|
}
|
||||||
|
revision 2020-08-17 {
|
||||||
|
description
|
||||||
|
"Added: CLICON_RESTCONF_IPV4_ADDR, CLICON_RESTCONF_IPV6_ADDR,
|
||||||
|
CLICON_RESTCONF_HTTP_PORT, CLICON_RESTCONF_HTTPS_PORT
|
||||||
|
CLICON_NAMESPACE_NETCONF_DEFAULT,
|
||||||
|
CLICON_CLI_HELPSTRING_TRUNCATE, CLICON_CLI_HELPSTRING_LINES";
|
||||||
|
}
|
||||||
|
revision 2020-06-17 {
|
||||||
|
description
|
||||||
|
"Added: CLICON_CLI_LINES_DEFAULT
|
||||||
|
Added enum HIDE to CLICON_CLI_GENMODEL
|
||||||
|
Added CLICON_SSL_SERVER_CERT, CLICON_SSL_SERVER_KEY, CLICON_SSL_CA_CERT
|
||||||
|
Added CLICON_NACM_DISABLED_ON_EMPTY
|
||||||
|
Removed default valude of CLICON_NACM_RECOVERY_USER";
|
||||||
|
}
|
||||||
|
revision 2020-04-23 {
|
||||||
|
description
|
||||||
|
"Added: CLICON_YANG_UNKNOWN_ANYDATA to treat unknown XML (wrt YANG) as anydata.
|
||||||
|
Deleted: xml-stats non-config data (replaced by rpc stats in clixon-lib.yang)";
|
||||||
|
}
|
||||||
|
revision 2020-02-22 {
|
||||||
|
description
|
||||||
|
"Added: search index extension,
|
||||||
|
Added: clixon-stats state for clixon XML and memory statistics.
|
||||||
|
Added: CLICON_CLI_BUF_START and CLICON_CLI_BUF_THRESHOLD for quadratic and linear
|
||||||
|
growth of CLIgen buffers (cbuf:s)
|
||||||
|
Added: CLICON_VALIDATE_STATE_XML for controling validation of user state XML
|
||||||
|
Added: CLICON_CLICON_YANG_LIST_CHECK to skip list key checks";
|
||||||
|
}
|
||||||
|
revision 2019-09-11 {
|
||||||
|
description
|
||||||
|
"Added: CLICON_BACKEND_USER: drop of privileges to user,
|
||||||
|
CLICON_BACKEND_PRIVILEGES: how to drop privileges
|
||||||
|
CLICON_NACM_CREDENTIALS: If and how to check backend sock priveleges with NACM
|
||||||
|
CLICON_NACM_RECOVERY_USER: Name of NACM recovery user.";
|
||||||
|
}
|
||||||
|
revision 2019-06-05 {
|
||||||
|
description
|
||||||
|
"Added: CLICON_YANG_REGEXP, CLICON_CLI_TAB_MODE,
|
||||||
|
CLICON_CLI_HIST_FILE, CLICON_CLI_HIST_SIZE,
|
||||||
|
CLICON_XML_CHANGELOG, CLICON_XML_CHANGELOG_FILE;
|
||||||
|
Renamed CLICON_XMLDB_CACHE to CLICON_DATASTORE_CACHE (changed type)
|
||||||
|
Deleted: CLICON_XMLDB_PLUGIN, CLICON_USE_STARTUP_CONFIG";
|
||||||
|
}
|
||||||
|
revision 2019-03-05{
|
||||||
|
description
|
||||||
|
"Changed URN. Changed top-level symbol to clixon-config.
|
||||||
|
Released in Clixon 3.10";
|
||||||
|
}
|
||||||
|
revision 2019-02-06 {
|
||||||
|
description
|
||||||
|
"Released in Clixon 3.9";
|
||||||
|
}
|
||||||
|
revision 2018-10-21 {
|
||||||
|
description
|
||||||
|
"Released in Clixon 3.8";
|
||||||
|
}
|
||||||
|
extension search_index {
|
||||||
|
description "This list argument acts as a search index using optimized binary search.
|
||||||
|
";
|
||||||
|
}
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typedef datastore_format{
|
||||||
|
description
|
||||||
|
"Datastore format.";
|
||||||
|
type enumeration{
|
||||||
|
enum xml{
|
||||||
|
description "Save and load xmldb as XML";
|
||||||
|
}
|
||||||
|
enum json{
|
||||||
|
description "Save and load xmldb as JSON";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typedef datastore_cache{
|
||||||
|
description
|
||||||
|
"XML configuration, ie running/candididate/ datastore cache behaviour.";
|
||||||
|
type enumeration{
|
||||||
|
enum nocache{
|
||||||
|
description "No cache always work directly with file";
|
||||||
|
}
|
||||||
|
enum cache{
|
||||||
|
description "Use in-memory cache.
|
||||||
|
Make copies when accessing internally.";
|
||||||
|
}
|
||||||
|
enum cache-zerocopy{
|
||||||
|
description "Use in-memory cache and dont copy.
|
||||||
|
Fastest but opens up for callbacks changing cache.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typedef cli_genmodel_type{
|
||||||
|
description
|
||||||
|
"How to generate CLI from YANG model,
|
||||||
|
eg {container c {list a{ key x; leaf x; leaf y;}}";
|
||||||
|
type enumeration{
|
||||||
|
enum NONE{
|
||||||
|
description "No extra keywords: c a <x> <y>";
|
||||||
|
}
|
||||||
|
enum VARS{
|
||||||
|
description "Keywords on non-key variables: c a <x> y <y>";
|
||||||
|
}
|
||||||
|
enum ALL{
|
||||||
|
description "Keywords on all variables: c a x <x> y <y>";
|
||||||
|
}
|
||||||
|
enum HIDE{
|
||||||
|
description "Keywords on non-key variables and hide container around lists: a <x> y <y>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typedef nacm_mode{
|
||||||
|
description
|
||||||
|
"Mode of RFC8341 Network Configuration Access Control Model.
|
||||||
|
It is unclear from the RFC whether NACM rules are internal
|
||||||
|
in a configuration (ie embedded in regular config) or external/OOB
|
||||||
|
in s separate, specific NACM-config";
|
||||||
|
type enumeration{
|
||||||
|
enum disabled{
|
||||||
|
description "NACM is disabled";
|
||||||
|
}
|
||||||
|
enum internal{
|
||||||
|
description "NACM is enabled and available in the regular config";
|
||||||
|
}
|
||||||
|
enum external{
|
||||||
|
description "NACM is enabled and available in a separate config";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typedef regexp_mode{
|
||||||
|
description
|
||||||
|
"The regular expression engine Clixon uses in its validation of
|
||||||
|
Yang patterns, and in the CLI.
|
||||||
|
Yang RFC 7950 stipulates XSD XML Schema regexps
|
||||||
|
according to W3 CXML Schema Part 2: Datatypes Second Edition,
|
||||||
|
see http://www.w3.org/TR/2004/REC-xmlschema-2-20041028#regexs";
|
||||||
|
type enumeration{
|
||||||
|
enum posix {
|
||||||
|
description
|
||||||
|
"Translate XSD XML Schema regexp:s to Posix regexp. This is
|
||||||
|
not a complete translation, but can be considered good-enough
|
||||||
|
for Yang use-cases as defined by openconfig and yang-models
|
||||||
|
for example.";
|
||||||
|
}
|
||||||
|
enum libxml2 {
|
||||||
|
description
|
||||||
|
"Use libxml2 XSD XML Schema regexp engine. This is a complete
|
||||||
|
XSD regexp engine..
|
||||||
|
Requires libxml2 to be available at configure time
|
||||||
|
(HAVE_LIBXML2 should be set)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typedef priv_mode{
|
||||||
|
description
|
||||||
|
"Privilege mode, used for dropping (or not) priveleges to a non-provileged
|
||||||
|
user after initialization";
|
||||||
|
type enumeration{
|
||||||
|
enum none {
|
||||||
|
description
|
||||||
|
"Make no drop/change in privileges.";
|
||||||
|
}
|
||||||
|
enum drop_perm {
|
||||||
|
description
|
||||||
|
"After initialization, drop privileges permanently to a uid";
|
||||||
|
}
|
||||||
|
enum drop_temp {
|
||||||
|
description
|
||||||
|
"After initialization, drop privileges temporarily to a euid";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typedef nacm_cred_mode{
|
||||||
|
description
|
||||||
|
"How NACM user should be matched with unix socket peer credentials.
|
||||||
|
This means nacm user must match socket peer user accessing the
|
||||||
|
backend socket. For IP sockets only mode none makes sense.";
|
||||||
|
type enumeration{
|
||||||
|
enum none {
|
||||||
|
description
|
||||||
|
"Dont match NACM user to any user credentials. Any user can pose
|
||||||
|
as any other user. Set this for IP sockets, or dont use NACM.";
|
||||||
|
}
|
||||||
|
enum exact {
|
||||||
|
description
|
||||||
|
"Exact match between NACM user and unix socket peer user.";
|
||||||
|
}
|
||||||
|
enum except {
|
||||||
|
description
|
||||||
|
"Exact match between NACM user and unix socket peer user, except
|
||||||
|
for root and www user (restconf).";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
container clixon-config {
|
||||||
|
leaf-list CLICON_FEATURE {
|
||||||
|
description
|
||||||
|
"Supported features as used by YANG feature/if-feature
|
||||||
|
value is: <module>:<feature>, where <module> and <feature>
|
||||||
|
are either names, or the special character '*'.
|
||||||
|
*:* means enable all features
|
||||||
|
<module>:* means enable all features in the specified module
|
||||||
|
*:<feature> means enable the specific feature in all modules";
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf-list CLICON_YANG_DIR {
|
||||||
|
ordered-by user;
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Yang directory path for finding module and submodule files.
|
||||||
|
A list of these options should be in the configuration.
|
||||||
|
When loading a Yang module, Clixon searches this list in the order
|
||||||
|
they appear. Ensure that YANG_INSTALLDIR(default
|
||||||
|
/usr/local/share/clixon) is present in the path";
|
||||||
|
}
|
||||||
|
leaf CLICON_CONFIGFILE{
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Location of the main configuration-file.
|
||||||
|
Default is CLIXON_DEFAULT_CONFIG=/usr/local/etc/clicon.xml set in configure.
|
||||||
|
Note that due to bootstrapping, this value is not actually read from file
|
||||||
|
and therefore a default value would be meaningless.";
|
||||||
|
}
|
||||||
|
leaf CLICON_CONFIGDIR{
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Location of directory of extra configuration files.
|
||||||
|
If not given, only main configfile is read.
|
||||||
|
If given, and if the directory exists, all files in this directory will be loaded
|
||||||
|
AFTER the main config file (CLICON_CONFIGFILE) in the following way:
|
||||||
|
- leaf values are overwritten
|
||||||
|
- leaf-list values are appended
|
||||||
|
The files in this directory will be loaded alphabetically.
|
||||||
|
If the dir is given but does not exist will result in an error.
|
||||||
|
You can override file setting with -E <dir> command-line option.
|
||||||
|
Note that due to bootstraping this value is only meaningful in the main config file";
|
||||||
|
}
|
||||||
|
leaf CLICON_YANG_MAIN_FILE {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"If specified load a yang module in a specific absolute filename.
|
||||||
|
This corresponds to the -y command-line option in most CLixon
|
||||||
|
programs.";
|
||||||
|
}
|
||||||
|
leaf CLICON_YANG_MAIN_DIR {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"If given, load all modules in this directory (all .yang files)
|
||||||
|
See also CLICON_YANG_DIR which specifies a path of dirs";
|
||||||
|
}
|
||||||
|
leaf CLICON_YANG_MODULE_MAIN {
|
||||||
|
type string;
|
||||||
|
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>].
|
||||||
|
Used together with CLICON_YANG_MODULE_MAIN";
|
||||||
|
}
|
||||||
|
leaf CLICON_YANG_REGEXP {
|
||||||
|
type regexp_mode;
|
||||||
|
default posix;
|
||||||
|
description
|
||||||
|
"The regular expression engine Clixon uses in its validation of
|
||||||
|
Yang patterns, and in the CLI.
|
||||||
|
There is a 'good-enough' posix translation mode and a complete
|
||||||
|
libxml2 mode";
|
||||||
|
}
|
||||||
|
leaf CLICON_YANG_LIST_CHECK {
|
||||||
|
type boolean;
|
||||||
|
default true;
|
||||||
|
description
|
||||||
|
"If false, skip Yang list check sanity checks from RFC 7950, Sec 7.8.2:
|
||||||
|
The 'key' statement, which MUST be present if the list represents configuration.
|
||||||
|
Some yang specs seem not to fulfil this. However, if you reset this, there may
|
||||||
|
be follow-up errors due to code that assumes a configuration list has keys";
|
||||||
|
}
|
||||||
|
leaf CLICON_YANG_UNKNOWN_ANYDATA{
|
||||||
|
type boolean;
|
||||||
|
default false;
|
||||||
|
description
|
||||||
|
"Treat unknown XML/JSON nodes as anydata when loading from startup db.
|
||||||
|
This does not apply to namespaces, which means a top-level node: xxx:yyy
|
||||||
|
is accepted only if yyy is unknown, not xxx.
|
||||||
|
Note that this option has several caveats which needs to be fixed. Please
|
||||||
|
use with care.
|
||||||
|
The primary issue is that the unknown->anydata handling is not restricted to
|
||||||
|
only loading from startup but may occur in other circumstances as well. This
|
||||||
|
means that sanity checks of erroneous XML/JSON may not be properly signalled.";
|
||||||
|
}
|
||||||
|
leaf CLICON_BACKEND_DIR {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Location of backend .so plugins. Load all .so
|
||||||
|
plugins in this dir as backend plugins";
|
||||||
|
}
|
||||||
|
leaf CLICON_BACKEND_REGEXP {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Regexp of matching backend plugins in CLICON_BACKEND_DIR";
|
||||||
|
default "(.so)$";
|
||||||
|
}
|
||||||
|
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_RESTCONF_PRETTY {
|
||||||
|
type boolean;
|
||||||
|
default true;
|
||||||
|
description
|
||||||
|
"Restconf return value pretty print.
|
||||||
|
Restconf clients may add HTTP header:
|
||||||
|
Accept: application/yang-data+json, or
|
||||||
|
Accept: application/yang-data+xml
|
||||||
|
to get return value in XML or JSON.
|
||||||
|
RFC 8040 examples print XML and JSON in pretty-printed form.
|
||||||
|
Setting this value to false makes restconf return not pretty-printed
|
||||||
|
which may be desirable for performance or tests";
|
||||||
|
}
|
||||||
|
leaf CLICON_RESTCONF_IPV4_ADDR {
|
||||||
|
type string;
|
||||||
|
default "0.0.0.0";
|
||||||
|
description
|
||||||
|
"RESTCONF IPv4 socket binding address.
|
||||||
|
Applies to native http by config option --with-restconf=evhtp.";
|
||||||
|
}
|
||||||
|
leaf CLICON_RESTCONF_IPV6_ADDR {
|
||||||
|
type string;
|
||||||
|
default "::";
|
||||||
|
description
|
||||||
|
"RESTCONF IPv6 socket binding address.
|
||||||
|
Applies to native http by config option --with-restconf=evhtp.";
|
||||||
|
}
|
||||||
|
leaf CLICON_RESTCONF_HTTP_PORT {
|
||||||
|
type uint16;
|
||||||
|
default 80;
|
||||||
|
description
|
||||||
|
"RESTCONF socket binding port, non-ssl
|
||||||
|
In the restconf daemon, it can be overriden by -P <port>
|
||||||
|
Applies to native http only by config option --with-restconf=evhtp.";
|
||||||
|
}
|
||||||
|
leaf CLICON_RESTCONF_HTTPS_PORT {
|
||||||
|
type uint16;
|
||||||
|
default 443;
|
||||||
|
description
|
||||||
|
"RESTCONF socket binding port, ssl
|
||||||
|
In the restconf daemon, this is the port chosen if -s is given.
|
||||||
|
Note it can be overriden by -P <port>
|
||||||
|
Applies to native http by config option --with-restconf=evhtp.";
|
||||||
|
}
|
||||||
|
leaf CLICON_SSL_SERVER_CERT {
|
||||||
|
type string;
|
||||||
|
default "/etc/ssl/certs/clixon-server-crt.pem";
|
||||||
|
description
|
||||||
|
"SSL server cert for restconf https.
|
||||||
|
Applies to native http only by config option --with-restconf=evhtp.";
|
||||||
|
}
|
||||||
|
leaf CLICON_SSL_SERVER_KEY {
|
||||||
|
type string;
|
||||||
|
default "/etc/ssl/private/clixon-server-key.pem";
|
||||||
|
description
|
||||||
|
"SSL server private key for restconf https.
|
||||||
|
Applies to native http only by config option --with-restconf=evhtp.";
|
||||||
|
}
|
||||||
|
leaf CLICON_SSL_CA_CERT {
|
||||||
|
type string;
|
||||||
|
default "/etc/ssl/certs/clixon-ca_crt.pem";
|
||||||
|
description
|
||||||
|
"SSL CA cert for client authentication.
|
||||||
|
Applies to native http only by config option --with-restconf=evhtp.";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_DIR {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Directory containing frontend cli loadable plugins. Load all .so
|
||||||
|
plugins in this directory as CLI object plugins";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLISPEC_DIR {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Directory containing frontend cligen spec files. Load all .cli
|
||||||
|
files in this directory as CLI specification files.
|
||||||
|
See also CLICON_CLISPEC_FILE.";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLISPEC_FILE {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"Specific frontend cligen spec file as aletrnative or complement
|
||||||
|
to CLICON_CLISPEC_DIR. Also available as -c in clixon_cli.";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_MODE {
|
||||||
|
type string;
|
||||||
|
default "base";
|
||||||
|
description
|
||||||
|
"Startup CLI mode. This should match a CLICON_MODE variable set in
|
||||||
|
one of the clispec files";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_GENMODEL {
|
||||||
|
type int32;
|
||||||
|
default 1;
|
||||||
|
description
|
||||||
|
"0: Do not generate CLISPEC syntax for the auto-cli.
|
||||||
|
1: Generate a CLI specification for CLI completion of all loaded Yang modules.
|
||||||
|
This CLI tree can be accessed in CLI-spec files using the tree reference syntax (eg
|
||||||
|
@datamodel).
|
||||||
|
2: Same including state syntax in a tree called @datamodelstate.
|
||||||
|
See also CLICON_CLI_MODEL_TREENAME.";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_MODEL_TREENAME {
|
||||||
|
type string;
|
||||||
|
default "datamodel";
|
||||||
|
description
|
||||||
|
"If set, CLI specs can reference the
|
||||||
|
model syntax using this reference.
|
||||||
|
Example: set @datamodel, cli_set();
|
||||||
|
A second tree called eg @datamodelstate is created that
|
||||||
|
also contains state together with config.";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_GENMODEL_COMPLETION {
|
||||||
|
type int32;
|
||||||
|
default 1;
|
||||||
|
description "Generate code for CLI completion of existing db symbols.
|
||||||
|
(consider boolean)";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_GENMODEL_TYPE {
|
||||||
|
type cli_genmodel_type;
|
||||||
|
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
|
||||||
|
(consider boolean)";
|
||||||
|
}
|
||||||
|
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_CLI_LINES_DEFAULT {
|
||||||
|
type int32;
|
||||||
|
default 24;
|
||||||
|
description
|
||||||
|
"Set to number of CLI terminal rows for pageing/scrolling. 0 means unlimited.
|
||||||
|
The number is set statically UNLESS:
|
||||||
|
- there is no terminal, such as file input, in which case nr lines is 0
|
||||||
|
- there is a terminal sufficiently powerful to read the number of lines from
|
||||||
|
ioctl calls.
|
||||||
|
In other words, this setting is used ONLY on raw terminals such as serial
|
||||||
|
consoles.";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_TAB_MODE {
|
||||||
|
type int8;
|
||||||
|
default 0;
|
||||||
|
description
|
||||||
|
"Set CLI tab mode. This is actually a bitfield of three
|
||||||
|
combinations:
|
||||||
|
bit 1: 0: <tab> shows short info of available commands
|
||||||
|
1: <tab> has same output as <?>, ie line per command
|
||||||
|
bit 2: 0: On <tab>, select a command over a <var> if both exist
|
||||||
|
1: Commands and vars have same preference.
|
||||||
|
bit 3: 0: On <tab>, never complete more than one level per <tab>
|
||||||
|
1: Complete all levels at once if possible.
|
||||||
|
";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_UTF8 {
|
||||||
|
type int8;
|
||||||
|
default 0;
|
||||||
|
description
|
||||||
|
"Set to 1 to enable CLIgen UTF-8 experimental mode.
|
||||||
|
Note that this feature is EXPERIMENTAL and may not properly handle
|
||||||
|
scrolling, control characters, etc
|
||||||
|
(consider boolean)";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_HIST_FILE {
|
||||||
|
type string;
|
||||||
|
default "~/.clixon_cli_history";
|
||||||
|
description
|
||||||
|
"Name of CLI history file. If not given, history is not saved.
|
||||||
|
The number of lines is saved is given by CLICON_CLI_HIST_SIZE.";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_HIST_SIZE {
|
||||||
|
type int32;
|
||||||
|
default 300;
|
||||||
|
description
|
||||||
|
"Number of lines to save in CLI history.
|
||||||
|
Also, if CLICON_CLI_HIST_FILE is set, also the size in lines
|
||||||
|
of the saved history.";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_BUF_START {
|
||||||
|
type uint32;
|
||||||
|
default 256;
|
||||||
|
description
|
||||||
|
"CLIgen buffer (cbuf) initial size.
|
||||||
|
When the buffer needs to grow, the allocation grows quadratic up to a threshold
|
||||||
|
after which linear growth continues.
|
||||||
|
See CLICON_CLI_BUF_THRESHOLD";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_BUF_THRESHOLD {
|
||||||
|
type uint32;
|
||||||
|
default 65536;
|
||||||
|
description
|
||||||
|
"CLIgen buffer (cbuf) threshold size.
|
||||||
|
When the buffer exceeds the threshold, the allocation grows by adding the threshold
|
||||||
|
value to the buffer length.
|
||||||
|
If 0, the growth continues with quadratic growth.
|
||||||
|
See CLICON_CLI_BUF_THRESHOLD";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_HELPSTRING_TRUNCATE {
|
||||||
|
type boolean;
|
||||||
|
default false;
|
||||||
|
description
|
||||||
|
"CLIgen help string on query (?): Truncate help string on right margin mode
|
||||||
|
This only applies if you have long help strings, such as when generating them from a
|
||||||
|
spec such as the autocli";
|
||||||
|
}
|
||||||
|
leaf CLICON_CLI_HELPSTRING_LINES {
|
||||||
|
type int32;
|
||||||
|
default 0;
|
||||||
|
description
|
||||||
|
"CLIgen help string on query (?) limit of number of lines to show, 0 means unlimited.
|
||||||
|
This only applies if you have multi-line help strings, such as when generating
|
||||||
|
from a spec, such as in the autocli.";
|
||||||
|
}
|
||||||
|
leaf CLICON_SOCK_FAMILY {
|
||||||
|
type string;
|
||||||
|
default "UNIX";
|
||||||
|
description
|
||||||
|
"Address family for communicating with clixon_backend
|
||||||
|
(UNIX|IPv4). IPv6 not yet implemented.
|
||||||
|
Note that UNIX socket makes credential check as follows:
|
||||||
|
(1) client needs rw access to the socket
|
||||||
|
(2) NACM credentials can be checked according to CLICON_NACM_CREDENTIALS
|
||||||
|
Warning: IPv4 and IPv6 sockets have no credential mechanism.
|
||||||
|
";
|
||||||
|
}
|
||||||
|
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 and gid for
|
||||||
|
deamon";
|
||||||
|
}
|
||||||
|
leaf CLICON_BACKEND_USER {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"User name for backend (both foreground and daemonized).
|
||||||
|
If you set this value the backend if started as root will lower
|
||||||
|
the privileges after initialization.
|
||||||
|
The ownership of files created by the backend will also be set to this
|
||||||
|
user (eg datastores).
|
||||||
|
It also sets the backend unix socket owner to this user, but its group
|
||||||
|
is set by CLICON_SOCK_GROUP.
|
||||||
|
See also CLICON_PRIVILEGES setting";
|
||||||
|
}
|
||||||
|
leaf CLICON_BACKEND_PRIVILEGES {
|
||||||
|
type priv_mode;
|
||||||
|
default none;
|
||||||
|
description
|
||||||
|
"Backend privileges mode.
|
||||||
|
If CLICON_BACKEND_USER user is set, mode can be set to drop_perm or
|
||||||
|
drop_temp.";
|
||||||
|
}
|
||||||
|
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
|
||||||
|
(consider boolean)";
|
||||||
|
}
|
||||||
|
leaf CLICON_XMLDB_DIR {
|
||||||
|
type string;
|
||||||
|
mandatory true;
|
||||||
|
description
|
||||||
|
"Directory where \"running\", \"candidate\" and \"startup\" are placed.";
|
||||||
|
}
|
||||||
|
leaf CLICON_DATASTORE_CACHE {
|
||||||
|
type datastore_cache;
|
||||||
|
default cache;
|
||||||
|
description
|
||||||
|
"Clixon datastore cache behaviour. There are three values: no cache,
|
||||||
|
cache with copy, or cache without copy.";
|
||||||
|
}
|
||||||
|
leaf CLICON_XMLDB_FORMAT {
|
||||||
|
type datastore_format;
|
||||||
|
default xml;
|
||||||
|
description "XMLDB datastore format.";
|
||||||
|
}
|
||||||
|
leaf CLICON_XMLDB_PRETTY {
|
||||||
|
type boolean;
|
||||||
|
default true;
|
||||||
|
description
|
||||||
|
"XMLDB datastore pretty print.
|
||||||
|
If set, insert spaces and line-feeds making the XML/JSON human
|
||||||
|
readable. If not set, make the XML/JSON more compact.";
|
||||||
|
}
|
||||||
|
leaf CLICON_XMLDB_MODSTATE {
|
||||||
|
type boolean;
|
||||||
|
default false;
|
||||||
|
description
|
||||||
|
"If set, tag datastores with RFC 7895 YANG Module Library
|
||||||
|
info. When loaded at startup, a check is made if the system
|
||||||
|
yang modules match.
|
||||||
|
See also CLICON_MODULE_LIBRARY_RFC7895";
|
||||||
|
}
|
||||||
|
leaf CLICON_XML_CHANGELOG {
|
||||||
|
type boolean;
|
||||||
|
default false;
|
||||||
|
description "If true enable automatic upgrade using yang clixon
|
||||||
|
changelog.";
|
||||||
|
}
|
||||||
|
leaf CLICON_XML_CHANGELOG_FILE {
|
||||||
|
type string;
|
||||||
|
description "Name of file with module revision changelog.
|
||||||
|
If CLICON_XML_CHANGELOG is true, Clixon
|
||||||
|
reads the module changelog from this file.";
|
||||||
|
}
|
||||||
|
leaf CLICON_VALIDATE_STATE_XML {
|
||||||
|
type boolean;
|
||||||
|
default false;
|
||||||
|
description
|
||||||
|
"Validate user state callback content.
|
||||||
|
Users may register state callbacks using ca_statedata callback
|
||||||
|
When set, the XML returned from the callback is validated after merging with
|
||||||
|
the running db. If it fails, an internal error is returned to the originating
|
||||||
|
user.
|
||||||
|
If the option is not set, the XML returned by the user is not validated.
|
||||||
|
Note that enabling currently causes a large performance overhead for large
|
||||||
|
lists, therefore it is recommended to enable it during development and debugging
|
||||||
|
but disable it in production, until this has been resolved.";
|
||||||
|
}
|
||||||
|
leaf CLICON_NAMESPACE_NETCONF_DEFAULT {
|
||||||
|
type boolean;
|
||||||
|
default false;
|
||||||
|
description
|
||||||
|
"Undefine if you want to ensure strict namespace assignment on all netconf
|
||||||
|
and XML statements according to the standard RFC 6241.
|
||||||
|
If defined, top-level rpc calls need not have namespaces (eg using xmlns=<ns>)
|
||||||
|
since the default NETCONF namespace will be assumed. (This is not standard).
|
||||||
|
See rfc6241 3.1: urn:ietf:params:xml:ns:netconf:base:1.0.";
|
||||||
|
|
||||||
|
}
|
||||||
|
leaf CLICON_STARTUP_MODE {
|
||||||
|
type startup_mode;
|
||||||
|
description "Which method to boot/start clicon backend";
|
||||||
|
}
|
||||||
|
leaf CLICON_TRANSACTION_MOD {
|
||||||
|
type boolean;
|
||||||
|
default false;
|
||||||
|
description "If set, modifications in validation and commit
|
||||||
|
callbacks are written back into the datastore.
|
||||||
|
This is a bad idea and therefore obsoleted.";
|
||||||
|
status obsolete;
|
||||||
|
}
|
||||||
|
leaf CLICON_NACM_MODE {
|
||||||
|
type nacm_mode;
|
||||||
|
default disabled;
|
||||||
|
description
|
||||||
|
"RFC8341 network access configuration control model (NACM) mode: disabled,
|
||||||
|
in regular (internal) config or separate external file given by CLICON_NACM_FILE";
|
||||||
|
}
|
||||||
|
leaf CLICON_NACM_FILE {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"RFC8341 NACM external configuration file (if CLIXON_NACM_MODE is external)";
|
||||||
|
}
|
||||||
|
leaf CLICON_NACM_CREDENTIALS {
|
||||||
|
type nacm_cred_mode;
|
||||||
|
default except;
|
||||||
|
description
|
||||||
|
"Verify nacm user credentials with unix socket peer cred.
|
||||||
|
This means nacm user must match unix user accessing the backend
|
||||||
|
socket.";
|
||||||
|
}
|
||||||
|
leaf CLICON_NACM_RECOVERY_USER {
|
||||||
|
type string;
|
||||||
|
description
|
||||||
|
"RFC8341 defines a 'recovery session' as outside its scope. Clixon
|
||||||
|
defines this user as having special admin rights to exempt from
|
||||||
|
all access control enforcements.
|
||||||
|
Note setting of CLICON_NACM_CREDENTIALS is important, if set to
|
||||||
|
exact for example, this user must exist and be used, otherwise
|
||||||
|
another user (such as root or www) can pose as the recovery user.";
|
||||||
|
}
|
||||||
|
leaf CLICON_NACM_DISABLED_ON_EMPTY {
|
||||||
|
type boolean;
|
||||||
|
default false;
|
||||||
|
description
|
||||||
|
"RFC 8341 and ietf-netconf-acm@2018-02-14.yang defines enable-nacm as true by
|
||||||
|
default. Since also write-default is deny by default it leads to that empty
|
||||||
|
configs can not be edited.
|
||||||
|
This means that a startup config must always have a NACM configuration or
|
||||||
|
that the NACM recovery session is used to edit an empty config.
|
||||||
|
If this option is set, Clixon disables NACM if a datastore does NOT contain a
|
||||||
|
NACM config on load.";
|
||||||
|
}
|
||||||
|
leaf CLICON_MODULE_LIBRARY_RFC7895 {
|
||||||
|
type boolean;
|
||||||
|
default true;
|
||||||
|
description
|
||||||
|
"Enable RFC 7895 YANG Module library support as state data. If
|
||||||
|
enabled, module info will appear when doing netconf get or
|
||||||
|
restconf GET.
|
||||||
|
See also CLICON_XMLDB_MODSTATE";
|
||||||
|
}
|
||||||
|
leaf CLICON_MODULE_SET_ID {
|
||||||
|
type string;
|
||||||
|
default "0";
|
||||||
|
description "If RFC 7895 YANG Module library enabled:
|
||||||
|
Contains a server-specific identifier representing
|
||||||
|
the current set of modules and submodules. The
|
||||||
|
server MUST change the value of this leaf if the
|
||||||
|
information represented by the 'module' list instances
|
||||||
|
has changed.";
|
||||||
|
}
|
||||||
|
leaf CLICON_STREAM_DISCOVERY_RFC5277 {
|
||||||
|
type boolean;
|
||||||
|
default false;
|
||||||
|
description "Enable event stream discovery as described in RFC 5277
|
||||||
|
sections 3.2. If enabled, available streams will appear
|
||||||
|
when doing netconf get or restconf GET";
|
||||||
|
}
|
||||||
|
leaf CLICON_STREAM_DISCOVERY_RFC8040 {
|
||||||
|
type boolean;
|
||||||
|
default false;
|
||||||
|
description
|
||||||
|
"Enable monitoring information for the RESTCONF protocol from RFC 8040";
|
||||||
|
}
|
||||||
|
leaf CLICON_STREAM_PATH {
|
||||||
|
type string;
|
||||||
|
default "streams";
|
||||||
|
description "Stream path appended to CLICON_STREAM_URL to form
|
||||||
|
stream subscription URL.";
|
||||||
|
}
|
||||||
|
leaf CLICON_STREAM_URL {
|
||||||
|
type string;
|
||||||
|
default "https://localhost";
|
||||||
|
description "Prepend this to CLICON_STREAM_PATH to form URL.
|
||||||
|
See RFC 8040 Sec 9.3 location leaf:
|
||||||
|
'Contains a URL that represents the entry point for
|
||||||
|
establishing notification delivery via server-sent events.'
|
||||||
|
Prepend this constant to name of stream.
|
||||||
|
Example: https://localhost/streams/NETCONF. Note this is the
|
||||||
|
external URL, not local behind a reverse-proxy.
|
||||||
|
Note that -s <stream> command-line option to clixon_restconf
|
||||||
|
should correspond to last path of url (eg 'streams')";
|
||||||
|
}
|
||||||
|
leaf CLICON_STREAM_PUB {
|
||||||
|
type string;
|
||||||
|
description "For stream publish using eg nchan, the base address
|
||||||
|
to publish to. Example value: http://localhost/pub
|
||||||
|
Example: stream NETCONF would then be pushed to
|
||||||
|
http://localhost/pub/NETCONF.
|
||||||
|
Note this may be a local/provate URL behind reverse-proxy.
|
||||||
|
If not given, do NOT enable stream publishing using NCHAN.";
|
||||||
|
}
|
||||||
|
leaf CLICON_STREAM_RETENTION {
|
||||||
|
type uint32;
|
||||||
|
default 3600;
|
||||||
|
units s;
|
||||||
|
description "Retention for stream replay buffers in seconds, ie how much
|
||||||
|
data to store before dropping. 0 means no retention";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue