Disabled key-value datastore; Removed mandatory requirements for BACKEND, NETCONF, RESTCONF and CLI dirs

This commit is contained in:
Olof hagsand 2017-11-19 18:04:23 +01:00
parent 13377da34e
commit 548ffd2da6
21 changed files with 64 additions and 55 deletions

View file

@ -26,6 +26,8 @@ clixon_cli -f /usr/local/etc/routing.conf -1x
Backward compatibility is enabled by defining BACKEND_STARTUP_BACKWARD_COMPAT in include/clixon_custom.h Backward compatibility is enabled by defining BACKEND_STARTUP_BACKWARD_COMPAT in include/clixon_custom.h
### Minor changes: ### Minor changes:
* Disabled key-value datastore. Enable with --with-keyvalue
* Removed mandatory requirements for BACKEND, NETCONF, RESTCONF and CLI dirs.
* When user callbacks such as statedata() call returns -1, clixon_backend no * When user callbacks such as statedata() call returns -1, clixon_backend no
longer silently exits. Instead a log is printed and an RPC error is returned. longer silently exits. Instead a log is printed and an RPC error is returned.
* Added Floating point and negative number support to JSON * Added Floating point and negative number support to JSON

View file

@ -140,7 +140,7 @@ usage(char *argv0, clicon_handle h)
" -1\t\tRun once and then quit (dont wait for events)\n" " -1\t\tRun once and then quit (dont wait for events)\n"
" -u <path>\tConfig UNIX domain path / ip address (default: %s)\n" " -u <path>\tConfig UNIX domain path / ip address (default: %s)\n"
" -P <file>\tPid filename (default: %s)\n" " -P <file>\tPid filename (default: %s)\n"
" -s <mode>\tSpecify backend startup mode: none|startup|running|init (replaces -IRCc:r:\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" " -c <file>\tLoad extra xml configuration, but don't commit.\n"
#ifdef BACKEND_STARTUP_BACKWARD_COMPAT #ifdef BACKEND_STARTUP_BACKWARD_COMPAT
" -I\t\tInitialize running state database\n" " -I\t\tInitialize running state database\n"
@ -835,7 +835,8 @@ main(int argc, char **argv)
) < 0) ) < 0)
goto done; goto done;
#else #else
clicon_log(LOG_ERR, "Startup mode indefined. Specify option CLICON_STARTUP_MODE or specify -s option to clicon_backend.\n"); clicon_log(LOG_ERR, "Startup mode undefined. Specify option CLICON_STARTUP_MODE or specify -s option to clicon_backend.\n");
goto done;
#endif #endif
} }
else { else {

View file

@ -431,11 +431,9 @@ plugin_initiate(clicon_handle h)
return -1; return -1;
/* Then load application plugins */ /* Then load application plugins */
if ((dir = clicon_backend_dir(h)) == NULL){ dir = clicon_backend_dir(h);
clicon_err(OE_PLUGIN, 0, "backend_dir not defined"); /* If backend directory, load the backend plugisn */
return -1; if (dir && backend_plugin_load_dir(h, dir) < 0)
}
if (backend_plugin_load_dir(h, dir) < 0)
return -1; return -1;
return 0; return 0;

View file

@ -400,12 +400,6 @@ main(int argc, char **argv)
if (yang_spec_main(h, stdout, printspec) < 0) if (yang_spec_main(h, stdout, printspec) < 0)
goto done; goto done;
/* Check plugin directory */
if (clicon_cli_dir(h) == NULL){
clicon_err(OE_PLUGIN, 0, "clicon_cli_dir not defined");
goto done;
}
/* Create tree generated from dataspec. If no other trees exists, this is /* Create tree generated from dataspec. If no other trees exists, this is
* the only one. * the only one.
*/ */

View file

@ -366,7 +366,9 @@ done:
/*! Load plugins within a directory /*! Load plugins within a directory
*/ */
static int static int
cli_plugin_load_dir(clicon_handle h, char *dir, cli_syntax_t *stx) cli_plugin_load_dir(clicon_handle h,
char *dir,
cli_syntax_t *stx)
{ {
int i; int i;
int ndp; int ndp;
@ -452,10 +454,7 @@ cli_syntax_load (clicon_handle h)
return 0; return 0;
/* Format plugin directory path */ /* Format plugin directory path */
if ((plugin_dir = clicon_cli_dir(h)) == NULL){ plugin_dir = clicon_cli_dir(h);
clicon_err(OE_FATAL, 0, "clicon_cli_dir not set");
goto quit;
}
clispec_dir = clicon_clispec_dir(h); clispec_dir = clicon_clispec_dir(h);
clispec_file = clicon_option_str(h, "CLICON_CLISPEC_FILE"); clispec_file = clicon_option_str(h, "CLICON_CLISPEC_FILE");
@ -474,7 +473,7 @@ cli_syntax_load (clicon_handle h)
goto quit; goto quit;
/* Then load application plugins */ /* Then load application plugins */
if (cli_plugin_load_dir(h, plugin_dir, stx) < 0) if (plugin_dir && cli_plugin_load_dir(h, plugin_dir, stx) < 0)
goto quit; goto quit;
if (clispec_file){ if (clispec_file){

View file

@ -286,8 +286,6 @@ static void
usage(clicon_handle h, usage(clicon_handle h,
char *argv0) char *argv0)
{ {
char *netconfdir = clicon_netconf_dir(h);
fprintf(stderr, "usage:%s\n" fprintf(stderr, "usage:%s\n"
"where options are\n" "where options are\n"
"\t-h\t\tHelp\n" "\t-h\t\tHelp\n"
@ -298,7 +296,7 @@ usage(clicon_handle h,
"\t-S\t\tLog on syslog\n" "\t-S\t\tLog on syslog\n"
"\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n", "\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n",
argv0, argv0,
netconfdir clicon_netconf_dir(h)
); );
exit(0); exit(0);
} }

View file

@ -92,8 +92,9 @@ netconf_plugin_load(clicon_handle h)
char filename[MAXPATHLEN]; char filename[MAXPATHLEN];
plghndl_t *handle; plghndl_t *handle;
/* If no DIR defined, then dont load plugins */
if ((dir = clicon_netconf_dir(h)) == NULL){ if ((dir = clicon_netconf_dir(h)) == NULL){
clicon_err(OE_PLUGIN, 0, "clicon_netconf_dir not defined"); retval = 0;
goto quit; goto quit;
} }

View file

@ -316,7 +316,7 @@ restconf_plugin_load(clicon_handle h)
char filename[MAXPATHLEN]; char filename[MAXPATHLEN];
if ((dir = clicon_restconf_dir(h)) == NULL){ if ((dir = clicon_restconf_dir(h)) == NULL){
clicon_err(OE_PLUGIN, 0, "clicon_restconf_dir not defined"); retval = 0;
goto quit; goto quit;
} }
/* Get plugin objects names from plugin directory */ /* Get plugin objects names from plugin directory */

View file

@ -269,8 +269,6 @@ 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"
@ -279,7 +277,7 @@ usage(clicon_handle h,
"\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>\tOverride yang spec file (dont include .yang suffix)\n",
argv0, argv0,
restconfdir clicon_restconf_dir(h)
); );
exit(0); exit(0);
} }

6
configure vendored
View file

@ -1344,7 +1344,7 @@ Optional Packages:
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-cligen=dir Use CLIGEN here --with-cligen=dir Use CLIGEN here
--without-restconf disable support for restconf --without-restconf disable support for restconf
--without-keyvalue disable support for key-value xmldb datastore --with-keyvalue enable support for key-value xmldb datastore
--with-qdbm=dir Use QDBM here, if keyvalue --with-qdbm=dir Use QDBM here, if keyvalue
Some influential environment variables: Some influential environment variables:
@ -3943,10 +3943,10 @@ fi
if test "${with_keyvalue+set}" = set; then : if test "${with_keyvalue+set}" = set; then :
withval=$with_keyvalue; withval=$with_keyvalue;
else else
with_keyvalue=yes with_keyvalue=no
fi fi
echo "keyvalue:${with_keyvalue}"
if test "x${with_keyvalue}" == xyes; then if test "x${with_keyvalue}" == xyes; then
echo "yes keyvalue" echo "yes keyvalue"
# This is for qdbm # This is for qdbm

View file

@ -138,10 +138,10 @@ fi
# This is for keyvalue datastore (and qdbm) # This is for keyvalue datastore (and qdbm)
AC_ARG_WITH([keyvalue], AC_ARG_WITH([keyvalue],
[AS_HELP_STRING([--without-keyvalue],[disable support for key-value xmldb datastore])], [AS_HELP_STRING([--with-keyvalue],[enable support for key-value xmldb datastore])],
[], [],
[with_keyvalue=yes]) [with_keyvalue=no])
echo "keyvalue:${with_keyvalue}"
if test "x${with_keyvalue}" == xyes; then if test "x${with_keyvalue}" == xyes; then
echo "yes keyvalue" echo "yes keyvalue"
# This is for qdbm # This is for qdbm

View file

@ -881,7 +881,7 @@ text_unlock_all(xmldb_handle xh,
int pid) int pid)
{ {
struct text_handle *th = handle(xh); struct text_handle *th = handle(xh);
char **keys; char **keys = NULL;
size_t klen; size_t klen;
int i; int i;
int *val; int *val;
@ -893,6 +893,8 @@ text_unlock_all(xmldb_handle xh,
if ((val = hash_value(th->th_dbs, keys[i], &vlen)) != NULL && if ((val = hash_value(th->th_dbs, keys[i], &vlen)) != NULL &&
*val == pid) *val == pid)
hash_del(th->th_dbs, keys[i]); hash_del(th->th_dbs, keys[i]);
if (keys)
free(keys);
return 0; return 0;
} }

View file

@ -153,6 +153,8 @@ route_count(clicon_handle h,
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* @see xmldb_get * @see xmldb_get
* @note this example code returns a static statedata used in testing.
* Real code would poll state
*/ */
int int
plugin_statedata(clicon_handle h, plugin_statedata(clicon_handle h,
@ -162,15 +164,11 @@ plugin_statedata(clicon_handle h,
int retval = -1; int retval = -1;
cxobj **xvec = NULL; cxobj **xvec = NULL;
fprintf(stderr, "%s xpath:%s\n", __FUNCTION__, xpath);
/* Example of (static) statedata, real code would poll state */ /* Example of (static) statedata, real code would poll state */
if (xml_parse("<interfaces-state><interface>" if (xml_parse("<interfaces-state><interface>"
"<name>eth0</name>" "<name>eth0</name>"
"<type>eth</type>" "<type>eth</type>"
"<admin-status>up</admin-status>"
"<oper-status>up</oper-status>"
"<if-index>42</if-index>" "<if-index>42</if-index>"
"<speed>1000000000</speed>"
"</interface></interfaces-state>", xstate) < 0) "</interface></interfaces-state>", xstate) < 0)
goto done; goto done;
retval = 0; retval = 0;
@ -218,6 +216,7 @@ plugin_init(clicon_handle h)
* @param[in] h Clicon handle * @param[in] h Clicon handle
* @param[in] db Name of database. Not may be other than "running" * @param[in] db Name of database. Not may be other than "running"
* In this example, a loopback interface is added * In this example, a loopback interface is added
* @note This assumes example yang with interfaces/interface
*/ */
int int
plugin_reset(clicon_handle h, plugin_reset(clicon_handle h,
@ -239,7 +238,7 @@ plugin_reset(clicon_handle h,
retval = 0; retval = 0;
done: done:
if (xt != NULL) if (xt != NULL)
free(xt); xml_free(xt);
return retval; return retval;
} }

View file

@ -178,6 +178,8 @@ clicon_option_readfile_xml(clicon_hash_t *copt,
} }
retval = 0; retval = 0;
done: done:
if (xt)
xml_free(xt);
if (f) if (f)
fclose(f); fclose(f);
return retval; return retval;
@ -356,7 +358,7 @@ clicon_options_main(clicon_handle h)
clicon_hash_t *copt = clicon_options(h); clicon_hash_t *copt = clicon_options(h);
char *suffix; char *suffix;
char xml = 0; /* Configfile is xml, otherwise legacy */ char xml = 0; /* Configfile is xml, otherwise legacy */
yang_spec *yspec; yang_spec *yspec = NULL;
/* /*
* Set configure file if not set by command-line above * Set configure file if not set by command-line above
@ -380,6 +382,8 @@ clicon_options_main(clicon_handle h)
/* Read configfile */ /* Read configfile */
if (clicon_option_readfile_xml(copt, configfile, yspec) < 0) if (clicon_option_readfile_xml(copt, configfile, yspec) < 0)
goto done; goto done;
if (yspec)
yspec_free(yspec);
} }
else { else {
/* Set default options */ /* Set default options */
@ -529,6 +533,7 @@ clicon_yang_module_revision(clicon_handle h)
return clicon_option_str(h, "CLICON_YANG_MODULE_REVISION"); return clicon_option_str(h, "CLICON_YANG_MODULE_REVISION");
} }
/*! Directory of backend plugins. If null, no plugins are loaded */
char * char *
clicon_backend_dir(clicon_handle h) clicon_backend_dir(clicon_handle h)
{ {

View file

@ -555,7 +555,7 @@ xmldb_unlock_all(clicon_handle h,
clicon_err(OE_DB, 0, "Not connected to datastore plugin"); clicon_err(OE_DB, 0, "Not connected to datastore plugin");
goto done; goto done;
} }
retval =xa->xa_unlock_all_fn(xh, pid); retval = xa->xa_unlock_all_fn(xh, pid);
done: done:
return retval; return retval;
} }

View file

@ -96,7 +96,7 @@ new "netconf edit state operation should fail"
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><edit-config><target><candidate/></target><config><interfaces-state><interface><name>eth1</name><type>eth</type></interface></interfaces-state></config></edit-config></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>invalid-value</error-tag>" expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><edit-config><target><candidate/></target><config><interfaces-state><interface><name>eth1</name><type>eth</type></interface></interfaces-state></config></edit-config></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>invalid-value</error-tag>"
new "netconf get state operation" new "netconf get state operation"
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><get><filter type=\"xpath\" select=\"/interfaces-state\"/></get></rpc>]]>]]>" "^<rpc-reply><data/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><get><filter type=\"xpath\" select=\"/interfaces-state\"/></get></rpc>]]>]]>" "^<rpc-reply><data><interfaces-state><interface><name>eth0</name><type>eth</type><if-index>42</if-index></interface></interfaces-state></data></rpc-reply>]]>]]>$"
new "netconf lock/unlock" new "netconf lock/unlock"
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><lock><target><candidate/></target></lock></rpc>]]>]]><rpc><unlock><target><candidate/></target></unlock></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]><rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><lock><target><candidate/></target></lock></rpc>]]>]]><rpc><unlock><target><candidate/></target></unlock></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]><rpc-reply><ok/></rpc-reply>]]>]]>$"

View file

@ -42,7 +42,6 @@ EOF
# kill old backend (if any) # kill old backend (if any)
new "kill old backend" new "kill old backend"
echo "clixon_backend -zf $clixon_cf -y $fyang"
sudo clixon_backend -zf $clixon_cf -y $fyang sudo clixon_backend -zf $clixon_cf -y $fyang
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
err err

View file

@ -6,7 +6,7 @@
. ./lib.sh . ./lib.sh
# This is a fixed 'state' implemented in routing_backend. It is always there # This is a fixed 'state' implemented in routing_backend. It is always there
state='{"interfaces-state": {"interface": {"name": "eth0","type": "eth","admin-status": "up","oper-status": "up","if-index": "42","speed": "1000000000"}}}' state='{"interfaces-state": {"interface": {"name": "eth0","type": "eth","if-index": "42"}}}'
# kill old backend (if any) # kill old backend (if any)
new "kill old backend" new "kill old backend"
@ -47,7 +47,7 @@ new "restconf Add subtree to datastore using POST"
expectfn 'curl -sS -X POST -d {"interfaces":{"interface":{"name":"eth/0/0","type":"eth","enabled":"true"}}} http://localhost/restconf/data' "" expectfn 'curl -sS -X POST -d {"interfaces":{"interface":{"name":"eth/0/0","type":"eth","enabled":"true"}}} http://localhost/restconf/data' ""
new "restconf Check interfaces eth/0/0 added" new "restconf Check interfaces eth/0/0 added"
expectfn "curl -sS -G http://localhost/restconf/data" '{"interfaces": {"interface": {"name": "eth/0/0","type": "eth","enabled": "true"}},"interfaces-state": {"interface": {"name": "eth0","type": "eth","admin-status": "up","oper-status": "up","if-index": "42","speed": "1000000000"}}} expectfn "curl -sS -G http://localhost/restconf/data" '{"interfaces": {"interface": {"name": "eth/0/0","type": "eth","enabled": "true"}},"interfaces-state": {"interface": {"name": "eth0","type": "eth","if-index": "42"}}}
$' $'
new "restconf delete interfaces" new "restconf delete interfaces"
@ -60,7 +60,7 @@ new "restconf Add interfaces subtree eth/0/0 using POST"
expectfn 'curl -sS -X POST -d {"interface":{"name":"eth/0/0","type":"eth","enabled":"true"}} http://localhost/restconf/data/interfaces' "" expectfn 'curl -sS -X POST -d {"interface":{"name":"eth/0/0","type":"eth","enabled":"true"}} http://localhost/restconf/data/interfaces' ""
new "restconf Check eth/0/0 added" new "restconf Check eth/0/0 added"
expectfn "curl -sS -G http://localhost/restconf/data" '{"interfaces": {"interface": {"name": "eth/0/0","type": "eth","enabled": "true"}},"interfaces-state": {"interface": {"name": "eth0","type": "eth","admin-status": "up","oper-status": "up","if-index": "42","speed": "1000000000"}}} expectfn "curl -sS -G http://localhost/restconf/data" '{"interfaces": {"interface": {"name": "eth/0/0","type": "eth","enabled": "true"}},"interfaces-state": {"interface": {"name": "eth0","type": "eth","if-index": "42"}}}
$' $'
new "restconf Re-post eth/0/0 which should generate error" new "restconf Re-post eth/0/0 which should generate error"
@ -86,7 +86,7 @@ new "restconf Add subtree eth/0/0 using PUT"
expectfn 'curl -sS -X PUT -d {"interface":{"name":"eth/0/0","type":"eth","enabled":"true"}} http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' "" expectfn 'curl -sS -X PUT -d {"interface":{"name":"eth/0/0","type":"eth","enabled":"true"}} http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' ""
new "restconf get subtree" new "restconf get subtree"
expectfn "curl -sS -G http://localhost/restconf/data" '{"interfaces": {"interface": {"name": "eth/0/0","type": "eth","enabled": "true"}},"interfaces-state": {"interface": {"name": "eth0","type": "eth","admin-status": "up","oper-status": "up","if-index": "42","speed": "1000000000"}}} expectfn "curl -sS -G http://localhost/restconf/data" '{"interfaces": {"interface": {"name": "eth/0/0","type": "eth","enabled": "true"}},"interfaces-state": {"interface": {"name": "eth0","type": "eth","if-index": "42"}}}
$' $'
new "restconf operation rpc using POST json" new "restconf operation rpc using POST json"

View file

@ -55,20 +55,20 @@ EOF
# kill old backend (if any) # kill old backend (if any)
new "kill old backend" new "kill old backend"
sudo clixon_backend -zf $clixon_cf $yang sudo clixon_backend -zf $clixon_cf
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
err err
fi fi
new "start backend" new "start backend"
# start new backend # start new backend
sudo clixon_backend -f $clixon_cf $yang -s $mode -c /tmp/config sudo clixon_backend -f $clixon_cf -s $mode -c /tmp/config
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
err err
fi fi
new "Check $mode" new "Check $mode"
expecteof "$clixon_netconf -qf $clixon_cf $yang" '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' "^<rpc-reply>$expect</rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $clixon_cf" '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' "^<rpc-reply>$expect</rpc-reply>]]>]]>$"
new "Kill backend" new "Kill backend"
# Check if still alive # Check if still alive

View file

@ -3,12 +3,29 @@
# include err() and new() functions # include err() and new() functions
. ./lib.sh . ./lib.sh
clixon_cf=/tmp/conf_yang.xml
# For memcheck # For memcheck
# clixon_netconf="valgrind --leak-check=full --show-leak-kinds=all clixon_netconf" # clixon_netconf="valgrind --leak-check=full --show-leak-kinds=all clixon_netconf"
clixon_netconf=clixon_netconf clixon_netconf=clixon_netconf
clixon_cli=clixon_cli clixon_cli=clixon_cli
cat <<EOF > /tmp/conf_yang.xml
<config>
<CLICON_CONFIGFILE>/tmp/test_yang.xml</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>/usr/local/share/routing/yang</CLICON_YANG_DIR>
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
<CLICON_CLISPEC_DIR>/usr/local/lib/routing/clispec</CLICON_CLISPEC_DIR>
<CLICON_CLI_DIR>/usr/local/lib/routing/cli</CLICON_CLI_DIR>
<CLICON_CLI_MODE>routing</CLICON_CLI_MODE>
<CLICON_SOCK>/usr/local/var/routing/routing.sock</CLICON_SOCK>
<CLICON_BACKEND_PIDFILE>/usr/local/var/routing/routing.pidfile</CLICON_BACKEND_PIDFILE>
<CLICON_CLI_GENMODEL_COMPLETION>1</CLICON_CLI_GENMODEL_COMPLETION>
<CLICON_XMLDB_DIR>/usr/local/var/routing</CLICON_XMLDB_DIR>
<CLICON_XMLDB_PLUGIN>/usr/local/lib/xmldb/text.so</CLICON_XMLDB_PLUGIN>
</config>
EOF
cat <<EOF > /tmp/test.yang cat <<EOF > /tmp/test.yang
module example{ module example{
container x { container x {

View file

@ -89,18 +89,15 @@
} }
leaf CLICON_BACKEND_DIR { leaf CLICON_BACKEND_DIR {
type string; type string;
mandatory true;
description "Location of backend .so plugins. Load all .so description "Location of backend .so plugins. Load all .so
plugins in this dir as backend plugins"; plugins in this dir as backend plugins";
} }
leaf CLICON_NETCONF_DIR { leaf CLICON_NETCONF_DIR {
type string; type string;
mandatory true;
description "Location of netconf (frontend) .so plugins"; description "Location of netconf (frontend) .so plugins";
} }
leaf CLICON_RESTCONF_DIR { leaf CLICON_RESTCONF_DIR {
type string; type string;
mandatory true;
description "Location of restconf (frontend) .so plugins. Load all .so description "Location of restconf (frontend) .so plugins. Load all .so
plugins in this dir as restconf code plugins"; plugins in this dir as restconf code plugins";
} }
@ -112,7 +109,6 @@
} }
leaf CLICON_CLI_DIR { leaf CLICON_CLI_DIR {
type string; type string;
mandatory true;
description "Location of cli frontend .so plugins. Load all .so description "Location of cli frontend .so plugins. Load all .so
plugins in this dir as CLI object plugins"; plugins in this dir as CLI object plugins";
} }