Migrated to XML configure file.

This commit is contained in:
Olof hagsand 2017-10-01 12:33:12 +02:00
parent a2bfe2bdd2
commit ca7b4d3d9e
12 changed files with 117 additions and 54 deletions

View file

@ -11,8 +11,15 @@ Sep 27 18:11:58: Commit failed. Edit and try again or discard changes:
protocol invalid-value Missing mandatory variable: type protocol invalid-value Missing mandatory variable: type
``` ```
* If clixon config file has .xml ending, yang/clixon-config.yang is used as * Migrated to XML configure file.
** If clixon config file has .xml ending, yang/clixon-config.yang is used as
model for an xml-based configuration file. Otherwise legacy format is used. model for an xml-based configuration file. Otherwise legacy format is used.
** As migration utility from legacy to XML configure file, clixon_cli -x can be used to print new format, eg:
```
clixon_cli -f /usr/local/etc/routing.conf -1x
```
* The clixon config file format has changed. It now uses XML and YANG. * The clixon config file format has changed. It now uses XML and YANG.
Old configuration files work, but you can use the new by setting an .xml suffix. Old configuration files work, but you can use the new by setting an .xml suffix.
The yang model is yang/clixon-config.yang. The yang model is yang/clixon-config.yang.

View file

@ -70,7 +70,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:F:1u:d:m:qpGLl:y:" #define CLI_OPTS "hD:f:F:1u:d:m:qpGLl:y:x"
/*! terminate cli application */ /*! terminate cli application */
static int static int
@ -109,9 +109,10 @@ cli_signal_init (clicon_handle h)
* @param[in] h CLICON handle * @param[in] h CLICON handle
* @see cligen_loop * @see cligen_loop
*/ */
static void static int
cli_interactive(clicon_handle h) cli_interactive(clicon_handle h)
{ {
int retval = -1;
int res; int res;
char *cmd; char *cmd;
char *new_mode; char *new_mode;
@ -123,11 +124,72 @@ cli_interactive(clicon_handle h)
new_mode = cli_syntax_mode(h); new_mode = cli_syntax_mode(h);
if ((cmd = clicon_cliread(h)) == NULL) { if ((cmd = clicon_cliread(h)) == NULL) {
cli_set_exiting(h, 1); /* EOF */ cli_set_exiting(h, 1); /* EOF */
break; retval = -1;
goto done;
} }
if ((res = clicon_parse(h, cmd, &new_mode, &result)) < 0) if ((res = clicon_parse(h, cmd, &new_mode, &result)) < 0)
break; goto done;
} }
retval = 0;
done:
return retval;
}
/*! Read file as configuration file and print xml file for migrating to new fmt
* @see clicon_option_readfile_xml
*/
static int
dump_configfile_xml_fn(FILE *fout,
const char *filename)
{
struct stat st;
char opt[1024];
char val[1024];
char line[1024];
char *cp;
FILE *f = NULL;
int retval = -1;
char *suffix;
if (filename == NULL || !strlen(filename)){
clicon_err(OE_UNIX, 0, "Not specified");
goto done;
}
if ((suffix = rindex(filename, '.')) != NULL &&
strcmp((suffix+1), "xml") == 0){
clicon_err(OE_CFG, 0, "Configfile %s should not be XML", 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;
}
clicon_debug(2, "Reading config file %s", __FUNCTION__, filename);
fprintf(fout, "<config>\n");
while (fgets(line, sizeof(line), f)) {
if ((cp = strchr(line, '\n')) != NULL) /* strip last \n */
*cp = '\0';
/* Trim out comments, strip whitespace, and remove CR */
if ((cp = strchr(line, '#')) != NULL)
memcpy(cp, "\n", 2);
if (sscanf(line, "%s %s", opt, val) < 2)
continue;
fprintf(fout, "\t<%s>%s</%s>\n", opt, val, opt);
}
fprintf(fout, "</config>\n");
retval = 0;
done:
if (f)
fclose(f);
return retval;
} }
static void static void
@ -142,6 +204,7 @@ usage(char *argv0, clicon_handle h)
"\t-h \t\tHelp\n" "\t-h \t\tHelp\n"
"\t-D <level> \tDebug\n" "\t-D <level> \tDebug\n"
"\t-f <file> \tConfig-file (mandatory)\n" "\t-f <file> \tConfig-file (mandatory)\n"
"\t-x\t\tDump configuration file as XML on stdout (migration utility)\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-u <sockpath>\tconfig UNIX domain path (default: %s)\n" "\t-u <sockpath>\tconfig UNIX domain path (default: %s)\n"
@ -178,6 +241,7 @@ main(int argc, char **argv)
int len; int len;
int logdst = CLICON_LOG_STDERR; int logdst = CLICON_LOG_STDERR;
char *restarg = NULL; /* what remains after options */ char *restarg = NULL; /* what remains after options */
int dump_configfile_xml = 0;
/* Defaults */ /* Defaults */
@ -216,6 +280,9 @@ main(int argc, char **argv)
usage(argv[0], h); usage(argv[0], h);
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg); clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
break; break;
case 'x': /* dump config file as xml */
dump_configfile_xml++;
break;
case 'l': /* Log destination: s|e|o */ case 'l': /* Log destination: s|e|o */
switch (optarg[0]){ switch (optarg[0]){
case 's': case 's':
@ -239,6 +306,14 @@ main(int argc, char **argv)
clicon_debug_init(debug, NULL); clicon_debug_init(debug, NULL);
/* Use cli as util tool to dump config file as xml for migration */
if (dump_configfile_xml) {
clicon_hash_t *copt = clicon_options(h);
char *configfile = hash_value(copt, "CLICON_CONFIGFILE", NULL);
if (dump_configfile_xml_fn(stdout, configfile) < 0)
goto done;
}
/* Find and read configfile */ /* Find and read configfile */
if (clicon_options_main(h) < 0){ if (clicon_options_main(h) < 0){
if (help) if (help)
@ -254,6 +329,7 @@ main(int argc, char **argv)
case 'D' : /* debug */ case 'D' : /* debug */
case 'f': /* config file */ case 'f': /* config file */
case 'l': /* Log destination */ case 'l': /* Log destination */
case 'x': /* dump config file as xml */
break; /* see above */ break; /* see above */
case 'F': /* read commands from file */ case 'F': /* read commands from file */
if (freopen(optarg, "r", stdin) == NULL){ if (freopen(optarg, "r", stdin) == NULL){
@ -326,7 +402,9 @@ main(int argc, char **argv)
goto done; goto done;
} }
/* Create tree generated from dataspec */ /* Create tree generated from dataspec. If no other trees exists, this is
* the only one.
*/
if (clicon_cli_genmodel(h)){ if (clicon_cli_genmodel(h)){
yang_spec *yspec; /* yang spec */ yang_spec *yspec; /* yang spec */
parse_tree pt = {0,}; /* cli parse tree */ parse_tree pt = {0,}; /* cli parse tree */
@ -367,10 +445,8 @@ main(int argc, char **argv)
fprintf (stderr, "FATAL: No cli mode set (use -m or CLICON_CLI_MODE)\n"); fprintf (stderr, "FATAL: No cli mode set (use -m or CLICON_CLI_MODE)\n");
goto done; goto done;
} }
if (cli_tree(h, cli_syntax_mode(h)) == NULL){ if (cli_tree(h, cli_syntax_mode(h)) == NULL)
fprintf (stderr, "FATAL: No such cli mode: %s\n", cli_syntax_mode(h)); clicon_log(LOG_WARNING, "No such cli mode: %s (Specify cli mode with CLICON_CLI_MODE in config file or -m <mode> on command line", cli_syntax_mode(h));
goto done;
}
if (logclisyntax) if (logclisyntax)
cli_logsyntax_set(h, logclisyntax); cli_logsyntax_set(h, logclisyntax);

View file

@ -713,8 +713,9 @@ done:
return res; return res;
} }
/* /*! Read command from CLIgen's cliread() using current syntax mode.
* Read command from CLIgen's cliread() using current syntax mode. * @retval string char* buffer containing CLIgen command
* @retval NULL Fatal error
*/ */
char * char *
clicon_cliread(clicon_handle h) clicon_cliread(clicon_handle h)

View file

@ -105,7 +105,7 @@ CLICON_BACKEND_PIDFILE localstatedir/APPNAME/APPNAME.pidfile
# CLICON_CLI_GENMODEL 1 # CLICON_CLI_GENMODEL 1
# Generate code for CLI completion of existing db symbols # Generate code for CLI completion of existing db symbols
# CLICON_CLI_GENMODEL_COMPLETION 0 # CLICON_CLI_GENMODEL_COMPLETION 1
# How to generate and show CLI syntax: VARS|ALL # How to generate and show CLI syntax: VARS|ALL
# CLICON_CLI_GENMODEL_TYPE VARS # CLICON_CLI_GENMODEL_TYPE VARS

View file

@ -12,21 +12,6 @@ CLICON_YANG_MODULE_MAIN example
# <module>[@<revision>] # <module>[@<revision>]
#CLICON_YANG_MODULE_REVISION 2014-06-16 #CLICON_YANG_MODULE_REVISION 2014-06-16
# Generate code for CLI completion of existing db symbols
# CLICON_CLI_GENMODEL_COMPLETION 0
CLICON_CLI_GENMODEL_COMPLETION 1
# How to generate and show CLI syntax: VARS|ALL
# CLICON_CLI_GENMODEL_TYPE VARS
CLICON_CLI_GENMODEL_TYPE VARS
# Enabled uses "startup" configuration on boot
CLICON_USE_STARTUP_CONFIG 0
# XMLDB datastore plugin filename (see datastore/ and clixon_xml_db.[ch])
CLICON_XMLDB_PLUGIN /usr/local/lib/xmldb/text.so
#CLICON_XMLDB_PLUGIN /usr/local/lib/xmldb/keyvalue.so
# Set to 0 if you want CLI to wrap to next line. # 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 # Set to 1 if you want CLI to scroll sideways when approaching right margin
CLICON_CLI_LINESCROLLING 0 CLICON_CLI_LINESCROLLING 0

View file

@ -3,7 +3,7 @@
<CLICON_YANG_DIR>/usr/local/share/routing/yang</CLICON_YANG_DIR> <CLICON_YANG_DIR>/usr/local/share/routing/yang</CLICON_YANG_DIR>
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN> <CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
<CLICON_CLI_MODE>routing</CLICON_CLI_MODE> <CLICON_CLI_MODE>routing</CLICON_CLI_MODE>
<CLICON_BACKEND_DIR>/usr/local/lib/routing/backend></CLICON_BACKEND_DIR> <CLICON_BACKEND_DIR>/usr/local/lib/routing/backend</CLICON_BACKEND_DIR>
<CLICON_NETCONF_DIR>/usr/local/lib/routing/netconf</CLICON_NETCONF_DIR> <CLICON_NETCONF_DIR>/usr/local/lib/routing/netconf</CLICON_NETCONF_DIR>
<CLICON_RESTCONF_DIR>/usr/local/lib/routing/restconf</CLICON_RESTCONF_DIR> <CLICON_RESTCONF_DIR>/usr/local/lib/routing/restconf</CLICON_RESTCONF_DIR>
<CLICON_CLI_DIR>/usr/local/lib/routing/cli</CLICON_CLI_DIR> <CLICON_CLI_DIR>/usr/local/lib/routing/cli</CLICON_CLI_DIR>

View file

@ -69,12 +69,11 @@
#include "clixon_xsl.h" #include "clixon_xsl.h"
#include "clixon_xml_map.h" #include "clixon_xml_map.h"
/* /*! Print registry on file. For debugging.
* clicon_option_dump
* Print registry on file. For debugging.
*/ */
void void
clicon_option_dump(clicon_handle h, int dbglevel) clicon_option_dump(clicon_handle h,
int dbglevel)
{ {
clicon_hash_t *hash = clicon_options(h); clicon_hash_t *hash = clicon_options(h);
int i; int i;
@ -272,7 +271,7 @@ clicon_option_default(clicon_hash_t *copt)
goto done; goto done;
} }
if (!hash_lookup(copt, "CLICON_CLI_GENMODEL_COMPLETION")){ if (!hash_lookup(copt, "CLICON_CLI_GENMODEL_COMPLETION")){
if (hash_add(copt, "CLICON_CLI_GENMODEL_COMPLETION", "0", strlen("0")+1) < 0) if (hash_add(copt, "CLICON_CLI_GENMODEL_COMPLETION", "1", strlen("1")+1) < 0)
goto done; goto done;
} }
/* Default is to use line-scrolling */ /* Default is to use line-scrolling */
@ -280,18 +279,12 @@ clicon_option_default(clicon_hash_t *copt)
if (hash_add(copt, "CLICON_CLI_LINESCROLLING", "1", strlen("1")+1) < 0) if (hash_add(copt, "CLICON_CLI_LINESCROLLING", "1", strlen("1")+1) < 0)
goto done; goto done;
} }
/* Default is to use line-scrolling */
if (!hash_lookup(copt, "CLICON_CLI_LINESCROLLING")){
if (hash_add(copt, "CLICON_CLI_LINESCROLLING", "1", strlen("1")+1) < 0)
goto done;
}
retval = 0; retval = 0;
done: done:
return retval; return retval;
} }
/*! Check that options are set /*! Check that options are set
* XXX dont detect extra XML
*/ */
static int static int
clicon_option_sanity(clicon_hash_t *copt) clicon_option_sanity(clicon_hash_t *copt)
@ -440,7 +433,7 @@ clicon_option_str_set(clicon_handle h,
} }
/*! Get options as integer but stored as string /*! Get options as integer but stored as string
*
* @param h clicon handle * @param h clicon handle
* @param name name of option * @param name name of option
* @retval int An integer as aresult of atoi * @retval int An integer as aresult of atoi
@ -465,7 +458,7 @@ clicon_option_int(clicon_handle h, const char *name)
return atoi(s); return atoi(s);
} }
/*! set option given as int. /*! Set option given as int.
*/ */
int int
clicon_option_int_set(clicon_handle h, const char *name, int val) clicon_option_int_set(clicon_handle h, const char *name, int val)
@ -477,7 +470,7 @@ clicon_option_int_set(clicon_handle h, const char *name, int val)
return clicon_option_str_set(h, name, s); return clicon_option_str_set(h, name, s);
} }
/*! delete option /*! Delete option
*/ */
int int
clicon_option_del(clicon_handle h, const char *name) clicon_option_del(clicon_handle h, const char *name)
@ -557,7 +550,7 @@ clicon_xmldb_plugin(clicon_handle h)
return clicon_option_str(h, "CLICON_XMLDB_PLUGIN"); return clicon_option_str(h, "CLICON_XMLDB_PLUGIN");
} }
/* get family of backend socket: AF_UNIX, AF_INET or AF_INET6 */ /*! Get family of backend socket: AF_UNIX, AF_INET or AF_INET6 */
int int
clicon_sock_family(clicon_handle h) clicon_sock_family(clicon_handle h)
{ {
@ -609,7 +602,7 @@ clicon_master_plugin(clicon_handle h)
return clicon_option_str(h, "CLICON_MASTER_PLUGIN"); return clicon_option_str(h, "CLICON_MASTER_PLUGIN");
} }
/* return initial clicon cli mode */ /*! Return initial clicon cli mode */
char * char *
clicon_cli_mode(clicon_handle h) clicon_cli_mode(clicon_handle h)
{ {
@ -630,7 +623,7 @@ clicon_cli_genmodel(clicon_handle h)
return 0; return 0;
} }
/* How to generate and show CLI syntax: VARS|ALL */ /*! How to generate and show CLI syntax: VARS|ALL */
enum genmodel_type enum genmodel_type
clicon_cli_genmodel_type(clicon_handle h) clicon_cli_genmodel_type(clicon_handle h)
{ {
@ -709,7 +702,7 @@ clicon_cli_genmodel_completion(clicon_handle h)
return 0; return 0;
} }
/* Where are "running" and "candidate" databases? */ /*! Where are "running" and "candidate" databases? */
char * char *
clicon_xmldb_dir(clicon_handle h) clicon_xmldb_dir(clicon_handle h)
{ {

View file

@ -1504,7 +1504,7 @@ yang_parse_recurse(clicon_handle h,
yang_spec *ysp) yang_spec *ysp)
{ {
yang_stmt *yi = NULL; /* import */ yang_stmt *yi = NULL; /* import */
yang_stmt *ymod; yang_stmt *ymod = NULL;
yang_stmt *yrev; yang_stmt *yrev;
char *modname; char *modname;
char *subrevision; char *subrevision;
@ -1527,7 +1527,7 @@ yang_parse_recurse(clicon_handle h,
if ((nr = yang_parse_find_match(h, yang_dir, module, fbuf)) < 0) if ((nr = yang_parse_find_match(h, yang_dir, module, fbuf)) < 0)
goto done; goto done;
if (nr == 0){ if (nr == 0){
clicon_err(OE_YANG, errno, "No matching %s yang files found", module); clicon_err(OE_YANG, errno, "No matching %s yang files found (expected modulenameor absolute filename)", module);
goto done; goto done;
} }
} }

View file

@ -1,7 +1,7 @@
# Clixon tests # Clixon tests
This directory contains testing code for clixon and the example This directory contains testing code for clixon and the example
routing application: routing application. Assumes setup of http daemon as describe under apps/restonf
- clixon A top-level script clones clixon in /tmp and starts all.sh. You can copy this file (review it first) and place as cron script - clixon A top-level script clones clixon in /tmp and starts all.sh. You can copy this file (review it first) and place as cron script
- all.sh Run through all tests named 'test*.sh' in this directory. Therefore, if you place a test in this directory matching 'test*.sh' it will be run automatically. - all.sh Run through all tests named 'test*.sh' in this directory. Therefore, if you place a test in this directory matching 'test*.sh' it will be run automatically.
- test_cli.sh CLI tests - test_cli.sh CLI tests

View file

@ -2,7 +2,7 @@
testnr=0 testnr=0
testnname= testnname=
clixon_cf=/usr/local/etc/routing.conf clixon_cf=/usr/local/etc/routing.xml
# error and exit, arg is optional extra errmsg # error and exit, arg is optional extra errmsg
err(){ err(){
echo "Error in Test$testnr [$testname]:" echo "Error in Test$testnr [$testname]:"

View file

@ -1,5 +1,6 @@
#!/bin/bash #!/bin/bash
# Test3: backend and restconf basic functionality # Restconf basic functionality
# Assume http server setup, such as nginx described in apps/restconf/README.md
# include err() and new() functions # include err() and new() functions
. ./lib.sh . ./lib.sh
@ -20,7 +21,7 @@ new "kill old restconf daemon"
sudo pkill -u www-data clixon_restconf sudo pkill -u www-data clixon_restconf
new "start restconf daemon" new "start restconf daemon"
sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -Df /usr/local/etc/routing.conf # -D sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -Df /usr/local/etc/routing.xml # -D
sleep 1 sleep 1

View file

@ -146,7 +146,7 @@
} }
leaf CLICON_CLI_GENMODEL_COMPLETION { leaf CLICON_CLI_GENMODEL_COMPLETION {
type int32; type int32;
default 0; default 1;
description "Generate code for CLI completion of existing db symbols"; description "Generate code for CLI completion of existing db symbols";
} }
leaf CLICON_CLI_GENMODEL_TYPE { leaf CLICON_CLI_GENMODEL_TYPE {