* RESTCONF configuration is unified and moved from clixon-config.yang to clixon-restconf.yang

* Except `CLICON_RESTCONF_DIR` which remains in clixon-config.yang due to bootstrapping
    * -d <dir> option removed
  * This applies to both evhtp and fcgi RESTCONF
    * Both can also read config from backend, and be started from backend
  * You may need to move config as follows (from clixon-config.yang to clixon-restconf.yang)
    * CLICON_RESTCONF_PRETTY -> restconf/pretty
    * CLICON_RESTCONF_PATH -> restconf/fcgi-path
This commit is contained in:
Olof hagsand 2021-02-11 13:46:34 +01:00
parent 72dd31395e
commit c64878fd4a
58 changed files with 293 additions and 199 deletions

View file

@ -60,6 +60,7 @@
#include <signal.h>
#include <syslog.h>
#include <fcntl.h>
#include <pwd.h>
#include <time.h>
#include <limits.h>
#include <signal.h>
@ -175,15 +176,13 @@ usage(clicon_handle h,
"\t-E <dir> \t Extra configuration file directory\n"
"\t-l <s|f<file>> \t Log on (s)yslog, (f)ile (syslog is default)\n"
"\t-p <dir>\t Yang directory path (see CLICON_YANG_DIR)\n"
"\t-d <dir>\t Specify restconf plugin directory dir (default: %s)\n"
"\t-y <file>\t Load yang spec file (override yang main module)\n"
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
"\t-u <path|addr>\t Internal socket domain path or IP addr (see -a)\n"
"\t-r \t\t Do not drop privileges if run as root\n"
"\t-o \"<option>=<value>\" Give configuration option overriding config file (see clixon-config.yang)\n",
argv0,
clicon_restconf_dir(h)
argv0
);
exit(0);
}
@ -208,7 +207,6 @@ main(int argc,
yang_stmt *yspec = NULL;
char *stream_path;
int finish = 0;
int start = 1;
char *str;
clixon_plugin *cp = NULL;
uint32_t id = 0;
@ -217,9 +215,14 @@ main(int argc,
size_t cligen_bufthreshold;
int dbg = 0;
int drop_privileges = 1;
cxobj *xconfig = NULL;
cxobj *xrestconf = NULL;
int ret;
cxobj *xrestconf1 = NULL; /* Local config file */
cxobj *xconfig2 = NULL;
cxobj *xrestconf2 = NULL; /* Config from backend */
int configure_done = 0; /* First try local then backend */
cvec *nsc = NULL;
cxobj *xerr = NULL;
struct passwd *pw;
/* In the startup, logs to stderr & debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
@ -239,7 +242,7 @@ main(int argc,
if (sscanf(optarg, "%d", &dbg) != 1)
usage(h, argv[0]);
break;
case 'f': /* override config file */
case 'f': /* override config file */
if (!strlen(optarg))
usage(h, argv[0]);
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
@ -249,14 +252,14 @@ main(int argc,
usage(h, argv[0]);
clicon_option_str_set(h, "CLICON_CONFIGDIR", optarg);
break;
case 'l': /* Log destination: s|e|o */
if ((logdst = clicon_log_opt(optarg[0])) < 0)
case 'l': /* Log destination: s|e|o */
if ((logdst = clicon_log_opt(optarg[0])) < 0)
usage(h, argv[0]);
if (logdst == CLICON_LOG_FILE &&
strlen(optarg)>1 &&
clicon_log_file(optarg+1) < 0)
goto done;
break;
break;
} /* switch getopt */
/*
* Logs, error and debug to stderr or syslog, set debug level
@ -298,11 +301,6 @@ main(int argc,
if (clicon_option_add(h, "CLICON_YANG_DIR", optarg) < 0)
goto done;
break;
case 'd': /* Plugin directory */
if (!strlen(optarg))
usage(h, argv[0]);
clicon_option_str_set(h, "CLICON_RESTCONF_DIR", optarg);
break;
case 'y' : /* Load yang spec file (override yang main module) */
clicon_option_str_set(h, "CLICON_YANG_MAIN_FILE", optarg);
break;
@ -390,10 +388,11 @@ main(int argc,
if (yang_spec_load_dir(h, str, yspec) < 0)
goto done;
}
/* Load clixon lib yang module */
if (yang_spec_parse_module(h, "clixon-lib", NULL, yspec) < 0)
goto done;
/* Load yang module library, RFC7895 */
/* Load yang module library, RFC7895 */
if (yang_modules_init(h) < 0)
goto done;
@ -406,37 +405,77 @@ main(int argc,
goto done;
/* Add system modules */
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
yang_spec_parse_module(h, "ietf-restconf-monitoring", NULL, yspec)< 0)
goto done;
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
yang_spec_parse_module(h, "clixon-rfc5277", NULL, yspec)< 0)
goto done;
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC8040") &&
yang_spec_parse_module(h, "ietf-restconf-monitoring", NULL, yspec)< 0)
goto done;
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277") &&
yang_spec_parse_module(h, "clixon-rfc5277", NULL, yspec)< 0)
goto done;
/* Here all modules are loaded
* Compute and set canonical namespace context
*/
if (xml_nsctx_yangspec(yspec, &nsctx_global) < 0)
goto done;
if (clicon_nsctx_global_set(h, nsctx_global) < 0)
goto done;
/* Here all modules are loaded
* Compute and set canonical namespace context
*/
if (xml_nsctx_yangspec(yspec, &nsctx_global) < 0)
goto done;
if (clicon_nsctx_global_set(h, nsctx_global) < 0)
goto done;
/* Dump configuration options on debug */
/* Dump configuration options on debug */
if (dbg)
clicon_option_dump(h, dbg);
/* Call start function in all plugins before we go interactive */
if (clixon_plugin_start_all(h) < 0)
goto done;
xconfig = clicon_conf_xml(h); /* Get local config */
if ((xrestconf = xpath_first(xconfig, NULL, "restconf")) != NULL){
if ((ret = restconf_config_init(h, xrestconf)) < 0)
goto done;
if (ret == 0){
clicon_err(OE_DAEMON, EFAULT, "Restconf daemon disabled in config");
goto done;
}
}
if (clixon_plugin_start_all(h) < 0)
goto done;
/* First try to get restconf config from local config-file */
if ((xrestconf1 = clicon_conf_restconf(h)) != NULL){
if ((ret = restconf_config_init(h, xrestconf1)) < 0)
goto done;
if (ret == 1)
configure_done = 1;
}
/* If no local config, or it is disabled, try to query backend of config. */
if (!configure_done){
/* Loop to wait for backend starting, try again if not done */
while (1){
if (clicon_hello_req(h, &id) < 0){
if (errno == ENOENT){
fprintf(stderr, "waiting");
sleep(1);
continue;
}
clicon_err(OE_UNIX, errno, "clicon_session_id_get");
goto done;
}
clicon_session_id_set(h, id);
break;
}
if ((nsc = xml_nsctx_init(NULL, CLIXON_RESTCONF_NS)) == NULL)
goto done;
if ((pw = getpwuid(getuid())) == NULL){
clicon_err(OE_UNIX, errno, "getpwuid");
goto done;
}
if (clicon_rpc_get_config(h, pw->pw_name, "running", "/restconf", nsc, &xconfig2) < 0)
goto done;
if ((xerr = xpath_first(xconfig2, NULL, "/rpc-error")) != NULL){
clixon_netconf_error(xerr, "Get backend restconf config", NULL);
goto done;
}
/* Extract restconf configuration */
if ((xrestconf2 = xpath_first(xconfig2, nsc, "restconf")) != NULL){
if ((ret = restconf_config_init(h, xrestconf1)) < 0)
goto done;
if (ret == 1)
configure_done = 1;
}
}
if (!configure_done){ /* Query backend of config. */
clicon_err(OE_DAEMON, EFAULT, "Restconf daemon config not found or disabled");
goto done;
}
/* XXX see restconf_config_init access directly */
if ((sockpath = clicon_option_str(h, "CLICON_RESTCONF_PATH")) == NULL){
clicon_err(OE_CFG, errno, "No CLICON_RESTCONF_PATH in clixon configure file");
goto done;
@ -486,17 +525,6 @@ main(int argc,
}
clicon_debug(1, "------------");
if (start == 0){
/* Send hello request to backend to get session-id back
* This is done once at the beginning of the session and then this is
* used by the client, even though new TCP sessions are created for
* each message sent to the backend.
*/
if (clicon_hello_req(h, &id) < 0)
goto done;
clicon_session_id_set(h, id);
start++;
}
/* Translate from FCGI parameter form to Clixon runtime data
* XXX: potential name collision?
*/
@ -555,6 +583,10 @@ main(int argc,
} /* while */
retval = 0;
done:
if (xconfig2)
xml_free(xconfig2);
if (nsc)
cvec_free(nsc);
stream_child_freeall(h);
restconf_terminate(h);
return retval;