* 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)
|
## 3.8.0 (Upcoming)
|
||||||
|
|
||||||
### Major New features
|
### Major New features
|
||||||
|
|
||||||
### API changes on existing features (you may need to change your code)
|
|
||||||
* YANG Module Library support
|
* YANG Module Library support
|
||||||
* According to RFC 7895 and implemented by ietf-yang-library.yang
|
* According to RFC 7895 and implemented by ietf-yang-library.yang
|
||||||
* Supported: module, name, revision, namespace
|
* Supported: module, name, revision, namespace
|
||||||
* Not supported: notification, deviation, module-set-id, etc.
|
* Not supported: notification, deviation, module-set-id, etc.
|
||||||
* Enabled by default, disable by resetting CLICON_MODULE_LIBRARY_RFC7895
|
* Enabled by default, disable by resetting CLICON_MODULE_LIBRARY_RFC7895
|
||||||
* Yang 1.1 notification support (RFC 7950: Sec 7.16)
|
* 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
|
* Major rewrite of event streams
|
||||||
* If you used old event callbacks API, you need to switch to the streams API
|
* If you used old event callbacks API, you need to switch to the streams API
|
||||||
* See clixon_stream.[ch]
|
* See clixon_stream.[ch]
|
||||||
|
|
@ -18,23 +22,30 @@
|
||||||
* clicon_log_register_callback()
|
* clicon_log_register_callback()
|
||||||
* subscription_add() --> stream_register()
|
* subscription_add() --> stream_register()
|
||||||
* backend_notify() and backend_notify_xml() - use stream_notify() instead
|
* 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"
|
* Example uses "NETCONF" stream instead of "ROUTING"
|
||||||
* clixon_restconf and clixon_netconf now take -D <level> as command-line option instead of just -D
|
* 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
|
* This aligns to clixon_cli and clixon_backend
|
||||||
* Application command option -S to clixon_netconf is obsolete. Use `clixon_netconf -l s` instead.
|
* 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>.
|
* 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
|
* 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.
|
* 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
|
* 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
|
* Added -l option for clixon_backend for directing syslog to stderr or stdout if running in foreground
|
||||||
|
|
||||||
### Corrected Bugs
|
### Corrected Bugs
|
||||||
|
|
|
||||||
|
|
@ -129,24 +129,24 @@ usage(clicon_handle h,
|
||||||
|
|
||||||
fprintf(stderr, "usage:%s\n"
|
fprintf(stderr, "usage:%s\n"
|
||||||
"where options are\n"
|
"where options are\n"
|
||||||
" -h\t\tHelp\n"
|
"\t-h\t\tHelp\n"
|
||||||
" -D <level>\tDebug level\n"
|
"\t-D <level>\tDebug level\n"
|
||||||
" -f <file>\tCLICON config file\n"
|
"\t-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"
|
"\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"
|
||||||
" -d <dir>\tSpecify backend plugin directory (default: %s)\n"
|
"\t-d <dir>\tSpecify backend plugin directory (default: %s)\n"
|
||||||
" -b <dir>\tSpecify XMLDB database directory\n"
|
"\t-b <dir>\tSpecify XMLDB database directory\n"
|
||||||
" -F\t\tRun in foreground, do not run as daemon\n"
|
"\t-F\t\tRun in foreground, do not run as daemon\n"
|
||||||
" -z\t\tKill other config daemon and exit\n"
|
"\t-z\t\tKill other config daemon and exit\n"
|
||||||
" -a UNIX|IPv4|IPv6\tInternal backend socket family\n"
|
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
|
||||||
" -u <path|addr>\tInternal socket domain path or IP addr (see -a)(default: %s)\n"
|
"\t-u <path|addr>\tInternal socket domain path or IP addr (see -a)(default: %s)\n"
|
||||||
" -P <file>\tPid filename (default: %s)\n"
|
"\t-P <file>\tPid filename (default: %s)\n"
|
||||||
" -1\t\tRun once and then quit (dont wait for events)\n"
|
"\t-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"
|
"\t-s <mode>\tSpecify backend startup mode: none|startup|running|init)\n"
|
||||||
" -c <file>\tLoad extra xml configuration, but don't commit.\n"
|
"\t-c <file>\tLoad extra xml configuration, but don't commit.\n"
|
||||||
" -g <group>\tClient membership required to this group (default: %s)\n"
|
"\t-g <group>\tClient membership required to this group (default: %s)\n"
|
||||||
|
|
||||||
" -y <file>\tOverride yang spec file (dont include .yang suffix)\n"
|
"\t-y <file>\tLoad yang spec file (override yang main module)\n"
|
||||||
" -x <plugin>\tXMLDB plugin\n",
|
"\t-x <plugin>\tXMLDB plugin\n",
|
||||||
argv0,
|
argv0,
|
||||||
plgdir ? plgdir : "none",
|
plgdir ? plgdir : "none",
|
||||||
confsock ? confsock : "none",
|
confsock ? confsock : "none",
|
||||||
|
|
@ -258,7 +258,7 @@ nacm_load_external(clicon_handle h)
|
||||||
}
|
}
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if ((yspec = yspec_new()) == NULL)
|
||||||
goto done;
|
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;
|
goto done;
|
||||||
fd = fileno(f);
|
fd = fileno(f);
|
||||||
/* Read configfile */
|
/* Read configfile */
|
||||||
|
|
@ -519,6 +519,8 @@ main(int argc,
|
||||||
char *xml_format;
|
char *xml_format;
|
||||||
char *nacm_mode;
|
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 */
|
/* In the startup, logs to stderr & syslog and debug flag set later */
|
||||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||||
|
|
@ -638,8 +640,8 @@ main(int argc,
|
||||||
case 'g': /* config socket group */
|
case 'g': /* config socket group */
|
||||||
clicon_option_str_set(h, "CLICON_SOCK_GROUP", optarg);
|
clicon_option_str_set(h, "CLICON_SOCK_GROUP", optarg);
|
||||||
break;
|
break;
|
||||||
case 'y' :{ /* Override yang module or absolute filename */
|
case 'y' :{ /* Load yang spec file (override yang main module) */
|
||||||
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg);
|
yang_filename = optarg;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'x' :{ /* xmldb plugin */
|
case 'x' :{ /* xmldb plugin */
|
||||||
|
|
@ -727,18 +729,31 @@ main(int argc,
|
||||||
/* Connect to plugin to get a handle */
|
/* Connect to plugin to get a handle */
|
||||||
if (xmldb_connect(h) < 0)
|
if (xmldb_connect(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Read and parse application yang specification */
|
if ((yspec = yspec_new()) == NULL)
|
||||||
if (yang_spec_main(h) == NULL)
|
|
||||||
goto done;
|
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 */
|
/* Add system modules */
|
||||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
|
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;
|
goto done;
|
||||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
|
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;
|
goto done;
|
||||||
if (clicon_option_bool(h, "CLICON_MODULE_LIBRARY_RFC7895") &&
|
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;
|
goto done;
|
||||||
/* Set options: database dir and yangspec (could be hidden in connect?)*/
|
/* Set options: database dir and yangspec (could be hidden in connect?)*/
|
||||||
if (xmldb_setopt(h, "dbdir", clicon_xmldb_dir(h)) < 0)
|
if (xmldb_setopt(h, "dbdir", clicon_xmldb_dir(h)) < 0)
|
||||||
|
|
|
||||||
|
|
@ -251,6 +251,7 @@ main(int argc, char **argv)
|
||||||
int dump_configfile_xml = 0;
|
int dump_configfile_xml = 0;
|
||||||
yang_spec *yspec;
|
yang_spec *yspec;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
char *yang_filename = NULL;
|
||||||
|
|
||||||
/* Defaults */
|
/* Defaults */
|
||||||
once = 0;
|
once = 0;
|
||||||
|
|
@ -379,8 +380,8 @@ main(int argc, char **argv)
|
||||||
case 'L' : /* Debug print dynamic CLI syntax */
|
case 'L' : /* Debug print dynamic CLI syntax */
|
||||||
logclisyntax++;
|
logclisyntax++;
|
||||||
break;
|
break;
|
||||||
case 'y' :{ /* Overwrite yang module or absolute filename */
|
case 'y' :{ /* Load yang spec file (override yang main module) */
|
||||||
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg);
|
yang_filename = optarg;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'c' :{ /* Overwrite clispec with absolute filename */
|
case 'c' :{ /* Overwrite clispec with absolute filename */
|
||||||
|
|
@ -414,8 +415,19 @@ main(int argc, char **argv)
|
||||||
*/
|
*/
|
||||||
cv_exclude_keys(clicon_cli_varonly(h));
|
cv_exclude_keys(clicon_cli_varonly(h));
|
||||||
|
|
||||||
/* Parse db specification as cli*/
|
if ((yspec = yspec_new()) == NULL)
|
||||||
if ((yspec = yang_spec_main(h)) == 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;
|
goto done;
|
||||||
if (printspec)
|
if (printspec)
|
||||||
yang_print(stdout, (yang_node*)yspec);
|
yang_print(stdout, (yang_node*)yspec);
|
||||||
|
|
@ -425,17 +437,20 @@ main(int argc, char **argv)
|
||||||
*/
|
*/
|
||||||
if (clicon_cli_genmodel(h)){
|
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 */
|
/* Create cli command tree from dbspec */
|
||||||
if (yang2cli(h, yspec, &pt, clicon_cli_genmodel_type(h)) < 0)
|
if (yang2cli(h, yspec, &pt, clicon_cli_genmodel_type(h)) < 0)
|
||||||
goto done;
|
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){
|
if ((treename = malloc(len)) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "malloc");
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
goto done;
|
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);
|
cligen_tree_add(cli_cligen(h), treename, pt);
|
||||||
|
|
||||||
if (printgen)
|
if (printgen)
|
||||||
|
|
|
||||||
|
|
@ -276,8 +276,6 @@ netconf_terminate(clicon_handle h)
|
||||||
clicon_rpc_close_session(h);
|
clicon_rpc_close_session(h);
|
||||||
if ((yspec = clicon_dbspec_yang(h)) != NULL)
|
if ((yspec = clicon_dbspec_yang(h)) != NULL)
|
||||||
yspec_free(yspec);
|
yspec_free(yspec);
|
||||||
if ((yspec = clicon_netconf_yang(h)) != NULL)
|
|
||||||
yspec_free(yspec);
|
|
||||||
event_exit();
|
event_exit();
|
||||||
clicon_handle_exit(h);
|
clicon_handle_exit(h);
|
||||||
clicon_log_exit();
|
clicon_log_exit();
|
||||||
|
|
@ -306,12 +304,12 @@ usage(clicon_handle h,
|
||||||
"\t-D <level>\tDebug level\n"
|
"\t-D <level>\tDebug level\n"
|
||||||
"\t-q\t\tQuiet: dont send hello prompt\n"
|
"\t-q\t\tQuiet: dont send hello prompt\n"
|
||||||
"\t-f <file>\tConfiguration file (mandatory)\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-a UNIX|IPv4|IPv6\tInternal backend socket family\n"
|
||||||
"\t-u <path|addr>\tInternal socket domain path or IP addr (see -a)\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-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-U <user>\tOver-ride unix user with a pseudo user for NACM.\n"
|
||||||
"\t-t <sec>\tTimeout in seconds. Quit after this time.\n",
|
"\t-t <sec>\tTimeout in seconds. Quit after this time.\n",
|
||||||
argv0,
|
argv0,
|
||||||
|
|
@ -333,6 +331,8 @@ main(int argc,
|
||||||
int logdst = CLICON_LOG_STDERR;
|
int logdst = CLICON_LOG_STDERR;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
struct timeval tv = {0,}; /* timeout */
|
struct timeval tv = {0,}; /* timeout */
|
||||||
|
yang_spec *yspec = NULL;
|
||||||
|
char *yang_filename = NULL;
|
||||||
|
|
||||||
/* Create handle */
|
/* Create handle */
|
||||||
if ((h = clicon_handle_init()) == NULL)
|
if ((h = clicon_handle_init()) == NULL)
|
||||||
|
|
@ -407,8 +407,8 @@ main(int argc,
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_NETCONF_DIR", optarg);
|
clicon_option_str_set(h, "CLICON_NETCONF_DIR", optarg);
|
||||||
break;
|
break;
|
||||||
case 'y' :{ /* Overwrite yang module or absolute filename */
|
case 'y' :{ /* Load yang spec file (override yang main module) */
|
||||||
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg);
|
yang_filename = optarg;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'U': /* Clixon 'pseudo' user */
|
case 'U': /* Clixon 'pseudo' user */
|
||||||
|
|
@ -428,12 +428,22 @@ main(int argc,
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
|
if ((yspec = yspec_new()) == NULL)
|
||||||
|
goto done;
|
||||||
|
clicon_dbspec_yang_set(h, yspec);
|
||||||
/* Parse yang database spec file */
|
/* 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;
|
goto done;
|
||||||
|
|
||||||
/* Parse netconf yang spec file */
|
/* Add netconf yang spec, used by netconf client and as internal protocol */
|
||||||
if (yang_spec_netconf(h) == NULL)
|
if (yang_spec_parse_module(h, "ietf-yang-library", CLIXON_DATADIR, NULL, yspec)< 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Initialize plugins group */
|
/* Initialize plugins group */
|
||||||
|
|
|
||||||
|
|
@ -955,15 +955,9 @@ netconf_rpc_dispatch(clicon_handle h,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *xe;
|
cxobj *xe;
|
||||||
yang_spec *yspec = NULL;
|
|
||||||
char *username;
|
char *username;
|
||||||
cxobj *xa;
|
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
|
/* Tag username on all incoming requests in case they are forwarded as internal messages
|
||||||
* This may be unecesary since not all are forwarded.
|
* This may be unecesary since not all are forwarded.
|
||||||
* It may even be wrong if something else is done with the incoming message?
|
* 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-f <file>\tConfiguration file (mandatory)\n"
|
||||||
"\t-l <s|f<file>> \tLog on (s)yslog, (f)ile (syslog is default)\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-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-a UNIX|IPv4|IPv6\tInternal backend socket family\n"
|
||||||
"\t-u <path|addr>\tInternal socket domain path or IP addr (see -a)\n",
|
"\t-u <path|addr>\tInternal socket domain path or IP addr (see -a)\n",
|
||||||
argv0,
|
argv0,
|
||||||
|
|
@ -522,6 +522,8 @@ main(int argc,
|
||||||
char *dir;
|
char *dir;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
int logdst = CLICON_LOG_SYSLOG;
|
int logdst = CLICON_LOG_SYSLOG;
|
||||||
|
yang_spec *yspec = NULL;
|
||||||
|
char *yang_filename = NULL;
|
||||||
|
|
||||||
/* In the startup, logs to stderr & debug flag set later */
|
/* In the startup, logs to stderr & debug flag set later */
|
||||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||||
|
|
@ -589,8 +591,8 @@ main(int argc,
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_RESTCONF_DIR", optarg);
|
clicon_option_str_set(h, "CLICON_RESTCONF_DIR", optarg);
|
||||||
break;
|
break;
|
||||||
case 'y' : /* yang module */
|
case 'y' : /* Load yang spec file (override yang main module) */
|
||||||
yangspec = optarg;
|
yang_filename = optarg;
|
||||||
break;
|
break;
|
||||||
case 'a': /* internal backend socket address family */
|
case 'a': /* internal backend socket address family */
|
||||||
clicon_option_str_set(h, "CLICON_SOCK_FAMILY", optarg);
|
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)
|
if (clixon_plugins_load(h, CLIXON_PLUGIN_INIT, dir, NULL) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Parse yang database spec file */
|
/* Parse main yang spec */
|
||||||
if (yang_spec_main(h) == NULL)
|
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;
|
goto done;
|
||||||
/* Add system modules */
|
/* Add system modules */
|
||||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
|
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;
|
goto done;
|
||||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
|
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;
|
goto done;
|
||||||
if (clicon_option_bool(h, "CLICON_MODULE_LIBRARY_RFC7895") &&
|
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;
|
goto done;
|
||||||
|
|
||||||
if (stream_register(h, "NETCONF", "default NETCONF event stream") < 0)
|
if (stream_register(h, "NETCONF", "default NETCONF event stream") < 0)
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ main(int argc, char **argv)
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if ((yspec = yspec_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
/* Parse yang spec from given file */
|
/* 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;
|
goto done;
|
||||||
/* Set database directory option */
|
/* Set database directory option */
|
||||||
if (xmldb_setopt(h, "dbdir", dbdir) < 0)
|
if (xmldb_setopt(h, "dbdir", dbdir) < 0)
|
||||||
|
|
|
||||||
|
|
@ -1387,7 +1387,7 @@ main(int argc,
|
||||||
db_init(db);
|
db_init(db);
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if ((yspec = yspec_new()) == NULL)
|
||||||
goto done
|
goto done
|
||||||
if (yang_parse(h, yangdir, yangmod, NULL, yspec) < 0)
|
if (yang_parse(h, NULL, yangmod, yangdir, NULL, yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (strcmp(cmd, "get")==0){
|
if (strcmp(cmd, "get")==0){
|
||||||
if (argc < 5)
|
if (argc < 5)
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/syslog.h>
|
||||||
|
|
||||||
/* clicon */
|
/* clicon */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
@ -119,7 +120,7 @@ clixon_plugin_init(clicon_handle h)
|
||||||
clicon_debug(1, "%s backend nacm", __FUNCTION__);
|
clicon_debug(1, "%s backend nacm", __FUNCTION__);
|
||||||
nacm_mode = clicon_option_str(h, "CLICON_NACM_MODE");
|
nacm_mode = clicon_option_str(h, "CLICON_NACM_MODE");
|
||||||
if (nacm_mode==NULL || strcmp(nacm_mode, "disabled") == 0){
|
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 NULL;
|
||||||
}
|
}
|
||||||
return &api;
|
return &api;
|
||||||
|
|
|
||||||
|
|
@ -164,12 +164,6 @@ int clicon_quiet_mode_set(clicon_handle h, int val);
|
||||||
yang_spec * clicon_dbspec_yang(clicon_handle h);
|
yang_spec * clicon_dbspec_yang(clicon_handle h);
|
||||||
int clicon_dbspec_yang_set(clicon_handle h, struct yang_spec *ys);
|
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);
|
plghndl_t clicon_xmldb_plugin_get(clicon_handle h);
|
||||||
int clicon_xmldb_plugin_set(clicon_handle h, plghndl_t handle);
|
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);
|
int yn_insert(yang_node *yn_parent, yang_stmt *ys_child);
|
||||||
yang_stmt *yn_each(yang_node *yn, yang_stmt *ys);
|
yang_stmt *yn_each(yang_node *yn, yang_stmt *ys);
|
||||||
char *yang_key2str(int keyword);
|
char *yang_key2str(int keyword);
|
||||||
|
char *yang_main_module_name(yang_spec *ysp);
|
||||||
char *yarg_prefix(yang_stmt *ys);
|
char *yarg_prefix(yang_stmt *ys);
|
||||||
char *yarg_id(yang_stmt *ys);
|
char *yarg_id(yang_stmt *ys);
|
||||||
int yang_nodeid_split(char *nodeid, char **prefix, char **id);
|
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 yang_print_cbuf(cbuf *cb, yang_node *yn, int marginal);
|
||||||
int ys_populate(yang_stmt *ys, void *arg);
|
int ys_populate(yang_stmt *ys, void *arg);
|
||||||
yang_stmt *yang_parse_file(int fd, const char *name, yang_spec *ysp);
|
yang_stmt *yang_parse_file(int fd, const char *name, yang_spec *ysp);
|
||||||
int yang_parse(clicon_handle h, const char *yang_dir,
|
int yang_parse(clicon_handle h, const char *filename,
|
||||||
const char *module, const char *revision, yang_spec *ysp);
|
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,
|
int yang_apply(yang_node *yn, enum rfc_6020 key, yang_applyfn_t fn,
|
||||||
void *arg);
|
void *arg);
|
||||||
int yang_abs_schema_nodeid(yang_spec *yspec, char *schema_nodeid,
|
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 ys_parse_sub(yang_stmt *ys, char *extra);
|
||||||
int yang_mandatory(yang_stmt *ys);
|
int yang_mandatory(yang_stmt *ys);
|
||||||
int yang_config(yang_stmt *ys);
|
int yang_config(yang_stmt *ys);
|
||||||
yang_spec *yang_spec_netconf(clicon_handle h);
|
int yang_spec_parse_module(clicon_handle h, char *module, char *dir, char *revision, yang_spec *yspec);
|
||||||
yang_spec *yang_spec_main(clicon_handle h);
|
int yang_spec_parse_file(clicon_handle h, char *filename, char *dir, yang_spec *yspec);
|
||||||
int yang_spec_append(clicon_handle h, char *yang_dir, char *yang_module, char *yang_revision);
|
|
||||||
cvec *yang_arg2cvec(yang_stmt *ys, char *delimi);
|
cvec *yang_arg2cvec(yang_stmt *ys, char *delimi);
|
||||||
int yang_key_match(yang_node *yn, char *name);
|
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 (xml){ /* Read clixon yang file */
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if ((yspec = yspec_new()) == NULL)
|
||||||
goto done;
|
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;
|
goto done;
|
||||||
/* Read configfile */
|
/* Read configfile */
|
||||||
if (clicon_option_readfile_xml(copt, configfile, yspec) < 0)
|
if (clicon_option_readfile_xml(copt, configfile, yspec) < 0)
|
||||||
|
|
@ -571,58 +571,6 @@ clicon_dbspec_yang_set(clicon_handle h,
|
||||||
return 0;
|
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 */
|
/*! Get xmldb datastore plugin handle, as used by dlopen/dlsym/dlclose */
|
||||||
plghndl_t
|
plghndl_t
|
||||||
clicon_xmldb_plugin_get(clicon_handle h)
|
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
|
/*! 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
|
* Also add parent to child as up-pointer
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -607,7 +609,6 @@ yang_find_schemanode(yang_node *yn,
|
||||||
return ysmatch;
|
return ysmatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Find first matching data node in all (sub)modules in a yang spec
|
/*! Find first matching data node in all (sub)modules in a yang spec
|
||||||
*
|
*
|
||||||
* @param[in] ysp Yang specification
|
* @param[in] ysp Yang specification
|
||||||
|
|
@ -756,7 +757,22 @@ yang_key2str(int keyword)
|
||||||
return (char*)clicon_int2str(ykmap, 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
|
* @param[in] ys Any yang statement in a yang tree
|
||||||
* @retval ymod The top module or sub-module
|
* @retval ymod The top module or sub-module
|
||||||
* @see ys_spec
|
* @see ys_spec
|
||||||
|
|
@ -1612,7 +1628,8 @@ yang_expand(yang_node *yn)
|
||||||
* Calling order:
|
* Calling order:
|
||||||
* yang_parse # Parse top-level yang module. Expand and populate yang tree
|
* 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_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
|
* yang_parse_str # Set up yacc parser and call it given a string
|
||||||
* clixon_yang_parseparse # Actual yang parsing using yacc
|
* clixon_yang_parseparse # Actual yang parsing using yacc
|
||||||
*/
|
*/
|
||||||
|
|
@ -1712,49 +1729,6 @@ yang_parse_file(int fd,
|
||||||
return ymod; /* top-level (sub)module */
|
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
|
/*! No specific revision give. Match a yang file given dir and module
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] yang_dir Directory where all YANG module files reside
|
* @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;
|
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
|
/*! Parse one yang module then go through (sub)modules and parse them recursively
|
||||||
*
|
*
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
|
|
@ -1818,68 +1868,44 @@ yang_parse_find_match(const char *yang_dir,
|
||||||
* Calling order:
|
* Calling order:
|
||||||
* yang_parse # Parse top-level yang module. Expand and populate yang tree
|
* 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_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
|
* yang_parse_str # Set up yacc parser and call it given a string
|
||||||
* clixon_yang_parseparse # Actual yang parsing using yacc
|
* clixon_yang_parseparse # Actual yang parsing using yacc
|
||||||
*/
|
*/
|
||||||
static yang_stmt *
|
static int
|
||||||
yang_parse_recurse(const char *yang_dir,
|
yang_parse_recurse(yang_stmt *ymod,
|
||||||
const char *module,
|
const char *dir,
|
||||||
const char *revision,
|
|
||||||
yang_spec *ysp)
|
yang_spec *ysp)
|
||||||
{
|
{
|
||||||
|
int retval = -1;
|
||||||
yang_stmt *yi = NULL; /* import */
|
yang_stmt *yi = NULL; /* import */
|
||||||
yang_stmt *ymod = NULL;
|
|
||||||
yang_stmt *yrev;
|
yang_stmt *yrev;
|
||||||
char *modname;
|
char *submodule;
|
||||||
char *subrevision;
|
char *subrevision;
|
||||||
cbuf *fbuf = NULL;
|
yang_stmt *subymod;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* go through all import statements of ysp (or its module) */
|
/* go through all import statements of ysp (or its module) */
|
||||||
while ((yi = yn_each((yang_node*)ymod, yi)) != NULL){
|
while ((yi = yn_each((yang_node*)ymod, yi)) != NULL){
|
||||||
if (yi->ys_keyword != Y_IMPORT)
|
if (yi->ys_keyword != Y_IMPORT)
|
||||||
continue;
|
continue;
|
||||||
modname = yi->ys_argument;
|
submodule = yi->ys_argument;
|
||||||
if ((yrev = yang_find((yang_node*)yi, Y_REVISION_DATE, NULL)) != NULL)
|
if ((yrev = yang_find((yang_node*)yi, Y_REVISION_DATE, NULL)) != NULL)
|
||||||
subrevision = yrev->ys_argument;
|
subrevision = yrev->ys_argument;
|
||||||
else
|
else
|
||||||
subrevision = NULL;
|
subrevision = NULL;
|
||||||
if (yang_find((yang_node*)ysp, Y_MODULE, modname) == NULL)
|
if (yang_find((yang_node*)ysp, Y_MODULE, submodule) == NULL)
|
||||||
/* recursive call */
|
/* 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;
|
ymod = NULL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (fbuf)
|
return retval; /* top-level (sub)module */
|
||||||
cbuf_free(fbuf);
|
|
||||||
return ymod; /* top-level (sub)module */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -1929,7 +1955,8 @@ ys_schemanode_check(yang_stmt *ys,
|
||||||
*
|
*
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] yang_dir Directory where all YANG module files reside (except mainfile)
|
* @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[in] revision Main module revision date string or NULL
|
||||||
* @param[out] ysp Yang specification. Should have been created by caller using yspec_new
|
* @param[out] ysp Yang specification. Should have been created by caller using yspec_new
|
||||||
* @retval 0 Everything OK
|
* @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 # Parse top-level yang module. Expand and populate yang tree
|
||||||
* yang_parse_recurse # Parse one yang module, go through its (sub)modules,
|
* yang_parse_recurse # Parse one yang module, go through its (sub)modules,
|
||||||
* parse them and then recursively parse them
|
* 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
|
* yang_parse_str # Set up yacc parser and call it given a string
|
||||||
* clixon_yang_parseparse # Actual yang parsing using yacc
|
* clixon_yang_parseparse # Actual yang parsing using yacc
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
yang_parse(clicon_handle h,
|
yang_parse(clicon_handle h,
|
||||||
const char *yang_dir,
|
const char *filename,
|
||||||
const char *mainmodule,
|
const char *module,
|
||||||
|
const char *dir,
|
||||||
const char *revision,
|
const char *revision,
|
||||||
yang_spec *ysp)
|
yang_spec *ysp)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
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. */
|
modnr = ysp->yp_len;
|
||||||
if ((ymod = yang_parse_recurse(yang_dir, mainmodule, revision, ysp)) == NULL)
|
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;
|
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 */
|
/* 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;
|
goto done;
|
||||||
|
|
||||||
/* Step 3: Resolve all types: populate type caches. Requires eg length/range cvecs
|
/* Step 3: Resolve all types: populate type caches. Requires eg length/range cvecs
|
||||||
* from ys_populate step
|
* 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
|
/* 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
|
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 */
|
/* 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;
|
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)
|
if (yang_augment_spec(ysp) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* sanity check of schemanode references, need more here */
|
/* 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;
|
goto done;
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -2405,94 +2450,84 @@ yang_config(yang_stmt *ys)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Parse netconf yang spec, used by netconf client and as internal protocol
|
/*! Parse yang specification and its dependencies recursively given module
|
||||||
* @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
|
* @param[in] h clicon handle
|
||||||
*/
|
* @param[in] module Module name, or absolute filename (including dir)
|
||||||
yang_spec*
|
* @param[in] dir Directory where to look for modules and sub-modules
|
||||||
yang_spec_main(clicon_handle h)
|
* @param[in] revision Revision, or NULL
|
||||||
{
|
* @param[in,out] yspec Modules parse are added to this yangspec
|
||||||
yang_spec *yspec = NULL;
|
* @retval 0 OK
|
||||||
char *yang_module;
|
* @retval -1 Error
|
||||||
char *yang_revision;
|
* @see yang_spec_parse_file
|
||||||
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
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
yang_spec_append(clicon_handle h,
|
yang_spec_parse_module(clicon_handle h,
|
||||||
char *yang_dir,
|
char *module,
|
||||||
char *yang_module,
|
char *dir,
|
||||||
char *yang_revision)
|
char *revision,
|
||||||
|
yang_spec *yspec)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_spec *yspec = NULL;
|
|
||||||
yang_spec *yspec0;
|
|
||||||
yang_stmt *ym = NULL; /* module */
|
|
||||||
|
|
||||||
if ((yspec0 = clicon_dbspec_yang(h)) == NULL){
|
if (yspec == NULL){
|
||||||
clicon_err(OE_YANG, ENOENT, "yang spec not found");
|
clicon_err(OE_YANG, EINVAL, "yang spec is NULL");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if (module == NULL){
|
||||||
goto done;
|
clicon_err(OE_YANG, EINVAL, "yang module not set");
|
||||||
if (yang_parse(h, yang_dir, yang_module, yang_revision, yspec) < 0){
|
|
||||||
yspec_free(yspec); yspec = NULL;
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
while ((ym = yn_each((yang_node*)yspec, ym)) != NULL)
|
/* Sanity check - use yang_spec_parse_file instead */
|
||||||
if (yn_insert((yang_node*)yspec0, ym) < 0)
|
if (strlen(module) && module[0] == '/'){
|
||||||
|
clicon_err(OE_YANG, EINVAL, "yang module illegal format");
|
||||||
goto done;
|
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;
|
retval = 0;
|
||||||
done:
|
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_free(yspec);
|
||||||
|
yspec = NULL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ cat <<EOF > $cfg
|
||||||
<config>
|
<config>
|
||||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
<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_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
<CLICON_RESTCONF_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
|
<CLICON_RESTCONF_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
|
||||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ cat <<EOF > $cfg
|
||||||
<config>
|
<config>
|
||||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
<CLICON_YANG_DIR>/usr/local/share/example/yang</CLICON_YANG_DIR>
|
<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_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||||
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
|
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ cat <<EOF > $cfg
|
||||||
<config>
|
<config>
|
||||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
<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_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
<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
|
sudo pkill -u www-data clixon_restconf
|
||||||
|
|
||||||
new "start restconf daemon"
|
new "start restconf daemon"
|
||||||
sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -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
|
sleep 1
|
||||||
|
|
||||||
|
|
@ -110,7 +109,7 @@ expectwait "$clixon_netconf -qf $cfg -y $fyang" '<rpc><create-subscription><stre
|
||||||
new "netconf NETCONF subscription with simple filter"
|
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
|
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
|
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"
|
#new "restconf monitor event stream RFC8040 Sec 6.3"
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ cat <<EOF > $cfg
|
||||||
<config>
|
<config>
|
||||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
|
<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_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||||
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
|
<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>]]>]]>$"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
new "Kill backend"
|
||||||
# Check if still alive
|
# Check if still alive
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ cat <<EOF > $cfg
|
||||||
<config>
|
<config>
|
||||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
<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_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||||
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
|
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,11 @@ APPNAME=example
|
||||||
cfg=$dir/conf.xml
|
cfg=$dir/conf.xml
|
||||||
fyang=$dir/restconf.yang
|
fyang=$dir/restconf.yang
|
||||||
|
|
||||||
# <CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
|
||||||
cat <<EOF > $cfg
|
cat <<EOF > $cfg
|
||||||
<config>
|
<config>
|
||||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
<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_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||||
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
|
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ cat <<EOF > $cfg
|
||||||
<config>
|
<config>
|
||||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
<CLICON_YANG_DIR>/usr/local/var</CLICON_YANG_DIR>
|
<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_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
|
||||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
<CLICON_BACKEND_PIDFILE>$dir/restconf.pidfile</CLICON_BACKEND_PIDFILE>
|
<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
|
sudo pkill -u www-data clixon_restconf
|
||||||
|
|
||||||
new "start restconf daemon"
|
new "start restconf daemon"
|
||||||
sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -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
|
sleep 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -351,9 +351,9 @@ module clixon-config {
|
||||||
}
|
}
|
||||||
leaf CLICON_MODULE_LIBRARY_RFC7895 {
|
leaf CLICON_MODULE_LIBRARY_RFC7895 {
|
||||||
type boolean;
|
type boolean;
|
||||||
default false;
|
default true;
|
||||||
description "Enable RFC 7895 YANG Module library support as state
|
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";
|
netconf get or restconf GET";
|
||||||
}
|
}
|
||||||
leaf CLICON_STREAM_DISCOVERY_RFC5277 {
|
leaf CLICON_STREAM_DISCOVERY_RFC5277 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue