* Generilized top-level yang parsing functions

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

View file

@ -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 */
@ -518,7 +518,9 @@ main(int argc,
int xml_pretty;
char *xml_format;
char *nacm_mode;
int logdst = CLICON_LOG_SYSLOG|CLICON_LOG_STDERR;
int logdst = CLICON_LOG_SYSLOG|CLICON_LOG_STDERR;
yang_spec *yspec = NULL;
char *yang_filename = NULL;
/* In the startup, logs to stderr & syslog and debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
@ -638,8 +640,8 @@ main(int argc,
case 'g': /* config socket group */
clicon_option_str_set(h, "CLICON_SOCK_GROUP", optarg);
break;
case 'y' :{ /* Override yang module or absolute filename */
clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg);
case 'y' :{ /* Load yang spec file (override yang main module) */
yang_filename = optarg;
break;
}
case 'x' :{ /* xmldb plugin */
@ -727,18 +729,31 @@ main(int argc,
/* Connect to plugin to get a handle */
if (xmldb_connect(h) < 0)
goto done;
/* Read and parse application yang specification */
if (yang_spec_main(h) == NULL)
if ((yspec = yspec_new()) == NULL)
goto done;
clicon_dbspec_yang_set(h, yspec);
/* Read and parse application yang specification: either a module and search
* in dir, or a specific file
*/
if (yang_filename){
if (yang_spec_parse_file(h, yang_filename, clicon_yang_dir(h), yspec) < 0)
goto done;
}
else if (yang_spec_parse_module(h, clicon_yang_module_main(h),
clicon_yang_dir(h),
clicon_yang_module_revision(h),
yspec) < 0)
goto done;
/* Add system modules */
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
yang_spec_append(h, CLIXON_DATADIR, "ietf-restconf-monitoring", NULL)< 0)
yang_spec_parse_module(h, "ietf-restconf-monitoring", CLIXON_DATADIR, NULL, yspec)< 0)
goto done;
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
yang_spec_append(h, CLIXON_DATADIR, "ietf-netconf-notification", NULL)< 0)
yang_spec_parse_module(h, "ietf-netconf-notification", CLIXON_DATADIR, NULL, yspec)< 0)
goto done;
if (clicon_option_bool(h, "CLICON_MODULE_LIBRARY_RFC7895") &&
yang_spec_append(h, CLIXON_DATADIR, "ietf-yang-library", NULL)< 0)
yang_spec_parse_module(h, "ietf-yang-library", CLIXON_DATADIR, NULL, yspec)< 0)
goto done;
/* Set options: database dir and yangspec (could be hidden in connect?)*/
if (xmldb_setopt(h, "dbdir", clicon_xmldb_dir(h)) < 0)

View file

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

View file

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

View file

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

View file

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