* 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:
parent
782f75a7b9
commit
acb8748470
21 changed files with 369 additions and 340 deletions
33
CHANGELOG.md
33
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 <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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue