diff --git a/CHANGELOG.md b/CHANGELOG.md index 064f7bcf..13d7981c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 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. * The options stand for e:stderr, o:stdout, s: syslog, f:file * Added file logging (`-l f` or `-l f`) 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 diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c index 053b6d98..43e0cdbb 100644 --- a/apps/backend/backend_main.c +++ b/apps/backend/backend_main.c @@ -129,24 +129,24 @@ usage(clicon_handle h, fprintf(stderr, "usage:%s\n" "where options are\n" - " -h\t\tHelp\n" - " -D \tDebug level\n" - " -f \tCLICON config file\n" - " -l > \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 \tSpecify backend plugin directory (default: %s)\n" - " -b \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 \tInternal socket domain path or IP addr (see -a)(default: %s)\n" - " -P \tPid filename (default: %s)\n" - " -1\t\tRun once and then quit (dont wait for events)\n" - " -s \tSpecify backend startup mode: none|startup|running|init (replaces -IRCr\n" - " -c \tLoad extra xml configuration, but don't commit.\n" - " -g \tClient membership required to this group (default: %s)\n" + "\t-h\t\tHelp\n" + "\t-D \tDebug level\n" + "\t-f \tCLICON config file\n" + "\t-l (s|e|o|f) 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 \tSpecify backend plugin directory (default: %s)\n" + "\t-b \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 \tInternal socket domain path or IP addr (see -a)(default: %s)\n" + "\t-P \tPid filename (default: %s)\n" + "\t-1\t\tRun once and then quit (dont wait for events)\n" + "\t-s \tSpecify backend startup mode: none|startup|running|init)\n" + "\t-c \tLoad extra xml configuration, but don't commit.\n" + "\t-g \tClient membership required to this group (default: %s)\n" - " -y \tOverride yang spec file (dont include .yang suffix)\n" - " -x \tXMLDB plugin\n", + "\t-y \tLoad yang spec file (override yang main module)\n" + "\t-x \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 */ @@ -518,7 +518,9 @@ main(int argc, int xml_pretty; char *xml_format; char *nacm_mode; - int logdst = CLICON_LOG_SYSLOG|CLICON_LOG_STDERR; + 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) diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index f2d2de3a..f5881713 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -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 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); @@ -424,18 +436,21 @@ main(int argc, char **argv) * the only one. */ if (clicon_cli_genmodel(h)){ - parse_tree pt = {0,}; /* cli parse tree */ + 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) diff --git a/apps/netconf/netconf_main.c b/apps/netconf/netconf_main.c index 4fa50b29..f34f572c 100644 --- a/apps/netconf/netconf_main.c +++ b/apps/netconf/netconf_main.c @@ -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 \tDebug level\n" "\t-q\t\tQuiet: dont send hello prompt\n" "\t-f \tConfiguration file (mandatory)\n" - "\t-l > \tLog on std(e)rr, std(o)ut, (s)yslog, (f)ile (syslog is default)\n" + "\t-l (e|o|s|f) \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 \tInternal socket domain path or IP addr (see -a)\n" "\t-d \tSpecify netconf plugin directory dir (default: %s)\n" - "\t-y \tOverride yang spec file (dont include .yang suffix)\n" + "\t-y \tLoad yang spec file (override yang main module)\n" "\t-U \tOver-ride unix user with a pseudo user for NACM.\n" "\t-t \tTimeout in seconds. Quit after this time.\n", argv0, @@ -333,7 +331,9 @@ 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) return -1; @@ -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,13 +428,23 @@ 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) - goto done; - - /* Parse netconf yang spec file */ - if (yang_spec_netconf(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; + + /* 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 */ if ((dir = clicon_netconf_dir(h)) != NULL) diff --git a/apps/netconf/netconf_rpc.c b/apps/netconf/netconf_rpc.c index ec534063..2da03ef7 100644 --- a/apps/netconf/netconf_rpc.c +++ b/apps/netconf/netconf_rpc.c @@ -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? diff --git a/apps/restconf/restconf_main.c b/apps/restconf/restconf_main.c index a308315c..3bd4584c 100644 --- a/apps/restconf/restconf_main.c +++ b/apps/restconf/restconf_main.c @@ -494,7 +494,7 @@ usage(clicon_handle h, "\t-f \tConfiguration file (mandatory)\n" "\t-l > \tLog on (s)yslog, (f)ile (syslog is default)\n" "\t-d \tSpecify restconf plugin directory dir (default: %s)\n" - "\t-y \tOverride yang spec file (dont include .yang suffix)\n" + "\t-y \tLoad yang spec file (override yang main module)\n" "\t-a UNIX|IPv4|IPv6\tInternal backend socket family\n" "\t-u \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) diff --git a/datastore/datastore_client.c b/datastore/datastore_client.c index bdcd4ac5..7af411d2 100644 --- a/datastore/datastore_client.c +++ b/datastore/datastore_client.c @@ -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) diff --git a/datastore/text/clixon_xmldb_text.c b/datastore/text/clixon_xmldb_text.c index 299c2f22..2ca71910 100644 --- a/datastore/text/clixon_xmldb_text.c +++ b/datastore/text/clixon_xmldb_text.c @@ -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) diff --git a/example/example_backend_nacm.c b/example/example_backend_nacm.c index f484362e..3814a975 100644 --- a/example/example_backend_nacm.c +++ b/example/example_backend_nacm.c @@ -44,6 +44,7 @@ #include #include #include +#include /* clicon */ #include @@ -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; diff --git a/lib/clixon/clixon_options.h b/lib/clixon/clixon_options.h index 1f95c73a..738b2249 100644 --- a/lib/clixon/clixon_options.h +++ b/lib/clixon/clixon_options.h @@ -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); diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index 13ad5758..465fa1a6 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -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); diff --git a/lib/src/clixon_options.c b/lib/src/clixon_options.c index 7b97439f..d44f4df6 100644 --- a/lib/src/clixon_options.c +++ b/lib/src/clixon_options.c @@ -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) diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index 874f3256..8adbfdc1 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -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 @@ -1611,8 +1627,9 @@ yang_expand(yang_node *yn) * @retval NULL Error encountered * 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_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 */ @@ -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; } } - done: - if (fbuf) - cbuf_free(fbuf); - return ymod; /* top-level (sub)module */ + retval = 0; + done: + 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 */ + 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. */ - if ((ymod = yang_parse_recurse(yang_dir, mainmodule, revision, ysp)) == NULL) + /* 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) - goto done; + for (i=modnr; iyp_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; iyp_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,17 +2018,20 @@ yang_parse(clicon_handle h, */ /* Step 4: Macro expansion of all grouping/uses pairs. Expansion needs marking */ - if (yang_expand((yang_node*)ysp) < 0) - goto done; - yang_apply((yang_node*)ymod, -1, ys_flag_reset, (void*)YANG_FLAG_MARK); + for (i=modnr; iyp_len; i++){ + if (yang_expand((yang_node*)ysp->yp_stmt[i]) < 0) + goto done; + 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) - goto done; + for (i=modnr; iyp_len; i++) + if (yang_apply((yang_node*)ysp->yp_stmt[i], -1, ys_schemanode_check, NULL) < 0) + goto done; retval = 0; done: @@ -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 - * @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 +/*! Parse yang specification and its dependencies recursively given module + * @param[in] h clicon handle + * @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"); + int retval = -1; + + 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) - goto done; - yspec->yp_len = 0; - retval = 0; - done: - if (yspec) + /* Sanity check - use yang_spec_parse_file instead */ + if (strlen(module) && module[0] == '/'){ + clicon_err(OE_YANG, EINVAL, "yang module illegal format"); + goto done; + } + 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: + 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; } diff --git a/test/test_auth.sh b/test/test_auth.sh index d54609a8..6a16a318 100755 --- a/test/test_auth.sh +++ b/test/test_auth.sh @@ -15,7 +15,6 @@ cat < $cfg $cfg /usr/local/share/clixon - $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/restconf /usr/local/lib/$APPNAME/cli diff --git a/test/test_auth_ext.sh b/test/test_auth_ext.sh index 0d5d9dda..3d164dff 100755 --- a/test/test_auth_ext.sh +++ b/test/test_auth_ext.sh @@ -18,7 +18,6 @@ cat < $cfg $cfg /usr/local/share/example/yang - $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/backend example_backend.so$ diff --git a/test/test_event.sh b/test/test_event.sh index 65cdbc4c..61c198b7 100755 --- a/test/test_event.sh +++ b/test/test_event.sh @@ -13,7 +13,6 @@ cat < $cfg $cfg /usr/local/share/clixon - $fyang false /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/lib/$APPNAME/backend @@ -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" 'NETCONF]]>]]>" '^]]>]]>20' 5 -new "netconf NETCONF subscription with filter classfier" +new "netconf NETCONF subscription with filter classifier" expectwait "$clixon_netconf -qf $cfg -y $fyang" "NETCONF]]>]]>" '^]]>]]>20' 5 #new "restconf monitor event stream RFC8040 Sec 6.3" diff --git a/test/test_identity.sh b/test/test_identity.sh index 684d7416..8d7bea7f 100755 --- a/test/test_identity.sh +++ b/test/test_identity.sh @@ -11,7 +11,6 @@ cat < $cfg $cfg $dir - $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/backend example_backend.so$ @@ -163,22 +162,22 @@ new "netconf validate" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^operation-failedapplicationerrorIdentityref validation failed, foo:bar not derived from crypto-alg]]>]]>$" 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 diff --git a/test/test_netconf.sh b/test/test_netconf.sh index f662705c..29b53581 100755 --- a/test/test_netconf.sh +++ b/test/test_netconf.sh @@ -12,7 +12,6 @@ cat < $cfg $cfg /usr/local/share/$APPNAME/yang - $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/backend example_backend.so$ diff --git a/test/test_restconf.sh b/test/test_restconf.sh index 4ca2aa76..ff1cfb4b 100755 --- a/test/test_restconf.sh +++ b/test/test_restconf.sh @@ -7,12 +7,11 @@ APPNAME=example cfg=$dir/conf.xml fyang=$dir/restconf.yang -# example cat < $cfg $cfg /usr/local/share/$APPNAME/yang - $fyang + example /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/backend example_backend.so$ diff --git a/test/test_restconf2.sh b/test/test_restconf2.sh index 6780b6d2..5f796d35 100755 --- a/test/test_restconf2.sh +++ b/test/test_restconf2.sh @@ -12,7 +12,6 @@ cat < $cfg $cfg /usr/local/var - $fyang false /usr/local/var/$APPNAME/$APPNAME.sock $dir/restconf.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 diff --git a/yang/clixon-config@2018-04-30.yang b/yang/clixon-config@2018-04-30.yang index f0f7ce68..676276d1 100644 --- a/yang/clixon-config@2018-04-30.yang +++ b/yang/clixon-config@2018-04-30.yang @@ -351,9 +351,9 @@ 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. Ifenabled, module info will appear when doing + data. If enabled, module info will appear when doing netconf get or restconf GET"; } leaf CLICON_STREAM_DISCOVERY_RFC5277 {