From e45e8da6d77d366fcd90468fbc6785d8bf1f4d4f Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Sun, 24 Sep 2017 22:01:28 +0200 Subject: [PATCH] Added experimental reading of yang and xml-based config file. --- CHANGELOG.md | 1 + Makefile.in | 2 +- configure | 10 +++- configure.ac | 6 ++ example/routing.conf.local | 6 -- include/clixon_config.h.in | 3 + include/clixon_custom.h | 2 +- lib/src/clixon_options.c | 96 ++++++++++++++++++++---------- lib/src/clixon_xml_map.c | 8 ++- yang/Makefile.in | 69 +++++++++++++++++++++ yang/clixon-config@2017-07-02.yang | 6 ++ 11 files changed, 167 insertions(+), 42 deletions(-) create mode 100644 yang/Makefile.in diff --git a/CHANGELOG.md b/CHANGELOG.md index fea56a56..8b35ff68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Clixon CHANGELOG ## 3.3.3 Upcoming +* Added experimental reading of yang and xml-based config file. * netconf client was limited to 8K byte messages. Now limit is 2^32. * Added event_poll function. * Added experimental xml hash for better performance of large lists. diff --git a/Makefile.in b/Makefile.in index 3447442c..d467bcc6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -52,7 +52,7 @@ LIBS = @LIBS@ INCLUDES = -I. -I@srcdir@ @INCLUDES@ SHELL = /bin/sh -SUBDIRS = lib apps include etc datastore +SUBDIRS = lib apps include etc datastore yang .PHONY: doc all clean depend $(SUBDIRS) install loc TAGS .config.status docker diff --git a/configure b/configure index 1716ccfa..49a433ec 100755 --- a/configure +++ b/configure @@ -2165,6 +2165,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF + # clixon versions spread to Makefile's (.so files) and variable in build.c @@ -3483,6 +3484,12 @@ if test "$prefix" = "NONE"; then prefix=${ac_default_prefix} fi + +cat >>confdefs.h <<_ACEOF +#define CLIXON_DATADIR "${prefix}/share/clixon" +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lm" >&5 $as_echo_n "checking for main in -lm... " >&6; } if ${ac_cv_lib_m_main+:} false; then : @@ -4266,7 +4273,7 @@ done -ac_config_files="$ac_config_files Makefile lib/Makefile lib/src/Makefile lib/clixon/Makefile apps/Makefile apps/cli/Makefile apps/backend/Makefile apps/netconf/Makefile apps/restconf/Makefile include/Makefile etc/Makefile etc/clixonrc example/Makefile example/docker/Makefile docker/Makefile docker/cli/Makefile docker/cli/Dockerfile docker/backend/Makefile docker/backend/Dockerfile docker/netconf/Makefile docker/netconf/Dockerfile datastore/Makefile datastore/keyvalue/Makefile datastore/text/Makefile doc/Makefile" +ac_config_files="$ac_config_files Makefile lib/Makefile lib/src/Makefile lib/clixon/Makefile apps/Makefile apps/cli/Makefile apps/backend/Makefile apps/netconf/Makefile apps/restconf/Makefile include/Makefile etc/Makefile etc/clixonrc example/Makefile example/docker/Makefile docker/Makefile docker/cli/Makefile docker/cli/Dockerfile docker/backend/Makefile docker/backend/Dockerfile docker/netconf/Makefile docker/netconf/Dockerfile datastore/Makefile datastore/keyvalue/Makefile datastore/text/Makefile yang/Makefile doc/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -4983,6 +4990,7 @@ do "datastore/Makefile") CONFIG_FILES="$CONFIG_FILES datastore/Makefile" ;; "datastore/keyvalue/Makefile") CONFIG_FILES="$CONFIG_FILES datastore/keyvalue/Makefile" ;; "datastore/text/Makefile") CONFIG_FILES="$CONFIG_FILES datastore/text/Makefile" ;; + "yang/Makefile") CONFIG_FILES="$CONFIG_FILES yang/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; diff --git a/configure.ac b/configure.ac index 59dc3e10..00791bf1 100644 --- a/configure.ac +++ b/configure.ac @@ -55,6 +55,7 @@ AC_DEFINE_UNQUOTED(CLIXON_VERSION_MAJOR, $CLIXON_VERSION_MAJOR, [Clixon major re AC_DEFINE_UNQUOTED(CLIXON_VERSION_MINOR, $CLIXON_VERSION_MINOR, [Clixon minor release]) AC_DEFINE_UNQUOTED(CLIXON_VERSION_PATCH, $CLIXON_VERSION_PATCH, [Clixon path version]) + # clixon versions spread to Makefile's (.so files) and variable in build.c AC_SUBST(CLIXON_VERSION) AC_SUBST(CLIXON_VERSION_STRING) @@ -172,6 +173,10 @@ AC_CHECK_LIB(dl, dlopen) AC_CHECK_FUNCS(inet_aton sigaction sigvec strlcpy strsep strndup alphasort versionsort strverscmp) +# This is to find clixon system files in the source code. +# same as clixon_DATADIR defined in clixon.mk.cpp for Makefiles +AC_DEFINE_UNQUOTED(CLIXON_DATADIR, "${prefix}/share/clixon", [Clixon data dir for system yang files etc]) + AH_BOTTOM([#include ]) AC_OUTPUT(Makefile @@ -198,6 +203,7 @@ AC_OUTPUT(Makefile datastore/Makefile datastore/keyvalue/Makefile datastore/text/Makefile + yang/Makefile doc/Makefile ) diff --git a/example/routing.conf.local b/example/routing.conf.local index 9c4c75ad..660be03e 100644 --- a/example/routing.conf.local +++ b/example/routing.conf.local @@ -20,12 +20,6 @@ CLICON_CLI_GENMODEL_COMPLETION 1 # CLICON_CLI_GENMODEL_TYPE VARS CLICON_CLI_GENMODEL_TYPE VARS -# Set if you want to use old obsolete cligen callback variable syntax -# Migration: Set to 0 and change all user-defined cli callbacks in your cli spec files -# E.g cmd, callback("single arg"); -> cmd, callback("two" "args"); -# And change predefined callbacks, eg cli_commit -> cli_commitv in all cli files -CLICON_CLIGEN_CALLBACK_SINGLE_ARG 0 - # Enabled uses "startup" configuration on boot CLICON_USE_STARTUP_CONFIG 0 diff --git a/include/clixon_config.h.in b/include/clixon_config.h.in index 1b450323..9840a65d 100644 --- a/include/clixon_config.h.in +++ b/include/clixon_config.h.in @@ -1,5 +1,8 @@ /* include/clixon_config.h.in. Generated from configure.ac by autoheader. */ +/* Clixon data dir for system yang files etc */ +#undef CLIXON_DATADIR + /* Clixon major release */ #undef CLIXON_VERSION_MAJOR diff --git a/include/clixon_custom.h b/include/clixon_custom.h index e1ba8e19..6e2dc925 100644 --- a/include/clixon_custom.h +++ b/include/clixon_custom.h @@ -52,4 +52,4 @@ int strverscmp (__const char *__s1, __const char *__s2); /* Hash for XML trees list entries * Experimental */ -#define XML_CHILD_HASH 0 +#define XML_CHILD_HASH 1 diff --git a/lib/src/clixon_options.c b/lib/src/clixon_options.c index ccbba5b4..035ba187 100644 --- a/lib/src/clixon_options.c +++ b/lib/src/clixon_options.c @@ -67,6 +67,8 @@ #include "clixon_options.h" #if CONFIGFILE_XML #include "clixon_xml.h" +#include "clixon_xsl.h" +#include "clixon_xml_map.h" #endif /* * clicon_option_dump @@ -106,7 +108,12 @@ clicon_option_dump(clicon_handle h, int dbglevel) /*! Read filename and set values to global options registry */ static int -clicon_option_readfile(clicon_hash_t *copt, const char *filename) +clicon_option_readfile(clicon_hash_t *copt, + const char *filename +#if CONFIGFILE_XML + ,yang_spec *yspec +#endif + ) { struct stat st; #if !CONFIGFILE_XML @@ -139,23 +146,32 @@ clicon_option_readfile(clicon_hash_t *copt, const char *filename) { int fd = fileno(f); cxobj *xt = NULL; + cxobj *xc = NULL; cxobj *x = NULL; + char *name; + char *body; + if (clicon_xml_parse_file(fd, &xt, "") < 0) goto done; - - // yspec should be clicon/yang - // if (xml_apply(xt, CX_ELMNT, xml_spec_populate, yspec) < 0) - //goto done; - - while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) { - fprintf(stderr, "%s\n", xml_name(x)); -#if 0 - if ((hash_add(copt, - opt, - val, - strlen(val)+1)) == NULL) + if (xml_child_nr(xt)==1 && xml_child_nr_type(xt, CX_BODY)==1){ + clicon_err(OE_CFG, 0, "Config file %s: Expected XML but is probably old sh style", filename); + goto done; + } + if ((xc = xpath_first(xt, "config")) == NULL) { + clicon_err(OE_CFG, 0, "Config file %s: Lacks top-level \"config\" element", filename); + goto done; + } + if (xml_apply(xc, CX_ELMNT, xml_spec_populate, yspec) < 0) + goto done; + while ((x = xml_child_each(xc, x, CX_ELMNT)) != NULL) { + name = xml_name(x); + body = xml_body(x); + if (name && body && + (hash_add(copt, + name, + body, + strlen(body)+1)) == NULL) goto done; -#endif } } #else @@ -181,6 +197,7 @@ clicon_option_readfile(clicon_hash_t *copt, const char *filename) return retval; } +#if !CONFIGFILE_XML /*! Set default values of some options that may not appear in config-file */ static int @@ -191,45 +208,50 @@ clicon_option_default(clicon_hash_t *copt) if (!hash_lookup(copt, "CLICON_YANG_MODULE_MAIN")){ if (hash_add(copt, "CLICON_YANG_MODULE_MAIN", "clicon", strlen("clicon")+1) < 0) - goto catch; + goto done; } if (!hash_lookup(copt, "CLICON_SOCK_GROUP")){ val = CLICON_SOCK_GROUP; if (hash_add(copt, "CLICON_SOCK_GROUP", val, strlen(val)+1) < 0) - goto catch; + goto done; } if (!hash_lookup(copt, "CLICON_CLI_MODE")){ if (hash_add(copt, "CLICON_CLI_MODE", "base", strlen("base")+1) < 0) - goto catch; + goto done; } if (!hash_lookup(copt, "CLICON_MASTER_PLUGIN")){ val = CLICON_MASTER_PLUGIN; if (hash_add(copt, "CLICON_MASTER_PLUGIN", val, strlen(val)+1) < 0) - goto catch; + goto done; } if (!hash_lookup(copt, "CLICON_CLI_GENMODEL")){ if (hash_add(copt, "CLICON_CLI_GENMODEL", "1", strlen("1")+1) < 0) - goto catch; + goto done; } if (!hash_lookup(copt, "CLICON_CLI_GENMODEL_TYPE")){ if (hash_add(copt, "CLICON_CLI_GENMODEL_TYPE", "VARS", strlen("VARS")+1) < 0) - goto catch; + goto done; } if (!hash_lookup(copt, "CLICON_AUTOCOMMIT")){ if (hash_add(copt, "CLICON_AUTOCOMMIT", "0", strlen("0")+1) < 0) - goto catch; + goto done; } /* Legacy is 1 but default should really be 0. New apps should use 0 */ if (!hash_lookup(copt, "CLICON_CLI_VARONLY")){ if (hash_add(copt, "CLICON_CLI_VARONLY", "1", strlen("1")+1) < 0) - goto catch; + goto done; } if (!hash_lookup(copt, "CLICON_CLI_GENMODEL_COMPLETION")){ if (hash_add(copt, "CLICON_CLI_GENMODEL_COMPLETION", "0", strlen("0")+1) < 0) - goto catch; + 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; - catch: + done: return retval; } @@ -276,15 +298,11 @@ clicon_option_sanity(clicon_hash_t *copt) clicon_err(OE_UNIX, 0, "CLICON_BACKEND_PIDFILE not defined in config file"); 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; done: return retval; } +#endif /* !CONFIGFILE_XML */ /*! Initialize option values @@ -308,16 +326,32 @@ clicon_options_main(clicon_handle h) } configfile = hash_value(copt, "CLICON_CONFIGFILE", NULL); clicon_debug(1, "CLICON_CONFIGFILE=%s", configfile); + + +#if CONFIGFILE_XML + /* Read clixon yang file */ + { + yang_spec *yspec; + + if ((yspec = yspec_new()) == NULL) + goto done; + if (yang_parse(h, CLIXON_DATADIR, "clixon-config", NULL, yspec) < 0) + goto done; + /* Read configfile */ + if (clicon_option_readfile(copt, configfile, yspec) < 0) + goto done; + } +#else /* Set default options */ if (clicon_option_default(copt) < 0) /* init registry from file */ goto done; - /* Read configfile */ if (clicon_option_readfile(copt, configfile) < 0) goto done; - if (clicon_option_sanity(copt) < 0) goto done; +#endif + retval = 0; done: return retval; diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index 5356fa23..1c8abcb4 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -1451,8 +1451,10 @@ xml_non_config_data(cxobj *xt, /*! Add yang specification backpoint to XML node * @param[in] xt XML tree node - * @note This should really be unnecessary since yspec should be set on creation + * @param[in] arg Yang spec + * @note This may be unnecessary if yspec us set on creation * @note For subs to anyxml nodes will not have spec set + * @note No validation is done,... XXX * @code * xml_apply(xc, CX_ELMNT, xml_spec_populate, yspec) * @endcode @@ -1474,11 +1476,13 @@ xml_spec_populate(cxobj *x, y = yang_find_datanode((yang_node*)yp, xml_name(x)); else y = yang_find_topnode(yspec, name, 0); /* still NULL for config */ -#ifdef XXX_OBSOLETE /* Add validate elsewhere */ + //#ifdef XXX_OBSOLETE /* Add validate elsewhere */ +#if 0 if (y==NULL){ clicon_err(OE_XML, EBADF, "yang spec not found for xml node '%s' xml parent name: '%s' yangspec:'%s']", name, xp?xml_name(xp):"", yp?yp->ys_argument:""); + return -1; // XXX goto done; } #endif diff --git a/yang/Makefile.in b/yang/Makefile.in new file mode 100644 index 00000000..59bc5c6e --- /dev/null +++ b/yang/Makefile.in @@ -0,0 +1,69 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# +# Copyright (C) 2009-2017 Olof Hagsand and Benny Holmgren +# +# This file is part of CLIXON +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Alternatively, the contents of this file may be used under the terms of +# the GNU General Public License Version 3 or later (the "GPL"), +# in which case the provisions of the GPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of the GPL, and not to allow others to +# use your version of this file under the terms of Apache License version 2, +# indicate your decision by deleting the provisions above and replace them with +# the notice and other provisions required by the GPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the Apache License version 2 or the GPL. +# +# ***** END LICENSE BLOCK ***** +# +VPATH = @srcdir@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +prefix = @prefix@ +bindir = @bindir@ +includedir = @includedir@ +datarootdir = @datarootdir@ + +YANGSPECS = clixon-config@2017-07-02.yang +YANGSPECS += ietf-netconf@2011-06-01.yang + +APPNAME = clixon # subdir ehere these files are installed + +all: + +# Note: clixon.mk has a rule for: +-include $(DESTDIR)$(datarootdir)/clixon/clixon.mk + +clean: + +distclean: clean + rm -f Makefile *~ .depend + +install: $(YANGSPECS) + install -d $(DESTDIR)/yang + install $(YANGSPECS) $(DESTDIR)$(clixon_DATADIR) + +uninstall: + (cd $(DESTDIR)$(clixon_DATADIR); rm -rf $(YANGSPECS)) + +install-include: + +depend: + + +#include .depend + diff --git a/yang/clixon-config@2017-07-02.yang b/yang/clixon-config@2017-07-02.yang index ed704545..bc5be699 100644 --- a/yang/clixon-config@2017-07-02.yang +++ b/yang/clixon-config@2017-07-02.yang @@ -170,6 +170,12 @@ description "Dont include keys in cvec in cli vars callbacks, ie a & k in 'a k ' ignored"; } + leaf CLICON_CLI_LINESCROLLING { + type int32; + default 1; + description "Set to 0 if you want CLI to wrap to next line. + Set to 1 if you want CLI to scroll sideways when approaching right margin"; + } leaf CLICON_RESTCONF_PATH { type string; default "/www-data/fastcgi_restconf.sock";