restconf plugins
This commit is contained in:
parent
b82a8bae26
commit
64f197cb00
7 changed files with 247 additions and 34 deletions
|
|
@ -53,8 +53,7 @@
|
||||||
#include "netconf_lib.h"
|
#include "netconf_lib.h"
|
||||||
#include "netconf_plugin.h"
|
#include "netconf_plugin.h"
|
||||||
|
|
||||||
/*
|
/*! Unload a plugin
|
||||||
* Unload a plugin
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
plugin_unload(clicon_handle h, void *handle)
|
plugin_unload(clicon_handle h, void *handle)
|
||||||
|
|
@ -112,9 +111,7 @@ static int nplugins = 0;
|
||||||
static plghndl_t *plugins = NULL;
|
static plghndl_t *plugins = NULL;
|
||||||
static netconf_reg_t *deps = NULL;
|
static netconf_reg_t *deps = NULL;
|
||||||
|
|
||||||
/*
|
/*! Load all plugins you can find in CLICON_NETCONF_DIR
|
||||||
* netconf_plugin_load
|
|
||||||
* Load allplugins you can find in CLICON_NETCONF_DIR
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_plugin_load(clicon_handle h)
|
netconf_plugin_load(clicon_handle h)
|
||||||
|
|
@ -160,6 +157,7 @@ quit:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Unload all netconf plugins */
|
||||||
int
|
int
|
||||||
netconf_plugin_unload(clicon_handle h)
|
netconf_plugin_unload(clicon_handle h)
|
||||||
{
|
{
|
||||||
|
|
@ -180,8 +178,7 @@ netconf_plugin_unload(clicon_handle h)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*! Call plugin_start in all plugins
|
||||||
* Call plugin_start in all plugins
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_plugin_start(clicon_handle h, int argc, char **argv)
|
netconf_plugin_start(clicon_handle h, int argc, char **argv)
|
||||||
|
|
@ -203,8 +200,7 @@ netconf_plugin_start(clicon_handle h, int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*! Register netconf callback
|
||||||
* netconf_register_callback
|
|
||||||
* Called from plugin to register a callback for a specific netconf XML tag.
|
* Called from plugin to register a callback for a specific netconf XML tag.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <fcgi_stdio.h>
|
#include <fcgi_stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
@ -230,3 +231,143 @@ readdata(FCGX_Request *r)
|
||||||
return cb;
|
return cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nplugins = 0;
|
||||||
|
static plghndl_t *plugins = NULL;
|
||||||
|
|
||||||
|
/*! Load a dynamic plugin object and call it's init-function
|
||||||
|
* Note 'file' may be destructively modified
|
||||||
|
*/
|
||||||
|
static plghndl_t
|
||||||
|
plugin_load (clicon_handle h,
|
||||||
|
char *file,
|
||||||
|
int dlflags,
|
||||||
|
const char *cnklbl)
|
||||||
|
{
|
||||||
|
char *error;
|
||||||
|
void *handle = NULL;
|
||||||
|
plginit_t *initfn;
|
||||||
|
|
||||||
|
dlerror(); /* Clear any existing error */
|
||||||
|
if ((handle = dlopen (file, dlflags)) == NULL) {
|
||||||
|
error = (char*)dlerror();
|
||||||
|
clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error");
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
/* call plugin_init() if defined */
|
||||||
|
if ((initfn = dlsym(handle, PLUGIN_INIT)) != NULL) {
|
||||||
|
if (initfn(h) != 0) {
|
||||||
|
clicon_err(OE_PLUGIN, errno, "Failed to initiate %s\n", strrchr(file,'/')?strchr(file, '/'):file);
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
quit:
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Load all plugins you can find in CLICON_RESTCONF_DIR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
restconf_plugin_load(clicon_handle h)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *dir;
|
||||||
|
int ndp;
|
||||||
|
struct dirent *dp;
|
||||||
|
int i;
|
||||||
|
char *filename;
|
||||||
|
plghndl_t *handle;
|
||||||
|
|
||||||
|
if ((dir = clicon_restconf_dir(h)) == NULL){
|
||||||
|
clicon_err(OE_PLUGIN, 0, "clicon_restconf_dir not defined");
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
/* Get plugin objects names from plugin directory */
|
||||||
|
if((ndp = clicon_file_dirent(dir, &dp, "(.so)$", S_IFREG, __FUNCTION__))<0)
|
||||||
|
goto quit;
|
||||||
|
|
||||||
|
/* Load all plugins */
|
||||||
|
for (i = 0; i < ndp; i++) {
|
||||||
|
filename = chunk_sprintf(__FUNCTION__, "%s/%s", dir, dp[i].d_name);
|
||||||
|
clicon_debug(1, "DEBUG: Loading plugin '%.*s' ...",
|
||||||
|
(int)strlen(filename), filename);
|
||||||
|
if (filename == NULL) {
|
||||||
|
clicon_err(OE_UNIX, errno, "chunk");
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
if ((handle = plugin_load (h, filename, RTLD_NOW, __FUNCTION__)) == NULL)
|
||||||
|
goto quit;
|
||||||
|
if ((plugins = rechunk(plugins, (nplugins+1) * sizeof (*plugins), NULL)) == NULL) {
|
||||||
|
clicon_err(OE_UNIX, errno, "chunk");
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
|
plugins[nplugins++] = handle;
|
||||||
|
unchunk (filename);
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
quit:
|
||||||
|
unchunk_group(__FUNCTION__);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Unload a plugin
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
plugin_unload(clicon_handle h, void *handle)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
char *error;
|
||||||
|
plgexit_t *exitfn;
|
||||||
|
|
||||||
|
/* Call exit function is it exists */
|
||||||
|
exitfn = dlsym(handle, PLUGIN_EXIT);
|
||||||
|
if (dlerror() == NULL)
|
||||||
|
exitfn(h);
|
||||||
|
|
||||||
|
dlerror(); /* Clear any existing error */
|
||||||
|
if (dlclose(handle) != 0) {
|
||||||
|
error = (char*)dlerror();
|
||||||
|
clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error");
|
||||||
|
/* Just report */
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Unload all restconf plugins */
|
||||||
|
int
|
||||||
|
restconf_plugin_unload(clicon_handle h)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < nplugins; i++)
|
||||||
|
plugin_unload(h, plugins[i]);
|
||||||
|
if (plugins)
|
||||||
|
unchunk(plugins);
|
||||||
|
nplugins = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Call plugin_start in all plugins
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
restconf_plugin_start(clicon_handle h,
|
||||||
|
int argc,
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
plgstart_t *startfn;
|
||||||
|
|
||||||
|
for (i = 0; i < nplugins; i++) {
|
||||||
|
/* Call exit function is it exists */
|
||||||
|
if ((startfn = dlsym(plugins[i], PLUGIN_START)) == NULL)
|
||||||
|
break;
|
||||||
|
optind = 0;
|
||||||
|
if (startfn(h, argc, argv) < 0) {
|
||||||
|
clicon_debug(1, "plugin_start() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,4 +30,10 @@ int str2cvec(char *string, char delim1, char delim2, cvec **cvp);
|
||||||
int test(FCGX_Request *r, int dbg);
|
int test(FCGX_Request *r, int dbg);
|
||||||
cbuf *readdata(FCGX_Request *r);
|
cbuf *readdata(FCGX_Request *r);
|
||||||
|
|
||||||
|
|
||||||
|
int restconf_plugin_load(clicon_handle h);
|
||||||
|
int restconf_plugin_start(clicon_handle h, int argc, char **argv);
|
||||||
|
int restconf_plugin_unload(clicon_handle h);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _RESTCONF_LIB_H_ */
|
#endif /* _RESTCONF_LIB_H_ */
|
||||||
|
|
|
||||||
|
|
@ -56,12 +56,42 @@
|
||||||
#include "restconf_lib.h"
|
#include "restconf_lib.h"
|
||||||
|
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* Command line options to be passed to getopt(3) */
|
||||||
#define RESTCONF_OPTS "hDf:"
|
#define RESTCONF_OPTS "hDf:p:"
|
||||||
|
|
||||||
/* Should be discovered via "/.well-known/host-meta"
|
/* Should be discovered via "/.well-known/host-meta"
|
||||||
resource ([RFC6415]) */
|
resource ([RFC6415]) */
|
||||||
#define RESTCONF_API_ROOT "/restconf/"
|
#define RESTCONF_API_ROOT "/restconf/"
|
||||||
|
|
||||||
|
/*! REST OPTIONS method
|
||||||
|
* According to restconf (Sec 3.5.1.1 in [draft])
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] r Fastcgi request handle
|
||||||
|
* @param[in] pcvec Vector of path ie DOCUMENT_URI element
|
||||||
|
* @param[in] pi Offset, where path starts
|
||||||
|
* @param[in] qvec Vector of query string (QUERY_STRING)
|
||||||
|
* @param[in] head Set if HEAD request instead of GET
|
||||||
|
* @code
|
||||||
|
* curl -G http://localhost/restconf/data/interfaces/interface=eth0
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
api_data_options(clicon_handle h,
|
||||||
|
FCGX_Request *r,
|
||||||
|
cvec *pcvec,
|
||||||
|
int pi,
|
||||||
|
cvec *qvec,
|
||||||
|
int head)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
|
||||||
|
FCGX_SetExitStatus(200, r->out); /* OK */
|
||||||
|
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
||||||
|
FCGX_FPrintF(r->out, "\r\n");
|
||||||
|
FCGX_FPrintF(r->out, "GET, HEAD, OPTIONS, PUT, POST, DELETE\r\n");
|
||||||
|
retval = 0;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Generic REST GET method
|
/*! Generic REST GET method
|
||||||
* According to restconf (Sec 3.5.1.1 in [draft])
|
* According to restconf (Sec 3.5.1.1 in [draft])
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
|
|
@ -172,19 +202,17 @@ api_data_get(clicon_handle h,
|
||||||
cprintf(path1, "/%s", name);
|
cprintf(path1, "/%s", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clicon_debug(1, "path:%s", cbuf_get(path));
|
|
||||||
clicon_debug(1, "path1:%s", cbuf_get(path1));
|
|
||||||
if (xmldb_get(h, "running", cbuf_get(path), 0, &xt, &vec, &veclen) < 0)
|
if (xmldb_get(h, "running", cbuf_get(path), 0, &xt, &vec, &veclen) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
FCGX_SetExitStatus(200, r->out); /* OK */
|
FCGX_SetExitStatus(200, r->out); /* OK */
|
||||||
|
FCGX_FPrintF(r->out, "Content-Type: application/yang.data+json\r\n");
|
||||||
FCGX_FPrintF(r->out, "Content-Type: application/yang.data+xml\r\n");
|
|
||||||
FCGX_FPrintF(r->out, "\r\n");
|
FCGX_FPrintF(r->out, "\r\n");
|
||||||
if ((cbx = cbuf_new()) == NULL)
|
if ((cbx = cbuf_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml2json_cbuf(cbx, xt, 1, 0) < 0)
|
if (xml2json_cbuf(cbx, xt, 1, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
FCGX_FPrintF(r->out, "%s\r\n", cbuf_get(cbx));
|
FCGX_FPrintF(r->out, "%s", cbuf_get(cbx));
|
||||||
|
FCGX_FPrintF(r->out, "hej\r\n\r\n");
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (vec)
|
if (vec)
|
||||||
|
|
@ -249,17 +277,23 @@ api_data_delete(clicon_handle h,
|
||||||
* @param[in] pi Offset, where to start pcvec
|
* @param[in] pi Offset, where to start pcvec
|
||||||
* @param[in] qvec Vector of query string (QUERY_STRING)
|
* @param[in] qvec Vector of query string (QUERY_STRING)
|
||||||
* @param[in] dvec Stream input data
|
* @param[in] dvec Stream input data
|
||||||
|
* @param[in] post POST instead of PUT
|
||||||
* Example:
|
* Example:
|
||||||
curl -X PUT -d {\"enabled\":\"false\"} http://127.0.0.1/restconf/data/interfaces/interface=eth1
|
curl -X PUT -d {\"enabled\":\"false\"} http://127.0.0.1/restconf/data/interfaces/interface=eth1
|
||||||
|
*
|
||||||
|
PUT:
|
||||||
|
if the PUT request creates a new resource,
|
||||||
|
a "201 Created" status-line is returned. If an existing resource is
|
||||||
|
modified, a "204 No Content" status-line is returned.
|
||||||
|
|
||||||
* Problem: we have URI that defines a path (eg "interface/name=eth1") and data
|
POST:
|
||||||
* which defines a tree from that point.
|
If the POST method succeeds, a "201 Created" status-line is returned
|
||||||
* But, xmldb api can only do either
|
and there is no response message-body. A "Location" header
|
||||||
* - xmldb_put() with a complete xml-tree, or
|
identifying the child resource that was created MUST be present in
|
||||||
* - xmldb_put_xkey for path and key value
|
the response in this case.
|
||||||
* What we need is path and sub-xml tree.
|
|
||||||
* Alt1: parse URI to XML and and call xmldb_put()
|
If the data resource already exists, then the POST request MUST fail
|
||||||
* Alt2: Extend xmldb API with path + xml-tree.
|
and a "409 Conflict" status-line MUST be returned.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
api_data_put(clicon_handle h,
|
api_data_put(clicon_handle h,
|
||||||
|
|
@ -268,7 +302,8 @@ api_data_put(clicon_handle h,
|
||||||
cvec *pcvec,
|
cvec *pcvec,
|
||||||
int pi,
|
int pi,
|
||||||
cvec *qvec,
|
cvec *qvec,
|
||||||
char *data)
|
char *data,
|
||||||
|
int post)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -304,7 +339,7 @@ api_data_put(clicon_handle h,
|
||||||
if (clicon_rpc_commit(h, "candidate", "running",
|
if (clicon_rpc_commit(h, "candidate", "running",
|
||||||
0, 0) < 0)
|
0, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
FCGX_SetExitStatus(201, r->out);
|
FCGX_SetExitStatus(201, r->out); /* Created */
|
||||||
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
||||||
FCGX_FPrintF(r->out, "\r\n");
|
FCGX_FPrintF(r->out, "\r\n");
|
||||||
done:
|
done:
|
||||||
|
|
@ -339,10 +374,14 @@ api_data(clicon_handle h,
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
request_method = FCGX_GetParam("REQUEST_METHOD", r->envp);
|
request_method = FCGX_GetParam("REQUEST_METHOD", r->envp);
|
||||||
if (strcmp(request_method, "GET")==0)
|
if (strcmp(request_method, "OPTIONS")==0)
|
||||||
|
retval = api_data_options(h, r, pcvec, pi, qvec, 0);
|
||||||
|
else if (strcmp(request_method, "GET")==0)
|
||||||
retval = api_data_get(h, r, pcvec, pi, qvec);
|
retval = api_data_get(h, r, pcvec, pi, qvec);
|
||||||
else if (strcmp(request_method, "PUT")==0)
|
else if (strcmp(request_method, "PUT")==0)
|
||||||
retval = api_data_put(h, r, api_path, pcvec, pi, qvec, data);
|
retval = api_data_put(h, r, api_path, pcvec, pi, qvec, data, 0);
|
||||||
|
else if (strcmp(request_method, "POST")==0)
|
||||||
|
retval = api_data_put(h, r, api_path, pcvec, pi, qvec, data, 1);
|
||||||
else if (strcmp(request_method, "DELETE")==0)
|
else if (strcmp(request_method, "DELETE")==0)
|
||||||
retval = api_data_delete(h, r, api_path, pi);
|
retval = api_data_delete(h, r, api_path, pi);
|
||||||
else
|
else
|
||||||
|
|
@ -389,6 +428,7 @@ request_process(clicon_handle h,
|
||||||
method = pvec[2];
|
method = pvec[2];
|
||||||
retval = 0;
|
retval = 0;
|
||||||
test(r, 1);
|
test(r, 1);
|
||||||
|
/* XXX Credentials */
|
||||||
if (strcmp(method, "data") == 0) /* restconf, skip /api/data */
|
if (strcmp(method, "data") == 0) /* restconf, skip /api/data */
|
||||||
retval = api_data(h, r, path, pcvec, 2, qvec, data);
|
retval = api_data(h, r, path, pcvec, 2, qvec, data);
|
||||||
else if (strcmp(method, "test") == 0)
|
else if (strcmp(method, "test") == 0)
|
||||||
|
|
@ -405,6 +445,7 @@ request_process(clicon_handle h,
|
||||||
if (cb)
|
if (cb)
|
||||||
cbuf_free(cb);
|
cbuf_free(cb);
|
||||||
unchunk_group(__FUNCTION__);
|
unchunk_group(__FUNCTION__);
|
||||||
|
clicon_debug(1, "%s end", __FUNCTION__);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -417,13 +458,18 @@ usage(clicon_handle h,
|
||||||
char *argv0)
|
char *argv0)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
char *restconfdir = clicon_restconf_dir(h);
|
||||||
|
|
||||||
fprintf(stderr, "usage:%s [options]\n"
|
fprintf(stderr, "usage:%s [options]\n"
|
||||||
"where options are\n"
|
"where options are\n"
|
||||||
"\t-h \t\tHelp\n"
|
"\t-h \t\tHelp\n"
|
||||||
"\t-D \t\tDebug. Log to syslog\n"
|
"\t-D \t\tDebug. Log to syslog\n"
|
||||||
"\t-f <file>\tConfiguration file (mandatory)\n",
|
"\t-f <file>\tConfiguration file (mandatory)\n"
|
||||||
argv0
|
"\t-d <dir>\tSpecify restconf plugin directory dir (default: %s)\n",
|
||||||
|
argv0,
|
||||||
|
restconfdir
|
||||||
);
|
);
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Main routine for grideye fastcgi API
|
/*! Main routine for grideye fastcgi API
|
||||||
|
|
@ -460,6 +506,11 @@ main(int argc,
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'd': /* Plugin directory */
|
||||||
|
if (!strlen(optarg))
|
||||||
|
usage(h, argv[0]);
|
||||||
|
clicon_option_str_set(h, "CLICON_RESTCONF_DIR", optarg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage(h, argv[0]);
|
usage(h, argv[0]);
|
||||||
break;
|
break;
|
||||||
|
|
@ -474,6 +525,10 @@ main(int argc,
|
||||||
if (clicon_options_main(h) < 0)
|
if (clicon_options_main(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
/* Initialize plugins group */
|
||||||
|
if (restconf_plugin_load(h) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* Parse yang database spec file */
|
/* Parse yang database spec file */
|
||||||
if (yang_spec_main(h, NULL, 0) < 0)
|
if (yang_spec_main(h, NULL, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -516,5 +571,6 @@ main(int argc,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
restconf_plugin_unload(h);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,9 @@ CLICON_BACKEND_DIR libdir/APPNAME/backend
|
||||||
# Location of netconf (frontend) .so plugins
|
# Location of netconf (frontend) .so plugins
|
||||||
CLICON_NETCONF_DIR libdir/APPNAME/netconf
|
CLICON_NETCONF_DIR libdir/APPNAME/netconf
|
||||||
|
|
||||||
|
# Location of restconf (frontend) .so plugins
|
||||||
|
CLICON_RESTCONF_DIR libdir/APPNAME/restconf
|
||||||
|
|
||||||
# Location of cli frontend .so plugins
|
# Location of cli frontend .so plugins
|
||||||
CLICON_CLI_DIR libdir/APPNAME/cli
|
CLICON_CLI_DIR libdir/APPNAME/cli
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ char *clicon_backend_dir(clicon_handle h);
|
||||||
char *clicon_cli_dir(clicon_handle h);
|
char *clicon_cli_dir(clicon_handle h);
|
||||||
char *clicon_clispec_dir(clicon_handle h);
|
char *clicon_clispec_dir(clicon_handle h);
|
||||||
char *clicon_netconf_dir(clicon_handle h);
|
char *clicon_netconf_dir(clicon_handle h);
|
||||||
|
char *clicon_restconf_dir(clicon_handle h);
|
||||||
char *clicon_archive_dir(clicon_handle h);
|
char *clicon_archive_dir(clicon_handle h);
|
||||||
char *clicon_startup_config(clicon_handle h);
|
char *clicon_startup_config(clicon_handle h);
|
||||||
int clicon_sock_family(clicon_handle h);
|
int clicon_sock_family(clicon_handle h);
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,10 @@ clicon_option_sanity(clicon_hash_t *copt)
|
||||||
clicon_err(OE_UNIX, 0, "CLICON_NETCONF_DIR not defined in config file");
|
clicon_err(OE_UNIX, 0, "CLICON_NETCONF_DIR not defined in config file");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (!hash_lookup(copt, "CLICON_RESTCONF_DIR")){
|
||||||
|
clicon_err(OE_UNIX, 0, "CLICON_RESTCONF_DIR not defined in config file");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
if (!hash_lookup(copt, "CLICON_YANG_DIR")){
|
if (!hash_lookup(copt, "CLICON_YANG_DIR")){
|
||||||
clicon_err(OE_UNIX, 0, "CLICON_YANG_DIR not defined in config file");
|
clicon_err(OE_UNIX, 0, "CLICON_YANG_DIR not defined in config file");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -432,6 +436,12 @@ clicon_netconf_dir(clicon_handle h)
|
||||||
return clicon_option_str(h, "CLICON_NETCONF_DIR");
|
return clicon_option_str(h, "CLICON_NETCONF_DIR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
clicon_restconf_dir(clicon_handle h)
|
||||||
|
{
|
||||||
|
return clicon_option_str(h, "CLICON_RESTCONF_DIR");
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
clicon_archive_dir(clicon_handle h)
|
clicon_archive_dir(clicon_handle h)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue