* Generilized top-level yang parsing functions

* Clarified semantics of main yang module:
    * -y option to commands MUST specify filename
    * CLICON_YANG_MODULE_MAIN MUST specify a module
    * yang_parse() changed to take either filename or module name and revision.
  * Removed clicon_dbspec_name[_set]().
    * Use yang_main_module_name() instead.
  * Replaced yang_spec_main with yang_spec_parse_module
  * Added yang_spec_parse_file
This commit is contained in:
Olof hagsand 2018-10-07 11:04:33 +02:00
parent 782f75a7b9
commit acb8748470
21 changed files with 369 additions and 340 deletions

View file

@ -3,14 +3,18 @@
## 3.8.0 (Upcoming)
### Major New features
### API changes on existing features (you may need to change your code)
* YANG Module Library support
* According to RFC 7895 and implemented by ietf-yang-library.yang
* Supported: module, name, revision, namespace
* Not supported: notification, deviation, module-set-id, etc.
* Enabled by default, disable by resetting CLICON_MODULE_LIBRARY_RFC7895
* Yang 1.1 notification support (RFC 7950: Sec 7.16)
* Major rewrite of event streams
* See clicon_stream.[ch] for details
* Added stream discovery according to RFC 5277 for netconf and RFC 8040 for restconf
* Enabled by CLICON_STREAM_DISCOVERY_RFC5277 and CLICON_STREAM_DISCOVERY_RFC8040.
### API changes on existing features (you may need to change your code)
* Major rewrite of event streams
* If you used old event callbacks API, you need to switch to the streams API
* See clixon_stream.[ch]
@ -18,23 +22,30 @@
* clicon_log_register_callback()
* subscription_add() --> stream_register()
* backend_notify() and backend_notify_xml() - use stream_notify() instead
* Added stream discovery according to RFC 5277 for netconf and RFC 8040 for restconf
* Enabled by CLICON_STREAM_DISCOVERY_RFC5277 and CLICON_STREAM_DISCOVERY_RFC8040.
* Example uses "NETCONF" stream instead of "ROUTING"
* clixon_restconf and clixon_netconf now take -D <level> as command-line option instead of just -D
* This aligns to clixon_cli and clixon_backend
* Application command option -S to clixon_netconf is obsolete. Use `clixon_netconf -l s` instead.
### Minor changes
* Added timeout option -t for clixon_netconf - quit after max time.
* Comply to RFC 8040 3.5.3.1 rule: api-identifier = [module-name ":"] identifier
* The "module-name" was a no-op before.
* This means that there was no difference between eg: GET /restconf/data/ietf-yang-library:modules-state and GET /restconf/data/XXXX:modules-state
* Unified log handling for all clicon applications using -l e|o|s|f<file>.
* The options stand for e:stderr, o:stdout, s: syslog, f:file
* Added file logging (`-l f` or `-l f<file>`) for cases where neither syslog nor stderr is useful.
* Comply to RFC 8040 3.5.3.1 rule: api-identifier = [module-name ":"] identifier
* The "module-name" was a no-op before.
* This means that there was no difference between eg: GET /restconf/data/ietf-yang-library:modules-state and GET /restconf/data/XXXX:modules-state
* Generilized top-level yang parsing functions
* Clarified semantics of main yang module:
* -y option to commands MUST specify filename
* CLICON_YANG_MODULE_MAIN MUST specify a module
* yang_parse() changed to take either filename or module name and revision.
* Removed clicon_dbspec_name[_set]().
* Use yang_main_module_name() instead.
* Replaced yang_spec_main with yang_spec_parse_module
* Added yang_spec_parse_file
### Minor changes
* Obsoleted COMPAT_CLIV and COMPAT_XSL that were optional in 3.7
* Added timeout option -t for clixon_netconf - quit after max time.
* Added -l option for clixon_backend for directing syslog to stderr or stdout if running in foreground
### Corrected Bugs

View file

@ -129,24 +129,24 @@ usage(clicon_handle h,
fprintf(stderr, "usage:%s\n"
"where options are\n"
" -h\t\tHelp\n"
" -D <level>\tDebug level\n"
" -f <file>\tCLICON config file\n"
" -l <s|e|o|f<file>> \tLog on (s)yslog, std(e)rr or std(o)ut (stderr is default) Only valid if -F, if background syslog is on syslog.\n"
" -d <dir>\tSpecify backend plugin directory (default: %s)\n"
" -b <dir>\tSpecify XMLDB database directory\n"
" -F\t\tRun in foreground, do not run as daemon\n"
" -z\t\tKill other config daemon and exit\n"
" -a UNIX|IPv4|IPv6\tInternal backend socket family\n"
" -u <path|addr>\tInternal socket domain path or IP addr (see -a)(default: %s)\n"
" -P <file>\tPid filename (default: %s)\n"
" -1\t\tRun once and then quit (dont wait for events)\n"
" -s <mode>\tSpecify backend startup mode: none|startup|running|init (replaces -IRCr\n"
" -c <file>\tLoad extra xml configuration, but don't commit.\n"
" -g <group>\tClient membership required to this group (default: %s)\n"
"\t-h\t\tHelp\n"
"\t-D <level>\tDebug level\n"
"\t-f <file>\tCLICON config file\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-b <dir>\tSpecify XMLDB database directory\n"
"\t-F\t\tRun in foreground, do not run as daemon\n"
"\t-z\t\tKill other config daemon and exit\n"
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
"\t-u <path|addr>\tInternal socket domain path or IP addr (see -a)(default: %s)\n"
"\t-P <file>\tPid filename (default: %s)\n"
"\t-1\t\tRun once and then quit (dont wait for events)\n"
"\t-s <mode>\tSpecify backend startup mode: none|startup|running|init)\n"
"\t-c <file>\tLoad extra xml configuration, but don't commit.\n"
"\t-g <group>\tClient membership required to this group (default: %s)\n"
" -y <file>\tOverride yang spec file (dont include .yang suffix)\n"
" -x <plugin>\tXMLDB plugin\n",
"\t-y <file>\tLoad yang spec file (override yang main module)\n"
"\t-x <plugin>\tXMLDB plugin\n",
argv0,
plgdir ? plgdir : "none",
confsock ? confsock : "none",
@ -258,7 +258,7 @@ nacm_load_external(clicon_handle h)
}
if ((yspec = yspec_new()) == NULL)
goto done;
if (yang_parse(h, CLIXON_DATADIR, "ietf-netconf-acm", NULL, yspec) < 0)
if (yang_parse(h, NULL, "ietf-netconf-acm", CLIXON_DATADIR, NULL, yspec) < 0)
goto done;
fd = fileno(f);
/* Read configfile */
@ -519,6 +519,8 @@ main(int argc,
char *xml_format;
char *nacm_mode;
int logdst = CLICON_LOG_SYSLOG|CLICON_LOG_STDERR;
yang_spec *yspec = NULL;
char *yang_filename = NULL;
/* In the startup, logs to stderr & syslog and debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
@ -638,8 +640,8 @@ main(int argc,
case 'g': /* config socket group */
clicon_option_str_set(h, "CLICON_SOCK_GROUP", optarg);
break;
case 'y' :{ /* Override yang module or absolute filename */
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg);
case 'y' :{ /* Load yang spec file (override yang main module) */
yang_filename = optarg;
break;
}
case 'x' :{ /* xmldb plugin */
@ -727,18 +729,31 @@ main(int argc,
/* Connect to plugin to get a handle */
if (xmldb_connect(h) < 0)
goto done;
/* Read and parse application yang specification */
if (yang_spec_main(h) == NULL)
if ((yspec = yspec_new()) == NULL)
goto done;
clicon_dbspec_yang_set(h, yspec);
/* Read and parse application yang specification: either a module and search
* in dir, or a specific file
*/
if (yang_filename){
if (yang_spec_parse_file(h, yang_filename, clicon_yang_dir(h), yspec) < 0)
goto done;
}
else if (yang_spec_parse_module(h, clicon_yang_module_main(h),
clicon_yang_dir(h),
clicon_yang_module_revision(h),
yspec) < 0)
goto done;
/* Add system modules */
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
yang_spec_append(h, CLIXON_DATADIR, "ietf-restconf-monitoring", NULL)< 0)
yang_spec_parse_module(h, "ietf-restconf-monitoring", CLIXON_DATADIR, NULL, yspec)< 0)
goto done;
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
yang_spec_append(h, CLIXON_DATADIR, "ietf-netconf-notification", NULL)< 0)
yang_spec_parse_module(h, "ietf-netconf-notification", CLIXON_DATADIR, NULL, yspec)< 0)
goto done;
if (clicon_option_bool(h, "CLICON_MODULE_LIBRARY_RFC7895") &&
yang_spec_append(h, CLIXON_DATADIR, "ietf-yang-library", NULL)< 0)
yang_spec_parse_module(h, "ietf-yang-library", CLIXON_DATADIR, NULL, yspec)< 0)
goto done;
/* Set options: database dir and yangspec (could be hidden in connect?)*/
if (xmldb_setopt(h, "dbdir", clicon_xmldb_dir(h)) < 0)

View file

@ -251,6 +251,7 @@ main(int argc, char **argv)
int dump_configfile_xml = 0;
yang_spec *yspec;
struct passwd *pw;
char *yang_filename = NULL;
/* Defaults */
once = 0;
@ -379,8 +380,8 @@ main(int argc, char **argv)
case 'L' : /* Debug print dynamic CLI syntax */
logclisyntax++;
break;
case 'y' :{ /* Overwrite yang module or absolute filename */
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg);
case 'y' :{ /* Load yang spec file (override yang main module) */
yang_filename = optarg;
break;
}
case 'c' :{ /* Overwrite clispec with absolute filename */
@ -414,8 +415,19 @@ main(int argc, char **argv)
*/
cv_exclude_keys(clicon_cli_varonly(h));
/* Parse db specification as cli*/
if ((yspec = yang_spec_main(h)) == NULL)
if ((yspec = yspec_new()) == NULL)
goto done;
clicon_dbspec_yang_set(h, yspec);
/* Parse db specification as cli.
* If -y <file> is given, it overrides main module */
if (yang_filename){
if (yang_spec_parse_file(h, yang_filename, clicon_yang_dir(h), yspec) < 0)
goto done;
}
else if (yang_spec_parse_module(h, clicon_yang_module_main(h),
clicon_yang_dir(h),
clicon_yang_module_revision(h),
yspec) < 0)
goto done;
if (printspec)
yang_print(stdout, (yang_node*)yspec);
@ -425,17 +437,20 @@ main(int argc, char **argv)
*/
if (clicon_cli_genmodel(h)){
parse_tree pt = {0,}; /* cli parse tree */
char *name; /* main module name */
/* Create cli command tree from dbspec */
if (yang2cli(h, yspec, &pt, clicon_cli_genmodel_type(h)) < 0)
goto done;
len = strlen("datamodel:") + strlen(clicon_dbspec_name(h)) + 1;
name = yang_main_module_name(yspec);
len = strlen("datamodel:") + strlen(name) + 1;
if ((treename = malloc(len)) == NULL){
clicon_err(OE_UNIX, errno, "malloc");
goto done;
}
snprintf(treename, len, "datamodel:%s", clicon_dbspec_name(h));
snprintf(treename, len, "datamodel:%s", name);
cligen_tree_add(cli_cligen(h), treename, pt);
if (printgen)

View file

@ -276,8 +276,6 @@ netconf_terminate(clicon_handle h)
clicon_rpc_close_session(h);
if ((yspec = clicon_dbspec_yang(h)) != NULL)
yspec_free(yspec);
if ((yspec = clicon_netconf_yang(h)) != NULL)
yspec_free(yspec);
event_exit();
clicon_handle_exit(h);
clicon_log_exit();
@ -306,12 +304,12 @@ usage(clicon_handle h,
"\t-D <level>\tDebug level\n"
"\t-q\t\tQuiet: dont send hello prompt\n"
"\t-f <file>\tConfiguration file (mandatory)\n"
"\t-l <e|o|s|f<file>> \tLog on std(e)rr, std(o)ut, (s)yslog, (f)ile (syslog is default)\n"
"\t-l (e|o|s|f<file>) \tLog on std(e)rr, std(o)ut, (s)yslog, (f)ile (syslog is default)\n"
"\t-a UNIX|IPv4|IPv6\tInternal backend socket family\n"
"\t-u <path|addr>\tInternal socket domain path or IP addr (see -a)\n"
"\t-d <dir>\tSpecify netconf plugin directory dir (default: %s)\n"
"\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n"
"\t-y <file>\tLoad yang spec file (override yang main module)\n"
"\t-U <user>\tOver-ride unix user with a pseudo user for NACM.\n"
"\t-t <sec>\tTimeout in seconds. Quit after this time.\n",
argv0,
@ -333,6 +331,8 @@ main(int argc,
int logdst = CLICON_LOG_STDERR;
struct passwd *pw;
struct timeval tv = {0,}; /* timeout */
yang_spec *yspec = NULL;
char *yang_filename = NULL;
/* Create handle */
if ((h = clicon_handle_init()) == NULL)
@ -407,8 +407,8 @@ main(int argc,
usage(h, argv[0]);
clicon_option_str_set(h, "CLICON_NETCONF_DIR", optarg);
break;
case 'y' :{ /* Overwrite yang module or absolute filename */
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg);
case 'y' :{ /* Load yang spec file (override yang main module) */
yang_filename = optarg;
break;
}
case 'U': /* Clixon 'pseudo' user */
@ -428,12 +428,22 @@ main(int argc,
argc -= optind;
argv += optind;
if ((yspec = yspec_new()) == NULL)
goto done;
clicon_dbspec_yang_set(h, yspec);
/* Parse yang database spec file */
if (yang_spec_main(h) == NULL)
if (yang_filename){
if (yang_spec_parse_file(h, yang_filename, clicon_yang_dir(h), yspec) < 0)
goto done;
}
else if (yang_spec_parse_module(h, clicon_yang_module_main(h),
clicon_yang_dir(h),
clicon_yang_module_revision(h),
yspec) < 0)
goto done;
/* Parse netconf yang spec file */
if (yang_spec_netconf(h) == NULL)
/* Add netconf yang spec, used by netconf client and as internal protocol */
if (yang_spec_parse_module(h, "ietf-yang-library", CLIXON_DATADIR, NULL, yspec)< 0)
goto done;
/* Initialize plugins group */

View file

@ -955,15 +955,9 @@ netconf_rpc_dispatch(clicon_handle h,
{
int retval = -1;
cxobj *xe;
yang_spec *yspec = NULL;
char *username;
cxobj *xa;
/* Check incoming RPC against system / netconf RPC:s */
if ((yspec = clicon_netconf_yang(h)) == NULL){
clicon_err(OE_YANG, ENOENT, "No netconf yang spec");
goto done;
}
/* Tag username on all incoming requests in case they are forwarded as internal messages
* This may be unecesary since not all are forwarded.
* It may even be wrong if something else is done with the incoming message?

View file

@ -494,7 +494,7 @@ usage(clicon_handle h,
"\t-f <file>\tConfiguration file (mandatory)\n"
"\t-l <s|f<file>> \tLog on (s)yslog, (f)ile (syslog is default)\n"
"\t-d <dir>\tSpecify restconf plugin directory dir (default: %s)\n"
"\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n"
"\t-y <file>\tLoad yang spec file (override yang main module)\n"
"\t-a UNIX|IPv4|IPv6\tInternal backend socket family\n"
"\t-u <path|addr>\tInternal socket domain path or IP addr (see -a)\n",
argv0,
@ -522,6 +522,8 @@ main(int argc,
char *dir;
char *tmp;
int logdst = CLICON_LOG_SYSLOG;
yang_spec *yspec = NULL;
char *yang_filename = NULL;
/* In the startup, logs to stderr & debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
@ -589,8 +591,8 @@ main(int argc,
usage(h, argv[0]);
clicon_option_str_set(h, "CLICON_RESTCONF_DIR", optarg);
break;
case 'y' : /* yang module */
yangspec = optarg;
case 'y' : /* Load yang spec file (override yang main module) */
yang_filename = optarg;
break;
case 'a': /* internal backend socket address family */
clicon_option_str_set(h, "CLICON_SOCK_FAMILY", optarg);
@ -616,18 +618,28 @@ main(int argc,
if (clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
return -1;
/* Parse yang database spec file */
if (yang_spec_main(h) == NULL)
/* Parse main yang spec */
if ((yspec = yspec_new()) == NULL)
goto done;
clicon_dbspec_yang_set(h, yspec);
if (yang_filename){
if (yang_spec_parse_file(h, yang_filename, clicon_yang_dir(h), yspec) < 0)
goto done;
}
else if (yang_spec_parse_module(h, clicon_yang_module_main(h),
clicon_yang_dir(h),
clicon_yang_module_revision(h),
yspec) < 0)
goto done;
/* Add system modules */
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
yang_spec_append(h, CLIXON_DATADIR, "ietf-restconf-monitoring", NULL)< 0)
yang_spec_parse_module(h, "ietf-restconf-monitoring", CLIXON_DATADIR, NULL, yspec)< 0)
goto done;
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
yang_spec_append(h, CLIXON_DATADIR, "ietf-netconf-notification", NULL)< 0)
yang_spec_parse_module(h, "ietf-netconf-notification", CLIXON_DATADIR, NULL, yspec)< 0)
goto done;
if (clicon_option_bool(h, "CLICON_MODULE_LIBRARY_RFC7895") &&
yang_spec_append(h, CLIXON_DATADIR, "ietf-yang-library", NULL)< 0)
yang_spec_parse_module(h, "ietf-yang-library", CLIXON_DATADIR, NULL, yspec)< 0)
goto done;
if (stream_register(h, "NETCONF", "default NETCONF event stream") < 0)

View file

@ -206,7 +206,7 @@ main(int argc, char **argv)
if ((yspec = yspec_new()) == NULL)
goto done;
/* Parse yang spec from given file */
if (yang_parse(h, yangdir, yangmodule, NULL, yspec) < 0)
if (yang_parse(h, NULL, yangmodule, yangdir, NULL, yspec) < 0)
goto done;
/* Set database directory option */
if (xmldb_setopt(h, "dbdir", dbdir) < 0)

View file

@ -1387,7 +1387,7 @@ main(int argc,
db_init(db);
if ((yspec = yspec_new()) == NULL)
goto done
if (yang_parse(h, yangdir, yangmod, NULL, yspec) < 0)
if (yang_parse(h, NULL, yangmod, yangdir, NULL, yspec) < 0)
goto done;
if (strcmp(cmd, "get")==0){
if (argc < 5)

View file

@ -44,6 +44,7 @@
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/syslog.h>
/* clicon */
#include <cligen/cligen.h>
@ -119,7 +120,7 @@ clixon_plugin_init(clicon_handle h)
clicon_debug(1, "%s backend nacm", __FUNCTION__);
nacm_mode = clicon_option_str(h, "CLICON_NACM_MODE");
if (nacm_mode==NULL || strcmp(nacm_mode, "disabled") == 0){
clicon_debug(1, "%s CLICON_NACM_MODE not enabled: example nacm module disabled", __FUNCTION__);
clicon_log(LOG_WARNING, "%s CLICON_NACM_MODE not enabled: example nacm module disabled", __FUNCTION__);
return NULL;
}
return &api;

View file

@ -164,12 +164,6 @@ int clicon_quiet_mode_set(clicon_handle h, int val);
yang_spec * clicon_dbspec_yang(clicon_handle h);
int clicon_dbspec_yang_set(clicon_handle h, struct yang_spec *ys);
char *clicon_dbspec_name(clicon_handle h);
int clicon_dbspec_name_set(clicon_handle h, char *name);
yang_spec *clicon_netconf_yang(clicon_handle h);
int clicon_netconf_yang_set(clicon_handle h, struct yang_spec *ys);
plghndl_t clicon_xmldb_plugin_get(clicon_handle h);
int clicon_xmldb_plugin_set(clicon_handle h, plghndl_t handle);

View file

@ -244,6 +244,7 @@ yang_stmt *ys_dup(yang_stmt *old);
int yn_insert(yang_node *yn_parent, yang_stmt *ys_child);
yang_stmt *yn_each(yang_node *yn, yang_stmt *ys);
char *yang_key2str(int keyword);
char *yang_main_module_name(yang_spec *ysp);
char *yarg_prefix(yang_stmt *ys);
char *yarg_id(yang_stmt *ys);
int yang_nodeid_split(char *nodeid, char **prefix, char **id);
@ -260,8 +261,9 @@ int yang_print(FILE *f, yang_node *yn);
int yang_print_cbuf(cbuf *cb, yang_node *yn, int marginal);
int ys_populate(yang_stmt *ys, void *arg);
yang_stmt *yang_parse_file(int fd, const char *name, yang_spec *ysp);
int yang_parse(clicon_handle h, const char *yang_dir,
const char *module, const char *revision, yang_spec *ysp);
int yang_parse(clicon_handle h, const char *filename,
const char *module, const char *dir,
const char *revision, yang_spec *ysp);
int yang_apply(yang_node *yn, enum rfc_6020 key, yang_applyfn_t fn,
void *arg);
int yang_abs_schema_nodeid(yang_spec *yspec, char *schema_nodeid,
@ -272,9 +274,8 @@ cg_var *ys_parse(yang_stmt *ys, enum cv_type cvtype);
int ys_parse_sub(yang_stmt *ys, char *extra);
int yang_mandatory(yang_stmt *ys);
int yang_config(yang_stmt *ys);
yang_spec *yang_spec_netconf(clicon_handle h);
yang_spec *yang_spec_main(clicon_handle h);
int yang_spec_append(clicon_handle h, char *yang_dir, char *yang_module, char *yang_revision);
int yang_spec_parse_module(clicon_handle h, char *module, char *dir, char *revision, yang_spec *yspec);
int yang_spec_parse_file(clicon_handle h, char *filename, char *dir, yang_spec *yspec);
cvec *yang_arg2cvec(yang_stmt *ys, char *delimi);
int yang_key_match(yang_node *yn, char *name);

View file

@ -216,7 +216,7 @@ clicon_options_main(clicon_handle h)
if (xml){ /* Read clixon yang file */
if ((yspec = yspec_new()) == NULL)
goto done;
if (yang_parse(h, CLIXON_DATADIR, "clixon-config", NULL, yspec) < 0)
if (yang_parse(h, NULL, "clixon-config", CLIXON_DATADIR, NULL, yspec) < 0)
goto done;
/* Read configfile */
if (clicon_option_readfile_xml(copt, configfile, yspec) < 0)
@ -571,58 +571,6 @@ clicon_dbspec_yang_set(clicon_handle h,
return 0;
}
/*! Get YANG NETCONF specification
* Must use hash functions directly since they are not strings.
*/
yang_spec *
clicon_netconf_yang(clicon_handle h)
{
clicon_hash_t *cdat = clicon_data(h);
size_t len;
void *p;
if ((p = hash_value(cdat, "netconf_yang", &len)) != NULL)
return *(yang_spec **)p;
return NULL;
}
/*! Set yang netconf specification
* ys must be a malloced pointer
*/
int
clicon_netconf_yang_set(clicon_handle h,
struct yang_spec *ys)
{
clicon_hash_t *cdat = clicon_data(h);
/* It is the pointer to ys that should be copied by hash,
so we send a ptr to the ptr to indicate what to copy.
*/
if (hash_add(cdat, "netconf_yang", &ys, sizeof(ys)) == NULL)
return -1;
return 0;
}
/*! Get dbspec name as read from spec. Can be used in CLI '@' syntax.
* XXX: this we muśt change,...
*/
char *
clicon_dbspec_name(clicon_handle h)
{
if (!clicon_option_exists(h, "dbspec_name"))
return NULL;
return clicon_option_str(h, "dbspec_name");
}
/*! Set dbspec name as read from spec. Can be used in CLI '@' syntax.
*/
int
clicon_dbspec_name_set(clicon_handle h, char *name)
{
return clicon_option_str_set(h, "dbspec_name", name);
}
/*! Get xmldb datastore plugin handle, as used by dlopen/dlsym/dlclose */
plghndl_t
clicon_xmldb_plugin_get(clicon_handle h)

View file

@ -344,6 +344,8 @@ ys_dup(yang_stmt *old)
/*! Insert yang statement as child of a parent yang_statement, last in list
*
* @param[in] yn_parent Add child to this parent
* @param[in] ys_child Add this child
* Also add parent to child as up-pointer
*/
int
@ -607,7 +609,6 @@ yang_find_schemanode(yang_node *yn,
return ysmatch;
}
/*! Find first matching data node in all (sub)modules in a yang spec
*
* @param[in] ysp Yang specification
@ -756,7 +757,22 @@ yang_key2str(int keyword)
return (char*)clicon_int2str(ykmap, keyword);
}
/*! Find top module or sub-module. Note that ultimate top is yang spec
/*! Name of main module of a specification. That is, name of first module
* @param[in] ysp Yang specification
* @retval name Name of first yang module
*/
char *
yang_main_module_name(yang_spec *ysp)
{
yang_stmt *ym;
if ((ym = yang_find((yang_node*)ysp, Y_MODULE, 0)) != NULL)
return ym->ys_argument;
return NULL;
}
/*! Find top module or sub-module given a statement. Ultimate top is yang spec
* The routine recursively finds ancestors.
* @param[in] ys Any yang statement in a yang tree
* @retval ymod The top module or sub-module
* @see ys_spec
@ -1612,7 +1628,8 @@ yang_expand(yang_node *yn)
* Calling order:
* yang_parse # Parse top-level yang module. Expand and populate yang tree
* yang_parse_recurse # Parse one yang module, go through its (sub)modules, parse them and then recursively parse them
* yang_parse_file # Read yang file into a string
* yang_parse_filename # Read yang file into a string
* yang_parse_file # Read yang open file descriptor into a string
* yang_parse_str # Set up yacc parser and call it given a string
* clixon_yang_parseparse # Actual yang parsing using yacc
*/
@ -1712,49 +1729,6 @@ yang_parse_file(int fd,
return ymod; /* top-level (sub)module */
}
/*! Open a file, read into a string and invoke yang parsing
*
* Similar to clicon_yang_str(), just read a file first
* (cloned from cligen)
* @param[in] h CLICON handle
* @param[in] filename Name of file
* @param[in] ysp Yang specification. Should ave been created by caller using yspec_new
* @retval ymod Top-level yang (sub)module
* @retval NULL Error encountered
* The database symbols are inserted in alphabetical order.
* Calling order:
* yang_parse # Parse top-level yang module. Expand and populate yang tree
* yang_parse_recurse # Parse one yang module, go through its (sub)modules, parse them and then recursively parse them
* yang_parse_file # Read yang file into a string
* yang_parse_str # Set up yacc parser and call it given a string
* clixon_yang_parseparse # Actual yang parsing using yacc
*/
static yang_stmt *
yang_parse_filename(const char *filename,
yang_spec *ysp)
{
yang_stmt *ymod = NULL;
int fd = -1;
struct stat st;
clicon_log(LOG_DEBUG, "Parsing yang file: %s", filename);
if (stat(filename, &st) < 0){
clicon_err(OE_YANG, errno, "%s not found", filename);
goto done;
}
if ((fd = open(filename, O_RDONLY)) < 0){
clicon_err(OE_YANG, errno, "open(%s)", filename);
goto done;
}
if ((ymod = yang_parse_file(fd, filename, ysp)) < 0)
goto done;
done:
if (fd != -1)
close(fd);
return ymod; /* top-level (sub)module */
}
/*! No specific revision give. Match a yang file given dir and module
* @param[in] h CLICON handle
* @param[in] yang_dir Directory where all YANG module files reside
@ -1805,6 +1779,82 @@ yang_parse_find_match(const char *yang_dir,
return retval;
}
/*! Open a file, read into a string and invoke yang parsing
*
* Similar to clicon_yang_str(), just read a file first
* (cloned from cligen)
* @param[in] h CLICON handle
* @param[in] filename Name of file
* @param[in] ysp Yang specification. Should ave been created by caller using yspec_new
* @retval ymod Top-level yang (sub)module
* @retval NULL Error encountered
* The database symbols are inserted in alphabetical order.
* Calling order:
* yang_parse # Parse top-level yang module. Expand and populate yang tree
* yang_parse_recurse # Parse one yang module, go through its (sub)modules, parse them and then recursively parse them
* yang_parse_filename # Read yang file into a string
* yang_parse_file # Read yang open file descriptor into a string
* yang_parse_str # Set up yacc parser and call it given a string
* clixon_yang_parseparse # Actual yang parsing using yacc
*/
static yang_stmt *
yang_parse_filename(const char *filename,
yang_spec *ysp)
{
yang_stmt *ymod = NULL;
int fd = -1;
struct stat st;
clicon_log(LOG_DEBUG, "Parsing yang file: %s", filename);
if (stat(filename, &st) < 0){
clicon_err(OE_YANG, errno, "%s not found", filename);
goto done;
}
if ((fd = open(filename, O_RDONLY)) < 0){
clicon_err(OE_YANG, errno, "open(%s)", filename);
goto done;
}
if ((ymod = yang_parse_file(fd, filename, ysp)) < 0)
goto done;
done:
if (fd != -1)
close(fd);
return ymod; /* top-level (sub)module */
}
static yang_stmt *
yang_parse_module(const char *module,
const char *dir,
const char *revision,
yang_spec *ysp)
{
cbuf *fbuf = NULL;
int nr;
yang_stmt *ymod = NULL;
if ((fbuf = cbuf_new()) == NULL){
clicon_err(OE_YANG, errno, "cbuf_new");
goto done;
}
if (revision)
cprintf(fbuf, "%s/%s@%s.yang", dir, module, revision);
else{
/* No specific revision, Match a yang file */
if ((nr = yang_parse_find_match(dir, module, fbuf)) < 0)
goto done;
if (nr == 0){
clicon_err(OE_YANG, errno, "No matching %s yang files found in %s (expected module name or absolute filename)", module, dir);
goto done;
}
}
if ((ymod = yang_parse_filename(cbuf_get(fbuf), ysp)) == NULL)
goto done;
done:
return ymod; /* top-level (sub)module */
}
/*! Parse one yang module then go through (sub)modules and parse them recursively
*
* @param[in] h CLICON handle
@ -1818,68 +1868,44 @@ yang_parse_find_match(const char *yang_dir,
* Calling order:
* yang_parse # Parse top-level yang module. Expand and populate yang tree
* yang_parse_recurse # Parse one yang module, go through its (sub)modules, parse them and then recursively parse them
* yang_parse_file # Read yang file into a string
* yang_parse_filename # Read yang file into a string
* yang_parse_file # Read yang open file descriptor into a string
* yang_parse_str # Set up yacc parser and call it given a string
* clixon_yang_parseparse # Actual yang parsing using yacc
*/
static yang_stmt *
yang_parse_recurse(const char *yang_dir,
const char *module,
const char *revision,
static int
yang_parse_recurse(yang_stmt *ymod,
const char *dir,
yang_spec *ysp)
{
int retval = -1;
yang_stmt *yi = NULL; /* import */
yang_stmt *ymod = NULL;
yang_stmt *yrev;
char *modname;
char *submodule;
char *subrevision;
cbuf *fbuf = NULL;
int nr;
if (module[0] == '/'){
if ((ymod = yang_parse_filename(module, ysp)) == NULL)
goto done;
}
else {
if ((fbuf = cbuf_new()) == NULL){
clicon_err(OE_YANG, errno, "cbuf_new");
goto done;
}
if (revision)
cprintf(fbuf, "%s/%s@%s.yang", yang_dir, module, revision);
else{
/* No specific revision, Match a yang file */
if ((nr = yang_parse_find_match(yang_dir, module, fbuf)) < 0)
goto done;
if (nr == 0){
clicon_err(OE_YANG, errno, "No matching %s yang files found in %s (expected module name or absolute filename)", module, yang_dir);
goto done;
}
}
if ((ymod = yang_parse_filename(cbuf_get(fbuf), ysp)) == NULL)
goto done;
}
yang_stmt *subymod;
/* go through all import statements of ysp (or its module) */
while ((yi = yn_each((yang_node*)ymod, yi)) != NULL){
if (yi->ys_keyword != Y_IMPORT)
continue;
modname = yi->ys_argument;
submodule = yi->ys_argument;
if ((yrev = yang_find((yang_node*)yi, Y_REVISION_DATE, NULL)) != NULL)
subrevision = yrev->ys_argument;
else
subrevision = NULL;
if (yang_find((yang_node*)ysp, Y_MODULE, modname) == NULL)
if (yang_find((yang_node*)ysp, Y_MODULE, submodule) == NULL)
/* recursive call */
if (yang_parse_recurse(yang_dir, modname, subrevision, ysp) == NULL){
if ((subymod = yang_parse_module(submodule, dir, subrevision, ysp)) == NULL)
goto done;
if (yang_parse_recurse(subymod, dir, ysp) < 0){
ymod = NULL;
goto done;
}
}
retval = 0;
done:
if (fbuf)
cbuf_free(fbuf);
return ymod; /* top-level (sub)module */
return retval; /* top-level (sub)module */
}
int
@ -1929,7 +1955,8 @@ ys_schemanode_check(yang_stmt *ys,
*
* @param[in] h CLICON handle
* @param[in] yang_dir Directory where all YANG module files reside (except mainfile)
* @param[in] mainmod Name of main YANG module. Or absolute file name.
* @param[in] filename File name containing Yang specification. Overrides module
* @param[in] module Name of main YANG module. Or absolute file name.
* @param[in] revision Main module revision date string or NULL
* @param[out] ysp Yang specification. Should have been created by caller using yspec_new
* @retval 0 Everything OK
@ -1941,34 +1968,49 @@ ys_schemanode_check(yang_stmt *ys,
* yang_parse # Parse top-level yang module. Expand and populate yang tree
* yang_parse_recurse # Parse one yang module, go through its (sub)modules,
* parse them and then recursively parse them
* yang_parse_file # Read yang file into a string
* yang_parse_filename # Read yang file into a string
* yang_parse_file # Read yang open file descriptor into a string
* yang_parse_str # Set up yacc parser and call it given a string
* clixon_yang_parseparse # Actual yang parsing using yacc
*/
int
yang_parse(clicon_handle h,
const char *yang_dir,
const char *mainmodule,
const char *filename,
const char *module,
const char *dir,
const char *revision,
yang_spec *ysp)
{
int retval = -1;
yang_stmt *ymod; /* Top-level yang (sub)module */
yang_stmt *ymod = NULL; /* Top-level yang (sub)module */
int i;
int modnr; /* Existing number of modules */
/* Step 1: parse from text to yang parse-tree. */
if ((ymod = yang_parse_recurse(yang_dir, mainmodule, revision, ysp)) == NULL)
modnr = ysp->yp_len;
if (filename){
if ((ymod = yang_parse_filename(filename, ysp)) == NULL)
goto done;
}
else
if ((ymod = yang_parse_module(module, dir, revision, ysp)) == NULL)
goto done;
/* From here on, apply actions on new modules, ie ones after modnr. */
/* Step 1: parse from text to yang parse-tree. */
/* Iterate through modules */
if (yang_parse_recurse(ymod, dir, ysp) < 0)
goto done;
/* Add top module name as dbspec-name */
clicon_dbspec_name_set(h, ymod->ys_argument);
/* Step 2: Go through parse tree and populate it with cv types */
if (yang_apply((yang_node*)ysp, -1, ys_populate, NULL) < 0)
for (i=modnr; i<ysp->yp_len; i++)
if (yang_apply((yang_node*)ysp->yp_stmt[i], -1, ys_populate, NULL) < 0)
goto done;
/* Step 3: Resolve all types: populate type caches. Requires eg length/range cvecs
* from ys_populate step
*/
yang_apply((yang_node*)ysp, Y_TYPE, ys_resolve_type, NULL);
for (i=modnr; i<ysp->yp_len; i++)
yang_apply((yang_node*)ysp->yp_stmt[i], Y_TYPE, ys_resolve_type, NULL);
/* Up to here resolving is made in the context they are defined, rather than the
context they are used. Like static scoping. After this we expand all
@ -1976,16 +2018,19 @@ yang_parse(clicon_handle h,
*/
/* Step 4: Macro expansion of all grouping/uses pairs. Expansion needs marking */
if (yang_expand((yang_node*)ysp) < 0)
for (i=modnr; i<ysp->yp_len; i++){
if (yang_expand((yang_node*)ysp->yp_stmt[i]) < 0)
goto done;
yang_apply((yang_node*)ymod, -1, ys_flag_reset, (void*)YANG_FLAG_MARK);
yang_apply((yang_node*)ysp->yp_stmt[i], -1, ys_flag_reset, (void*)YANG_FLAG_MARK);
}
/* Step 4: Top-level augmentation of all modules */
/* Step 4: Top-level augmentation of all modules XXX: only new modules? */
if (yang_augment_spec(ysp) < 0)
goto done;
/* sanity check of schemanode references, need more here */
if (yang_apply((yang_node*)ysp, -1, ys_schemanode_check, NULL) < 0)
for (i=modnr; i<ysp->yp_len; i++)
if (yang_apply((yang_node*)ysp->yp_stmt[i], -1, ys_schemanode_check, NULL) < 0)
goto done;
retval = 0;
@ -2405,94 +2450,84 @@ yang_config(yang_stmt *ys)
return 1;
}
/*! Parse netconf yang spec, used by netconf client and as internal protocol
* @note not used yet - unfinnisshed code
*/
yang_spec *
yang_spec_netconf(clicon_handle h)
{
yang_spec *yspec = NULL;
if ((yspec = yspec_new()) == NULL)
goto done;
if (yang_parse(h, CLIXON_DATADIR, "ietf-netconf", NULL, yspec) < 0){
yspec_free(yspec); yspec = NULL;
goto done;
}
clicon_netconf_yang_set(h, yspec);
done:
return yspec;
}
/*! Parse yang specification and its dependencies recursively and return
/*! Parse yang specification and its dependencies recursively given module
* @param[in] h clicon handle
*/
yang_spec*
yang_spec_main(clicon_handle h)
{
yang_spec *yspec = NULL;
char *yang_module;
char *yang_revision;
char *yang_dir;
if ((yang_dir = clicon_yang_dir(h)) == NULL){
clicon_err(OE_FATAL, 0, "CLICON_YANG_DIR option not set");
goto done;
}
/* Yang module is either specific absolute filename, or main module */
if ((yang_module = clicon_yang_module_main(h)) == NULL){
clicon_err(OE_FATAL, 0, "CLICON_YANG_MODULE_MAIN option not set");
goto done;
}
yang_revision = clicon_yang_module_revision(h);
if ((yspec = yspec_new()) == NULL)
goto done;
if (yang_parse(h, yang_dir, yang_module, yang_revision, yspec) < 0){
yspec_free(yspec); yspec = NULL;
goto done;
}
clicon_dbspec_yang_set(h, yspec);
done:
return yspec;
}
/*! Parse yang specification, its dependencies, and append to default yang spec
* yang_spec_main should have been called first.
* @param[in] h clicon handle
* @param[in] yang_dir Directory, either system-wide or application-specific
* @param[in] yang_module Name of module
* @param[in] yang_revision Revision, or NULL
* @see yang_spec_main
* @param[in] module Module name, or absolute filename (including dir)
* @param[in] dir Directory where to look for modules and sub-modules
* @param[in] revision Revision, or NULL
* @param[in,out] yspec Modules parse are added to this yangspec
* @retval 0 OK
* @retval -1 Error
* @see yang_spec_parse_file
*/
int
yang_spec_append(clicon_handle h,
char *yang_dir,
char *yang_module,
char *yang_revision)
yang_spec_parse_module(clicon_handle h,
char *module,
char *dir,
char *revision,
yang_spec *yspec)
{
int retval = -1;
yang_spec *yspec = NULL;
yang_spec *yspec0;
yang_stmt *ym = NULL; /* module */
if ((yspec0 = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_YANG, ENOENT, "yang spec not found");
if (yspec == NULL){
clicon_err(OE_YANG, EINVAL, "yang spec is NULL");
goto done;
}
if ((yspec = yspec_new()) == NULL)
goto done;
if (yang_parse(h, yang_dir, yang_module, yang_revision, yspec) < 0){
yspec_free(yspec); yspec = NULL;
if (module == NULL){
clicon_err(OE_YANG, EINVAL, "yang module not set");
goto done;
}
while ((ym = yn_each((yang_node*)yspec, ym)) != NULL)
if (yn_insert((yang_node*)yspec0, ym) < 0)
/* Sanity check - use yang_spec_parse_file instead */
if (strlen(module) && module[0] == '/'){
clicon_err(OE_YANG, EINVAL, "yang module illegal format");
goto done;
yspec->yp_len = 0;
}
if (dir == NULL){
clicon_err(OE_YANG, EINVAL, "yang dir not set");
goto done;
}
if (yang_parse(h, NULL, module, dir, revision, yspec) < 0){
yspec_free(yspec);
yspec = NULL;
goto done;
}
retval = 0;
done:
if (yspec)
return retval;
}
/*! Parse yang specification and its dependencies recursively given filename
* @param[in] h clicon handle
* @param[in] filename Actual filename (including dir and revision)
* @param[in] dir Directory for sub-modules
* @param[in,out] yspec Modules parse are added to this yangspec
* @retval 0 OK
* @retval -1 Error
* @see yang_spec_parse_module for yang dir,module,revision instead of actual filename
*/
int
yang_spec_parse_file(clicon_handle h,
char *filename,
char *dir,
yang_spec *yspec)
{
int retval = -1;
if (yspec == NULL){
clicon_err(OE_YANG, EINVAL, "yang spec is NULL");
goto done;
}
if (dir == NULL){
clicon_err(OE_YANG, EINVAL, "yang dir not set");
goto done;
}
if (yang_parse(h, filename, NULL, dir, NULL, yspec) < 0){
yspec_free(yspec);
yspec = NULL;
goto done;
}
retval = 0;
done:
return retval;
}

View file

@ -15,7 +15,6 @@ cat <<EOF > $cfg
<config>
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
<CLICON_YANG_MODULE_MAIN>$fyang</CLICON_YANG_MODULE_MAIN>
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
<CLICON_RESTCONF_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>

View file

@ -18,7 +18,6 @@ cat <<EOF > $cfg
<config>
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>/usr/local/share/example/yang</CLICON_YANG_DIR>
<CLICON_YANG_MODULE_MAIN>$fyang</CLICON_YANG_MODULE_MAIN>
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>

View file

@ -13,7 +13,6 @@ cat <<EOF > $cfg
<config>
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
<CLICON_YANG_MODULE_MAIN>$fyang</CLICON_YANG_MODULE_MAIN>
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
@ -88,7 +87,7 @@ new "kill old restconf daemon"
sudo pkill -u www-data clixon_restconf
new "start restconf daemon"
sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -f $cfg -D 1
sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -f $cfg -y $fyang # -D 1
sleep 1
@ -110,7 +109,7 @@ expectwait "$clixon_netconf -qf $cfg -y $fyang" '<rpc><create-subscription><stre
new "netconf NETCONF subscription with simple filter"
expectwait "$clixon_netconf -qf $cfg -y $fyang" "<rpc><create-subscription><stream>NETCONF</stream><filter type=\"xpath\" select=\"event\"/></create-subscription></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]><notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0"><eventTime>20' 5
new "netconf NETCONF subscription with filter classfier"
new "netconf NETCONF subscription with filter classifier"
expectwait "$clixon_netconf -qf $cfg -y $fyang" "<rpc><create-subscription><stream>NETCONF</stream><filter type=\"xpath\" select=\"event[event-class='fault']\"/></create-subscription></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]><notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0"><eventTime>20' 5
#new "restconf monitor event stream RFC8040 Sec 6.3"

View file

@ -11,7 +11,6 @@ cat <<EOF > $cfg
<config>
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
<CLICON_YANG_MODULE_MAIN>$fyang</CLICON_YANG_MODULE_MAIN>
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
@ -163,22 +162,22 @@ new "netconf validate"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag><error-type>application</error-type><error-severity>error</error-severity><error-message>Identityref validation failed, foo:bar not derived from crypto-alg</error-message></rpc-error></rpc-reply>]]>]]>$"
new "cli set crypto to mc:aes"
expectfn "$clixon_cli -1 -f $cfg -l o set crypto mc:aes" 0 "^$"
expectfn "$clixon_cli -1 -f $cfg -y $fyang -l o set crypto mc:aes" 0 "^$"
new "cli validate"
expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$"
expectfn "$clixon_cli -1 -f $cfg -y $fyang -l o validate" 0 "^$"
new "cli set crypto to aes"
expectfn "$clixon_cli -1 -f $cfg -l o set crypto aes" 0 "^$"
expectfn "$clixon_cli -1 -f $cfg -y $fyang -l o set crypto aes" 0 "^$"
new "cli validate"
expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$"
expectfn "$clixon_cli -1 -f $cfg -y $fyang -l o validate" 0 "^$"
new "cli set crypto to des:des3"
expectfn "$clixon_cli -1 -f $cfg -l o set crypto des:des3" 0 "^$"
expectfn "$clixon_cli -1 -f $cfg -y $fyang -l o set crypto des:des3" 0 "^$"
new "cli validate"
expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$"
expectfn "$clixon_cli -1 -f $cfg -y $fyang -l o validate" 0 "^$"
new "Kill backend"
# Check if still alive

View file

@ -12,7 +12,6 @@ cat <<EOF > $cfg
<config>
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
<CLICON_YANG_MODULE_MAIN>$fyang</CLICON_YANG_MODULE_MAIN>
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>

View file

@ -7,12 +7,11 @@ APPNAME=example
cfg=$dir/conf.xml
fyang=$dir/restconf.yang
# <CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
cat <<EOF > $cfg
<config>
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
<CLICON_YANG_MODULE_MAIN>$fyang</CLICON_YANG_MODULE_MAIN>
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>

View file

@ -12,7 +12,6 @@ cat <<EOF > $cfg
<config>
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>/usr/local/var</CLICON_YANG_DIR>
<CLICON_YANG_MODULE_MAIN>$fyang</CLICON_YANG_MODULE_MAIN>
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
<CLICON_BACKEND_PIDFILE>$dir/restconf.pidfile</CLICON_BACKEND_PIDFILE>
@ -60,7 +59,7 @@ new "kill old restconf daemon"
sudo pkill -u www-data clixon_restconf
new "start restconf daemon"
sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -f $cfg # -D 1
sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -f $cfg -y $fyang # -D 1
sleep 1

View file

@ -351,7 +351,7 @@ module clixon-config {
}
leaf CLICON_MODULE_LIBRARY_RFC7895 {
type boolean;
default false;
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";