removed cli single callback arg code
This commit is contained in:
parent
1e92304a52
commit
31c45e5c62
15 changed files with 368 additions and 1120 deletions
50
CHANGELOG
50
CHANGELOG
|
|
@ -29,7 +29,13 @@
|
||||||
#
|
#
|
||||||
# ***** END LICENSE BLOCK *****
|
# ***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
- show_configuration and cli_copy_object added as generic cli commands
|
- cli_copy_config added as generic cli command
|
||||||
|
- cli_show_config added as generic cli command
|
||||||
|
Replace all show_confv*() and show_conf*() with cli_show_config()
|
||||||
|
Example: replace:
|
||||||
|
show_confv_as_json("candidate","/sender");
|
||||||
|
with:
|
||||||
|
cli_show_config("candidate","json","/sender");
|
||||||
- Alternative yang spec option -y added to all applications
|
- Alternative yang spec option -y added to all applications
|
||||||
- Many clicon special string functions have been removed
|
- Many clicon special string functions have been removed
|
||||||
- The netconf support has been extended with lock/unlock
|
- The netconf support has been extended with lock/unlock
|
||||||
|
|
@ -69,18 +75,40 @@
|
||||||
- Netconf startup configuration support. Set CLICON_USE_STARTUP_CONFIG to 1 to
|
- Netconf startup configuration support. Set CLICON_USE_STARTUP_CONFIG to 1 to
|
||||||
enable. Eg, if backend_main is started with -CIr startup will be copied to
|
enable. Eg, if backend_main is started with -CIr startup will be copied to
|
||||||
running.
|
running.
|
||||||
|
|
||||||
- Added ".." as valid step in xpath
|
- Added ".." as valid step in xpath
|
||||||
|
|
||||||
- Use restconf format for internal xmldb keys. Eg /a/b=3,4
|
- Use restconf format for internal xmldb keys. Eg /a/b=3,4
|
||||||
- List keys with special characters are RFC 3986 encoded.
|
|
||||||
- Changed example to use multiple cli callbacks
|
- List keys with special characters RFC 3986 encoded.
|
||||||
- Added cli multiple callback and expand support. Use options
|
|
||||||
CLICON_CLIGEN_CALLBACK_SINGLE_ARG and CLICON_CLIGEN_EXPAND_SINGLE_ARG
|
- Replaced cli expand functions with single to multiple args
|
||||||
to control these.
|
This change is _not_ backward compatible
|
||||||
The multiple support for expand callbacks is enabled but not for callbacks
|
This effects all calls to expand_dbvar() or user-defined
|
||||||
since this causes problems for legacy applications.
|
expand callbacks
|
||||||
If you change to multiple argument callbacks change all cli callback functions.
|
|
||||||
Library functions in clixon_cli_api.h (e.g cli_commit) is rewritten in new
|
- Replaced cli callback functions with single arg to multiple args
|
||||||
for (eg cli_commitv). See clixon_cli_api.h for new names.
|
This change is _not_ backward compatible.
|
||||||
|
You are affected if you
|
||||||
|
(1) use system callbacks (i.e. in clixon_cli_api.h)
|
||||||
|
(2) write your own cli callbacks
|
||||||
|
|
||||||
|
If you use cli callbacks, you need to rewrite cli callbacks from eg:
|
||||||
|
load("Comment") <filename:string>,load_config_file("filename replace");
|
||||||
|
to:
|
||||||
|
load("Comment") <filename:string>,load_config_file("filename", "replace");
|
||||||
|
|
||||||
|
If you write your own, you need to change the callback signature from;
|
||||||
|
int cli_callback(clicon_handle h, cvec *vars, cg_var *arg)
|
||||||
|
to:
|
||||||
|
int cli_callback(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
and rewrite the code to handle argv instead of arg.
|
||||||
|
These are the system functions affected:
|
||||||
|
cli_set, cli_merge, cli_del, cli_debug_backend, cli_set_mode,
|
||||||
|
cli_start_shell, cli_quit, cli_commit, cli_validate, compare_dbs,
|
||||||
|
load_config_file, save_config_file, delete_all, discard_changes, cli_notify,
|
||||||
|
show_yang, show_conf_xpath
|
||||||
|
|
||||||
- Added --with-cligen and --with-qdbm configure options
|
- Added --with-cligen and --with-qdbm configure options
|
||||||
- Added union type check for non-cli (eg xml) input
|
- Added union type check for non-cli (eg xml) input
|
||||||
- Empty yang type. Relaxed yang types for unions, eg two strings with different length.
|
- Empty yang type. Relaxed yang types for unions, eg two strings with different length.
|
||||||
|
|
|
||||||
|
|
@ -197,10 +197,10 @@ cli_signal_flush(clicon_handle h)
|
||||||
* @see cli_callback_generate where arg is generated
|
* @see cli_callback_generate where arg is generated
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cli_dbxmlv(clicon_handle h,
|
cli_dbxml(clicon_handle h,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv,
|
cvec *argv,
|
||||||
enum operation_type op)
|
enum operation_type op)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *str = NULL;
|
char *str = NULL;
|
||||||
|
|
@ -253,40 +253,54 @@ cli_dbxmlv(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cli_setv(clicon_handle h, cvec *cvv, cvec *argv)
|
cli_set(clicon_handle h, cvec *cvv, cvec *argv)
|
||||||
{
|
{
|
||||||
int retval = 1;
|
int retval = 1;
|
||||||
|
|
||||||
if (cli_dbxmlv(h, cvv, argv, OP_REPLACE) < 0)
|
if (cli_dbxml(h, cvv, argv, OP_REPLACE) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int cli_setv(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return cli_set(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cli_mergev(clicon_handle h, cvec *cvv, cvec *argv)
|
cli_merge(clicon_handle h, cvec *cvv, cvec *argv)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
||||||
if (cli_dbxmlv(h, cvv, argv, OP_MERGE) < 0)
|
if (cli_dbxml(h, cvv, argv, OP_MERGE) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int cli_mergev(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return cli_merge(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cli_delv(clicon_handle h, cvec *cvv, cvec *argv)
|
cli_del(clicon_handle h, cvec *cvv, cvec *argv)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
||||||
if (cli_dbxmlv(h, cvv, argv, OP_REMOVE) < 0)
|
if (cli_dbxml(h, cvv, argv, OP_REMOVE) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int cli_delv(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return cli_del(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Set debug level on CLI client (not backend daemon)
|
/*! Set debug level on CLI client (not backend daemon)
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
|
|
@ -296,7 +310,7 @@ cli_delv(clicon_handle h, cvec *cvv, cvec *argv)
|
||||||
* _or_ if a 'level' variable is present in vars use that value instead.
|
* _or_ if a 'level' variable is present in vars use that value instead.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_debug_cliv(clicon_handle h,
|
cli_debug_cli(clicon_handle h,
|
||||||
cvec *vars,
|
cvec *vars,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
|
|
@ -318,6 +332,10 @@ cli_debug_cliv(clicon_handle h,
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int cli_debug_cliv(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return cli_debug_cli(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Set debug level on backend daemon (not CLI)
|
/*! Set debug level on backend daemon (not CLI)
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
|
|
@ -327,9 +345,9 @@ cli_debug_cliv(clicon_handle h,
|
||||||
* _or_ if a 'level' variable is present in vars use that value instead.
|
* _or_ if a 'level' variable is present in vars use that value instead.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_debug_backendv(clicon_handle h,
|
cli_debug_backend(clicon_handle h,
|
||||||
cvec *vars,
|
cvec *vars,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
|
|
@ -348,11 +366,15 @@ cli_debug_backendv(clicon_handle h,
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int cli_debug_backendv(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return cli_debug_backend(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Set syntax mode
|
/*! Set syntax mode
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_set_modev(clicon_handle h,
|
cli_set_mode(clicon_handle h,
|
||||||
cvec *vars,
|
cvec *vars,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
|
|
@ -369,14 +391,18 @@ cli_set_modev(clicon_handle h,
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int cli_set_modev(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return cli_set_mode(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Start bash from cli callback
|
/*! Start bash from cli callback
|
||||||
* XXX Application specific??
|
* XXX Application specific??
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_start_shellv(clicon_handle h,
|
cli_start_shell(clicon_handle h,
|
||||||
cvec *vars,
|
cvec *vars,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
char *cmd;
|
char *cmd;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
@ -426,23 +452,31 @@ cli_start_shellv(clicon_handle h,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int cli_start_shellv(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return cli_start_shell(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Generic quit callback
|
/*! Generic quit callback
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_quitv(clicon_handle h,
|
cli_quit(clicon_handle h,
|
||||||
cvec *vars,
|
cvec *vars,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
cli_set_exiting(h, 1);
|
cli_set_exiting(h, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int cli_quitv(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return cli_quit(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Generic commit callback
|
/*! Generic commit callback
|
||||||
* @param[in] argv No arguments expected
|
* @param[in] argv No arguments expected
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_commitv(clicon_handle h,
|
cli_commit(clicon_handle h,
|
||||||
cvec *vars,
|
cvec *vars,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
|
|
@ -456,11 +490,15 @@ cli_commitv(clicon_handle h,
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int cli_commitv(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return cli_commit(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Generic validate callback
|
/*! Generic validate callback
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_validatev(clicon_handle h,
|
cli_validate(clicon_handle h,
|
||||||
cvec *vars,
|
cvec *vars,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
|
|
@ -472,7 +510,10 @@ cli_validatev(clicon_handle h,
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int cli_validatev(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return cli_validate(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Compare two dbs using XML. Write to file and run diff
|
/*! Compare two dbs using XML. Write to file and run diff
|
||||||
*/
|
*/
|
||||||
|
|
@ -541,7 +582,7 @@ compare_xmls(cxobj *xc1,
|
||||||
* @param[in] arg arg: 0 as xml, 1: as text
|
* @param[in] arg arg: 0 as xml, 1: as text
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
compare_dbsv(clicon_handle h,
|
compare_dbs(clicon_handle h,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
|
|
@ -573,6 +614,10 @@ compare_dbsv(clicon_handle h,
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int compare_dbsv(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return compare_dbs(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Load a configuration file to candidate database
|
/*! Load a configuration file to candidate database
|
||||||
* Utility function used by cligen spec file
|
* Utility function used by cligen spec file
|
||||||
|
|
@ -589,9 +634,9 @@ compare_dbsv(clicon_handle h,
|
||||||
* @see save_config_file
|
* @see save_config_file
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
load_config_filev(clicon_handle h,
|
load_config_file(clicon_handle h,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
@ -669,6 +714,10 @@ load_config_filev(clicon_handle h,
|
||||||
close(fd);
|
close(fd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
int load_config_filev(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return load_config_file(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Copy database to local file
|
/*! Copy database to local file
|
||||||
* Utility function used by cligen spec file
|
* Utility function used by cligen spec file
|
||||||
|
|
@ -686,9 +735,9 @@ load_config_filev(clicon_handle h,
|
||||||
* @see load_config_file
|
* @see load_config_file
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
save_config_filev(clicon_handle h,
|
save_config_file(clicon_handle h,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
|
|
@ -736,14 +785,18 @@ save_config_filev(clicon_handle h,
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int save_config_filev(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return save_config_file(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Delete all elements in a database
|
/*! Delete all elements in a database
|
||||||
* Utility function used by cligen spec file
|
* Utility function used by cligen spec file
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
delete_allv(clicon_handle h,
|
delete_all(clicon_handle h,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
char *dbstr;
|
char *dbstr;
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -765,16 +818,24 @@ delete_allv(clicon_handle h,
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int delete_allv(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return delete_all(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Discard all changes in candidate and replace with running
|
/*! Discard all changes in candidate and replace with running
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
discard_changesv(clicon_handle h,
|
discard_changes(clicon_handle h,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
return clicon_rpc_discard_changes(h);
|
return clicon_rpc_discard_changes(h);
|
||||||
}
|
}
|
||||||
|
int discard_changesv(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return discard_changes(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Copy from one database to another, eg running->startup
|
/*! Copy from one database to another, eg running->startup
|
||||||
* @param[in] argv a string: "<db1> <db2>" Copy from db1 to db2
|
* @param[in] argv a string: "<db1> <db2>" Copy from db1 to db2
|
||||||
|
|
@ -864,9 +925,9 @@ cli_notification_cb(int s,
|
||||||
* XXX: format is a memory leak
|
* XXX: format is a memory leak
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_notifyv(clicon_handle h,
|
cli_notify(clicon_handle h,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
char *stream = NULL;
|
char *stream = NULL;
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -897,6 +958,10 @@ cli_notifyv(clicon_handle h,
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int cli_notifyv(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
{
|
||||||
|
return cli_notify(h, vars, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Lock database
|
/*! Lock database
|
||||||
*
|
*
|
||||||
|
|
@ -976,13 +1041,13 @@ cli_unlock(clicon_handle h,
|
||||||
* tovar: Name of variable containing name of object to copy to.
|
* tovar: Name of variable containing name of object to copy to.
|
||||||
* @code
|
* @code
|
||||||
* cli spec:
|
* cli spec:
|
||||||
* copy snd <n1:string> to <n2:string>, copy_object("candidate", "/sender[%s=%s]", "from", "n1", "n2");
|
* copy snd <n1:string> to <n2:string>, cli_copy_config("candidate", "/sender[%s=%s]", "from", "n1", "n2");
|
||||||
* cli command:
|
* cli command:
|
||||||
* copy snd from to to
|
* copy snd from to to
|
||||||
* @endcode
|
* @endcode
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_copy_object(clicon_handle h,
|
cli_copy_config(clicon_handle h,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
|
|
@ -1080,176 +1145,6 @@ cli_copy_object(clicon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Here are backward compatible cligen callback functions used when
|
|
||||||
* the option: CLICON_CLIGEN_CALLBACK_SINGLE_ARG is set.
|
|
||||||
*/
|
|
||||||
|
|
||||||
cb_single_arg(cli_set)
|
|
||||||
cb_single_arg(cli_merge)
|
|
||||||
cb_single_arg(cli_del)
|
|
||||||
cb_single_arg(cli_debug_cli)
|
|
||||||
cb_single_arg(cli_debug_backend)
|
|
||||||
cb_single_arg(cli_set_mode)
|
|
||||||
cb_single_arg(cli_start_shell)
|
|
||||||
cb_single_arg(cli_quit)
|
|
||||||
//cb_single_arg(cli_commit)
|
|
||||||
int cli_commit(clicon_handle h, cvec *cvv, cg_var *arg)
|
|
||||||
{
|
|
||||||
int retval=-1;
|
|
||||||
cvec *argv = NULL;
|
|
||||||
|
|
||||||
if (arg){
|
|
||||||
if (cv_type_get(arg) > CGV_EMPTY){
|
|
||||||
cligen_output(stderr, "%s: Illegal cvtype. This is most probably a single-argument cligen callback being used in a multi-argument setting. This can happen if option CLICON_CLIGEN_CALLBACK_SINGLE_ARG is 0 but you call a single argument callback (eg %s) from a .cli file. Please change to a multi-argument callback\n", __FUNCTION__, __FUNCTION__);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((argv = cvec_from_var(arg)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "cvec_from_var");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
retval = cli_commitv(h, cvv, argv);
|
|
||||||
done:
|
|
||||||
if (argv) cvec_free(argv);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
cb_single_arg(cli_validate)
|
|
||||||
cb_single_arg(compare_dbs)
|
|
||||||
cb_single_arg(delete_all)
|
|
||||||
cb_single_arg(discard_changes)
|
|
||||||
|
|
||||||
/* Follows some functions not covered by translation macro */
|
|
||||||
int
|
|
||||||
load_config_file(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cg_var *arg)
|
|
||||||
{
|
|
||||||
int retval=-1;
|
|
||||||
cvec *argv;
|
|
||||||
cg_var *cv;
|
|
||||||
char *str;
|
|
||||||
char **vec = NULL;
|
|
||||||
int nvec;
|
|
||||||
|
|
||||||
/* Split string into two parts and build a cvec of it and supply that to
|
|
||||||
the multi-arg callback */
|
|
||||||
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
|
|
||||||
goto done;
|
|
||||||
if (nvec != 2){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "Arg syntax is <varname> <replace|merge>");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((argv = cvec_new(nvec)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "cvec_from_var");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
cv = cvec_i(argv, 0);
|
|
||||||
cv_type_set(cv, CGV_STRING);
|
|
||||||
cv_string_set(cv, vec[0]);
|
|
||||||
cv = cvec_i(argv, 1);
|
|
||||||
cv_type_set(cv, CGV_STRING);
|
|
||||||
cv_string_set(cv, vec[1]);
|
|
||||||
|
|
||||||
retval = load_config_filev(h, cvv, argv);
|
|
||||||
done:
|
|
||||||
if (vec)
|
|
||||||
free(vec);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
save_config_file(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cg_var *arg)
|
|
||||||
{
|
|
||||||
int retval=-1;
|
|
||||||
cvec *argv;
|
|
||||||
cg_var *cv;
|
|
||||||
char *str;
|
|
||||||
char **vec = NULL;
|
|
||||||
int nvec;
|
|
||||||
|
|
||||||
/* Split string into two parts and build a cvec of it and supply that to
|
|
||||||
the multi-arg callback */
|
|
||||||
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
|
|
||||||
goto done;
|
|
||||||
if (nvec != 2){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "Arg syntax is <dbname> <varname>");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((argv = cvec_new(nvec)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "cvec_from_var");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
cv = cvec_i(argv, 0);
|
|
||||||
cv_type_set(cv, CGV_STRING);
|
|
||||||
cv_string_set(cv, vec[0]);
|
|
||||||
cv = cvec_i(argv, 1);
|
|
||||||
cv_type_set(cv, CGV_STRING);
|
|
||||||
cv_string_set(cv, vec[1]);
|
|
||||||
|
|
||||||
retval = save_config_filev(h, cvv, argv);
|
|
||||||
done:
|
|
||||||
if (vec)
|
|
||||||
free(vec);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
cli_notify(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cg_var *arg)
|
|
||||||
{
|
|
||||||
int retval=-1;
|
|
||||||
cvec *argv;
|
|
||||||
cg_var *cv;
|
|
||||||
char *str;
|
|
||||||
char **vec = NULL;
|
|
||||||
int nvec;
|
|
||||||
|
|
||||||
/* Split string into two parts and build a cvec of it and supply that to
|
|
||||||
the multi-arg callback */
|
|
||||||
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
|
|
||||||
goto done;
|
|
||||||
if (nvec != 2 && nvec != 3){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "Arg syntax is <logstream> <status> [<format>]");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((argv = cvec_new(nvec)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "cvec_from_var");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
cv = cvec_i(argv, 0);
|
|
||||||
cv_type_set(cv, CGV_STRING);
|
|
||||||
cv_string_set(cv, vec[0]);
|
|
||||||
|
|
||||||
cv = cvec_i(argv, 1);
|
|
||||||
cv_type_set(cv, CGV_STRING);
|
|
||||||
cv_string_set(cv, vec[1]);
|
|
||||||
if (nvec > 2){
|
|
||||||
cv = cvec_i(argv, 2);
|
|
||||||
cv_type_set(cv, CGV_STRING);
|
|
||||||
cv_string_set(cv, vec[2]);
|
|
||||||
}
|
|
||||||
retval = cli_notifyv(h, cvv, argv);
|
|
||||||
done:
|
|
||||||
if (vec)
|
|
||||||
free(vec);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! set debug level on stderr (not syslog).
|
/*! set debug level on stderr (not syslog).
|
||||||
* The level is either what is specified in arg as int argument.
|
* The level is either what is specified in arg as int argument.
|
||||||
|
|
|
||||||
|
|
@ -65,10 +65,9 @@
|
||||||
|
|
||||||
/* This is the default callback function. But this is typically overwritten */
|
/* This is the default callback function. But this is typically overwritten */
|
||||||
#define GENERATE_CALLBACK "cli_set"
|
#define GENERATE_CALLBACK "cli_set"
|
||||||
#define GENERATE_CALLBACKV "cli_setv"
|
|
||||||
|
|
||||||
/* variable expand function */
|
/* variable expand function */
|
||||||
#define GENERATE_EXPAND_XMLDB "expandv_dbvar"
|
#define GENERATE_EXPAND_XMLDB "expand_dbvar"
|
||||||
|
|
||||||
/*=====================================================================
|
/*=====================================================================
|
||||||
* YANG generate CLI
|
* YANG generate CLI
|
||||||
|
|
@ -154,10 +153,7 @@ cli_callback_generate(clicon_handle h,
|
||||||
|
|
||||||
if (yang2xmlkeyfmt(ys, 0, &xkfmt) < 0)
|
if (yang2xmlkeyfmt(ys, 0, &xkfmt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_option_int(h, "CLICON_CLIGEN_CALLBACK_SINGLE_ARG")==1)
|
cprintf(cb0, ",%s(\"%s\")", GENERATE_CALLBACK, xkfmt);
|
||||||
cprintf(cb0, ",%s(\"%s\")", GENERATE_CALLBACK, xkfmt);
|
|
||||||
else
|
|
||||||
cprintf(cb0, ",%s(\"%s\")", GENERATE_CALLBACKV, xkfmt);
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (xkfmt)
|
if (xkfmt)
|
||||||
|
|
|
||||||
|
|
@ -372,26 +372,13 @@ cli_load_syntax(clicon_handle h, const char *filename, const char *clispec_dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resolve callback names to function pointers. */
|
/* Resolve callback names to function pointers. */
|
||||||
if (clicon_option_int(h, "CLICON_CLIGEN_CALLBACK_SINGLE_ARG")==1){
|
if (cligen_callbackv_str2fn(pt, (cgv_str2fn_t*)clixon_str2fn, handle) < 0){
|
||||||
if (cligen_callback_str2fn(pt, (cg_str2fn_t*)clixon_str2fn, handle) < 0){
|
clicon_err(OE_PLUGIN, 0, "Mismatch between CLIgen file '%s' and CLI plugin file '%s'. Some possible errors:\n\t1. A function given in the CLIgen file does not exist in the plugin (ie link error)\n\t2. The CLIgen spec does not point to the correct plugin .so file (CLICON_PLUGIN=\"%s\" is wrong)",
|
||||||
clicon_err(OE_PLUGIN, 0, "Mismatch between CLIgen file '%s' and CLI plugin file '%s'. Some possible errors:\n\t1. A function given in the CLIgen file does not exist in the plugin (ie link error)\n\t2. The CLIgen spec does not point to the correct plugin .so file (CLICON_PLUGIN=\"%s\" is wrong)",
|
filename, plgnam, plgnam);
|
||||||
filename, plgnam, plgnam);
|
goto done;
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (cligen_callbackv_str2fn(pt, (cgv_str2fn_t*)clixon_str2fn, handle) < 0){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "Mismatch between CLIgen file '%s' and CLI plugin file '%s'. Some possible errors:\n\t1. A function given in the CLIgen file does not exist in the plugin (ie link error)\n\t2. The CLIgen spec does not point to the correct plugin .so file (CLICON_PLUGIN=\"%s\" is wrong)",
|
|
||||||
filename, plgnam, plgnam);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (clicon_option_int(h, "CLICON_CLIGEN_EXPAND_SINGLE_ARG")==1){
|
|
||||||
if (cligen_expand_str2fn(pt, (expand_str2fn_t*)clixon_str2fn, handle) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
else
|
if (cligen_expandv_str2fn(pt, (expandv_str2fn_t*)clixon_str2fn, handle) < 0)
|
||||||
if (cligen_expandv_str2fn(pt, (expandv_str2fn_t*)clixon_str2fn, handle) < 0)
|
goto done;
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Make sure we have a syntax mode specified */
|
/* Make sure we have a syntax mode specified */
|
||||||
if (mode == NULL || strlen(mode) < 1) { /* may be null if not given in file */
|
if (mode == NULL || strlen(mode) < 1) { /* may be null if not given in file */
|
||||||
|
|
|
||||||
|
|
@ -74,9 +74,6 @@
|
||||||
#include "clixon_cli_api.h"
|
#include "clixon_cli_api.h"
|
||||||
#include "cli_common.h" /* internal functions */
|
#include "cli_common.h" /* internal functions */
|
||||||
|
|
||||||
static int xml2csv(FILE *f, cxobj *x, cvec *cvv);
|
|
||||||
//static int xml2csv_raw(FILE *f, cxobj *x);
|
|
||||||
|
|
||||||
/*! Completion callback intended for automatically generated data model
|
/*! Completion callback intended for automatically generated data model
|
||||||
*
|
*
|
||||||
* Returns an expand-type list of commands as used by cligen 'expand'
|
* Returns an expand-type list of commands as used by cligen 'expand'
|
||||||
|
|
@ -94,12 +91,12 @@ static int xml2csv(FILE *f, cxobj *x, cvec *cvv);
|
||||||
* XXX: helptexts?
|
* XXX: helptexts?
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
expandv_dbvar(void *h,
|
expand_dbvar(void *h,
|
||||||
char *name,
|
char *name,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv,
|
cvec *argv,
|
||||||
cvec *commands,
|
cvec *commands,
|
||||||
cvec *helptexts)
|
cvec *helptexts)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *xkfmt;
|
char *xkfmt;
|
||||||
|
|
@ -197,13 +194,24 @@ expandv_dbvar(void *h,
|
||||||
free(xkpath);
|
free(xkpath);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int
|
||||||
|
expandv_dbvar(void *h,
|
||||||
|
char *name,
|
||||||
|
cvec *cvv,
|
||||||
|
cvec *argv,
|
||||||
|
cvec *commands,
|
||||||
|
cvec *helptexts)
|
||||||
|
{
|
||||||
|
return expand_dbvar(h, name, cvv, argv, commands, helptexts);
|
||||||
|
}
|
||||||
/*! List files in a directory
|
/*! List files in a directory
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
expand_dir(char *dir, int *nr, char ***commands, mode_t flags, int detail)
|
expand_dir(char *dir,
|
||||||
|
int *nr,
|
||||||
|
char ***commands,
|
||||||
|
mode_t flags,
|
||||||
|
int detail)
|
||||||
{
|
{
|
||||||
DIR *dirp;
|
DIR *dirp;
|
||||||
struct dirent *dp;
|
struct dirent *dp;
|
||||||
|
|
@ -313,13 +321,11 @@ expand_dir(char *dir, int *nr, char ***commands, mode_t flags, int detail)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! CLI callback show yang spec. If arg given matches yang argument string */
|
/*! CLI callback show yang spec. If arg given matches yang argument string */
|
||||||
int
|
int
|
||||||
show_yangv(clicon_handle h,
|
show_yang(clicon_handle h,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
yang_node *yn;
|
yang_node *yn;
|
||||||
char *str = NULL;
|
char *str = NULL;
|
||||||
|
|
@ -335,362 +341,9 @@ show_yangv(clicon_handle h,
|
||||||
yang_print(stdout, yn, 0);
|
yang_print(stdout, yn, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int show_yangv(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
|
||||||
#ifdef notused
|
|
||||||
/*! XML to CSV raw variant
|
|
||||||
* @see xml2csv
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
xml2csv_raw(FILE *f, cxobj *x)
|
|
||||||
{
|
{
|
||||||
cxobj *xc;
|
return show_yang(h, vars, argv);
|
||||||
cxobj *xb;
|
|
||||||
int retval = -1;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
xc = NULL;
|
|
||||||
while ((xc = xml_child_each(x, xc, CX_ELMNT)) != NULL) {
|
|
||||||
if (xml_child_nr(xc)){
|
|
||||||
xb = xml_child_i(xc, 0);
|
|
||||||
if (xml_type(xb) == CX_BODY){
|
|
||||||
if (i++)
|
|
||||||
fprintf(f, ";");
|
|
||||||
fprintf(f, "%s", xml_value(xb));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fprintf(f, "\n");
|
|
||||||
retval = 0;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*! Translate XML -> CSV commands
|
|
||||||
* Can only be made in a 'flat tree', ie on the form:
|
|
||||||
* <X><A>B</A></X> -->
|
|
||||||
* Type, A
|
|
||||||
* X, B
|
|
||||||
* @param[in] f Output file
|
|
||||||
* @param[in] x XML tree
|
|
||||||
* @param[in] cvv A vector of field names present in XML
|
|
||||||
* This means that only fields in x that are listed in cvv will be printed.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
xml2csv(FILE *f, cxobj *x, cvec *cvv)
|
|
||||||
{
|
|
||||||
cxobj *xe, *xb;
|
|
||||||
int retval = -1;
|
|
||||||
cg_var *vs;
|
|
||||||
|
|
||||||
fprintf(f, "%s", xml_name(x));
|
|
||||||
xe = NULL;
|
|
||||||
|
|
||||||
vs = NULL;
|
|
||||||
while ((vs = cvec_each(cvv, vs))) {
|
|
||||||
if ((xe = xml_find(x, cv_name_get(vs))) == NULL){
|
|
||||||
fprintf(f, ";");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (xml_child_nr(xe)){
|
|
||||||
xb = xml_child_i(xe, 0);
|
|
||||||
fprintf(f, ";%s", xml_value(xb));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fprintf(f, "\n");
|
|
||||||
retval = 0;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Generic function for showing configurations.
|
|
||||||
* Utility function used by cligen spec file
|
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] cvv Vector of variables from CLIgen command-line
|
|
||||||
* @param[in] argv A string: <dbname> <xpath> [<varname>]
|
|
||||||
* @param[out] xt Configuration as xml tree.
|
|
||||||
* Format of argv:
|
|
||||||
* <dbname> "running", "candidate", "startup"
|
|
||||||
* <xpath> xpath expression
|
|
||||||
* <varname> optional name of variable in cvv. If set, xpath must have a '%s'
|
|
||||||
* @code
|
|
||||||
* show config id <n:string>, show_conf_as("running interfaces/interface[name=%s] n");
|
|
||||||
* @endcode
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
show_confv_as(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cvec *argv,
|
|
||||||
cxobj **xt) /* top xml */
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
char *db;
|
|
||||||
char *xpath;
|
|
||||||
char *attr = NULL;
|
|
||||||
cbuf *cbx = NULL;
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
cg_var *cvattr;
|
|
||||||
char *val = NULL;
|
|
||||||
|
|
||||||
if (cvec_len(argv) != 2 && cvec_len(argv) != 3){
|
|
||||||
if (cvec_len(argv)==1)
|
|
||||||
clicon_err(OE_PLUGIN, 0, "Got single argument:\"%s\". Expected \"<dbname>,<xpath>[,<attr>]\"", cv_string_get(cvec_i(argv,0)));
|
|
||||||
else
|
|
||||||
clicon_err(OE_PLUGIN, 0, "Got %d arguments. Expected: <dbname>,<xpath>[,<attr>]", cvec_len(argv));
|
|
||||||
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* Dont get attr here, take it from arg instead */
|
|
||||||
db = cv_string_get(cvec_i(argv, 0));
|
|
||||||
if (strcmp(db, "running") != 0 &&
|
|
||||||
strcmp(db, "candidate") != 0 &&
|
|
||||||
strcmp(db, "startup") != 0) {
|
|
||||||
clicon_err(OE_PLUGIN, 0, "No such db name: %s", db);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
xpath = cv_string_get(cvec_i(argv, 1));
|
|
||||||
if ((cbx = cbuf_new()) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, errno, "cbuf_new");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (cvec_len(argv) == 3){
|
|
||||||
attr = cv_string_get(cvec_i(argv, 2));
|
|
||||||
j = 0;
|
|
||||||
for (i=0; i<strlen(xpath); i++)
|
|
||||||
if (xpath[i] == '%')
|
|
||||||
j++;
|
|
||||||
if (j != 1){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "xpath '%s' does not have a single '%%'");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((cvattr = cvec_find_var(cvv, attr)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "attr '%s' not found in cligen var list", attr);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((val = cv2str_dup(cvattr)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, errno, "cv2str_dup");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
cprintf(cbx, xpath, val);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cprintf(cbx, "%s", xpath);
|
|
||||||
if (clicon_rpc_get_config(h, db, cbuf_get(cbx), xt) < 0)
|
|
||||||
goto done;
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (val)
|
|
||||||
free(val);
|
|
||||||
if (cbx)
|
|
||||||
cbuf_free(cbx);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Show a configuration database on stdout using XML format
|
|
||||||
* Utility function used by cligen spec file
|
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] cvv Vector of variables from CLIgen command-line
|
|
||||||
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
|
||||||
* @param[in] netconf If set print as netconf edit-config, otherwise just xml
|
|
||||||
* @see show_conf_as the main function
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
show_confv_as_xml1(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cvec *argv,
|
|
||||||
int netconf)
|
|
||||||
{
|
|
||||||
cxobj *xt = NULL;
|
|
||||||
cxobj *xc;
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
if (show_confv_as(h, cvv, argv, &xt) < 0)
|
|
||||||
goto done;
|
|
||||||
if (netconf) /* netconf prefix */
|
|
||||||
fprintf(stdout, "<rpc><edit-config><target><candidate/></target><config>\n");
|
|
||||||
xc = NULL; /* Dont print xt itself */
|
|
||||||
while ((xc = xml_child_each(xt, xc, -1)) != NULL)
|
|
||||||
clicon_xml2file(stdout, xc, netconf?2:0, 1);
|
|
||||||
if (netconf) /* netconf postfix */
|
|
||||||
fprintf(stdout, "</config></edit-config></rpc>]]>]]>\n");
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (xt)
|
|
||||||
xml_free(xt);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Show configuration as prettyprinted xml
|
|
||||||
* Utility function used by cligen spec file
|
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] cvv Vector of variables from CLIgen command-line
|
|
||||||
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
|
||||||
* @see show_conf_as the main function
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
show_confv_as_xml(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cvec *argv)
|
|
||||||
{
|
|
||||||
return show_confv_as_xml1(h, cvv, argv, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Show configuration as prettyprinted xml with netconf hdr/tail
|
|
||||||
* Utility function used by cligen spec file
|
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] cvv Vector of variables from CLIgen command-line
|
|
||||||
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
|
||||||
* @see show_conf_as the main function
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
show_confv_as_netconf(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cvec *argv)
|
|
||||||
{
|
|
||||||
return show_confv_as_xml1(h, cvv, argv, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Show configuration as JSON
|
|
||||||
* Utility function used by cligen spec file
|
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] cvv Vector of variables from CLIgen command-line
|
|
||||||
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
|
||||||
* @see show_conf_as the main function
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
show_confv_as_json(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cvec *argv)
|
|
||||||
{
|
|
||||||
cxobj *xt = NULL;
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
if (show_confv_as(h, cvv, argv, &xt) < 0)
|
|
||||||
goto done;
|
|
||||||
xml2json(stdout, xt, 1);
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (xt)
|
|
||||||
xml_free(xt);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! Show configuration as text
|
|
||||||
* Utility function used by cligen spec file
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
show_confv_as_text1(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cvec *argv)
|
|
||||||
{
|
|
||||||
cxobj *xt = NULL;
|
|
||||||
cxobj *xc;
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
if (show_confv_as(h, cvv, argv, &xt) < 0)
|
|
||||||
goto done;
|
|
||||||
xc = NULL; /* Dont print xt itself */
|
|
||||||
while ((xc = xml_child_each(xt, xc, -1)) != NULL)
|
|
||||||
xml2txt(stdout, xc, 0); /* tree-formed text */
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (xt)
|
|
||||||
xml_free(xt);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Show configuration as commands, ie not tree format but as one-line commands
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
show_confv_as_command(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cvec *argv,
|
|
||||||
char *prepend)
|
|
||||||
{
|
|
||||||
cxobj *xt = NULL;
|
|
||||||
cxobj *xc;
|
|
||||||
enum genmodel_type gt;
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
if (show_confv_as(h, cvv, argv, &xt) < 0)
|
|
||||||
goto done;
|
|
||||||
xc = NULL; /* Dont print xt itself */
|
|
||||||
while ((xc = xml_child_each(xt, xc, -1)) != NULL){
|
|
||||||
if ((gt = clicon_cli_genmodel_type(h)) == GT_ERR)
|
|
||||||
goto done;
|
|
||||||
xml2cli(stdout, xc, prepend, gt); /* cli syntax */
|
|
||||||
}
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (xt)
|
|
||||||
xml_free(xt);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
show_confv_as_text(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cvec *argv)
|
|
||||||
{
|
|
||||||
return show_confv_as_text1(h, cvv, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
show_confv_as_cli(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cvec *argv)
|
|
||||||
{
|
|
||||||
return show_confv_as_command(h, cvv, argv, NULL); /* XXX: how to set prepend? */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
show_confv_as_csv1(clicon_handle h,
|
|
||||||
cvec *cvv0,
|
|
||||||
cvec *argv)
|
|
||||||
{
|
|
||||||
cxobj *xt = NULL;
|
|
||||||
cxobj *xc;
|
|
||||||
int retval = -1;
|
|
||||||
cvec *cvv=NULL;
|
|
||||||
char *str;
|
|
||||||
|
|
||||||
if (show_confv_as(h, cvv0, argv, &xt) < 0)
|
|
||||||
goto done;
|
|
||||||
xc = NULL; /* Dont print xt itself */
|
|
||||||
while ((xc = xml_child_each(xt, xc, -1)) != NULL){
|
|
||||||
if ((str = chunk_sprintf(__FUNCTION__, "%s[]", xml_name(xc))) == NULL)
|
|
||||||
goto done;
|
|
||||||
#ifdef NOTYET /* yang-spec? */
|
|
||||||
if (ds==NULL && (ds = key2spec_key(dbspec, str)) != NULL){
|
|
||||||
cg_var *vs;
|
|
||||||
fprintf(stdout, "Type");
|
|
||||||
cvv = db_spec2cvec(ds);
|
|
||||||
vs = NULL;
|
|
||||||
while ((vs = cvec_each(cvv, vs)))
|
|
||||||
fprintf(stdout, ";%s", cv_name_get(vs));
|
|
||||||
fprintf(stdout, "\n");
|
|
||||||
} /* Now values just need to follow,... */
|
|
||||||
#endif /* yang-spec? */
|
|
||||||
if (cvv== NULL)
|
|
||||||
goto done;
|
|
||||||
xml2csv(stdout, xc, cvv); /* csv syntax */
|
|
||||||
}
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (xt)
|
|
||||||
xml_free(xt);
|
|
||||||
unchunk_group(__FUNCTION__);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
show_confv_as_csv(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cvec *argv)
|
|
||||||
{
|
|
||||||
return show_confv_as_csv1(h, cvv, argv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Generic show configuration CLIGEN callback
|
/*! Generic show configuration CLIGEN callback
|
||||||
|
|
@ -704,13 +357,13 @@ show_confv_as_csv(clicon_handle h,
|
||||||
* <xpath> xpath expression, that may contain one %, eg "/sender[name=%s]"
|
* <xpath> xpath expression, that may contain one %, eg "/sender[name=%s]"
|
||||||
* <varname> optional name of variable in cvv. If set, xpath must have a '%s'
|
* <varname> optional name of variable in cvv. If set, xpath must have a '%s'
|
||||||
* @code
|
* @code
|
||||||
* show config id <n:string>, show_conf_as("running","xml","iface[name=%s]","n");
|
* show config id <n:string>, cli_show_config("running","xml","iface[name=%s]","n");
|
||||||
* @endcode
|
* @endcode
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
show_configuration(clicon_handle h,
|
cli_show_config(clicon_handle h,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *db;
|
char *db;
|
||||||
|
|
@ -824,9 +477,9 @@ done:
|
||||||
* @note Hardcoded that a variable in cvv is named "xpath"
|
* @note Hardcoded that a variable in cvv is named "xpath"
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
show_confv_xpath(clicon_handle h,
|
show_conf_xpath(clicon_handle h,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *str;
|
char *str;
|
||||||
|
|
@ -866,417 +519,7 @@ done:
|
||||||
xml_free(xt);
|
xml_free(xt);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
int show_confv_xpath(clicon_handle h, cvec *vars, cvec *argv)
|
||||||
|
|
||||||
/*=================================================================
|
|
||||||
* Here are backward compatible cligen callback functions used when
|
|
||||||
* the option: CLICON_CLIGEN_CALLBACK_SINGLE_ARG is set.
|
|
||||||
*/
|
|
||||||
|
|
||||||
cb_single_arg(show_yang)
|
|
||||||
|
|
||||||
/*! This is obsolete version of expandv_dbvar
|
|
||||||
* If CLICON_CLIGEN_EXPAND_SINGLE_ARG is set
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
expand_dbvar(void *h,
|
|
||||||
char *name,
|
|
||||||
cvec *cvv,
|
|
||||||
cg_var *arg,
|
|
||||||
int *nr,
|
|
||||||
char ***commands,
|
|
||||||
char ***helptexts)
|
|
||||||
{
|
{
|
||||||
int nvec;
|
return show_conf_xpath(h, vars, argv);
|
||||||
char **vec = NULL;
|
|
||||||
int retval = -1;
|
|
||||||
char *xkfmt;
|
|
||||||
char *str;
|
|
||||||
char *dbstr;
|
|
||||||
cxobj *xt = NULL;
|
|
||||||
char *xkpath = NULL;
|
|
||||||
cxobj **xvec = NULL;
|
|
||||||
size_t xlen = 0;
|
|
||||||
cxobj *x;
|
|
||||||
char *bodystr;
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
int k;
|
|
||||||
int i0;
|
|
||||||
|
|
||||||
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* In the example, str = "candidate /x/m1/%s/b" */
|
|
||||||
if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
|
|
||||||
goto done;
|
|
||||||
dbstr = vec[0];
|
|
||||||
if (strcmp(dbstr, "running") != 0 &&
|
|
||||||
strcmp(dbstr, "candidate") != 0 &&
|
|
||||||
strcmp(dbstr, "startup") != 0){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
xkfmt = vec[1];
|
|
||||||
/* xkfmt = /interface=%s/address=%s
|
|
||||||
--> /interface=eth0/address=1.2.3.4
|
|
||||||
*/
|
|
||||||
if (xmlkeyfmt2xpath(xkfmt, cvv, &xkpath) < 0)
|
|
||||||
goto done;
|
|
||||||
if (clicon_rpc_get_config(h, dbstr, "/", &xt) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xpath_vec(xt, xkpath, &xvec, &xlen) < 0)
|
|
||||||
goto done;
|
|
||||||
/* One round to detect duplicates
|
|
||||||
* XXX The code below would benefit from some cleanup
|
|
||||||
*/
|
|
||||||
j = 0;
|
|
||||||
for (i = 0; i < xlen; i++) {
|
|
||||||
char *str;
|
|
||||||
x = xvec[i];
|
|
||||||
if (xml_type(x) == CX_BODY)
|
|
||||||
bodystr = xml_value(x);
|
|
||||||
else
|
|
||||||
bodystr = xml_body(x);
|
|
||||||
if (bodystr == NULL){
|
|
||||||
clicon_err(OE_CFG, 0, "No xml body");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* detect duplicates */
|
|
||||||
for (k=0; k<j; k++){
|
|
||||||
if (xml_type(xvec[k]) == CX_BODY)
|
|
||||||
str = xml_value(xvec[k]);
|
|
||||||
else
|
|
||||||
str = xml_body(xvec[k]);
|
|
||||||
if (strcmp(str, bodystr)==0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (k==j) /* not duplicate */
|
|
||||||
xvec[j++] = x;
|
|
||||||
}
|
|
||||||
xlen = j;
|
|
||||||
i0 = *nr;
|
|
||||||
*nr += xlen;
|
|
||||||
if ((*commands = realloc(*commands, sizeof(char *) * (*nr))) == NULL) {
|
|
||||||
clicon_err(OE_UNIX, errno, "realloc: %s", strerror (errno));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
for (i = 0; i < xlen; i++) {
|
|
||||||
x = xvec[i];
|
|
||||||
if (xml_type(x) == CX_BODY)
|
|
||||||
bodystr = xml_value(x);
|
|
||||||
else
|
|
||||||
bodystr = xml_body(x);
|
|
||||||
if (bodystr == NULL){
|
|
||||||
clicon_err(OE_CFG, 0, "No xml body");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
(*commands)[i0+i] = strdup(bodystr);
|
|
||||||
}
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (vec)
|
|
||||||
free(vec);
|
|
||||||
if (xvec)
|
|
||||||
free(xvec);
|
|
||||||
if (xt)
|
|
||||||
xml_free(xt);
|
|
||||||
if (xkpath)
|
|
||||||
free(xkpath);
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! Generic function for showing configurations.
|
|
||||||
* Utility function used by cligen spec file
|
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] cvv Vector of variables from CLIgen command-line
|
|
||||||
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
|
||||||
* @param[out] xt Configuration as xml tree.
|
|
||||||
* Format of arg:
|
|
||||||
* <dbname> "running", "candidate", "startup"
|
|
||||||
* <xpath> xpath expression
|
|
||||||
* <varname> optional name of variable in cvv. If set, xpath must have a '%s'
|
|
||||||
* @code
|
|
||||||
* show config id <n:string>, show_conf_as("running interfaces/interface[name=%s] n");
|
|
||||||
* @endcode
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
show_conf_as(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cg_var *arg,
|
|
||||||
cxobj **xt) /* top xml */
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
char *db;
|
|
||||||
char **vec = NULL;
|
|
||||||
int nvec;
|
|
||||||
char *str;
|
|
||||||
char *xpath;
|
|
||||||
char *attr = NULL;
|
|
||||||
cbuf *cbx = NULL;
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
cg_var *cvattr;
|
|
||||||
char *val = NULL;
|
|
||||||
|
|
||||||
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((vec = clicon_strsep(str, " ", &nvec)) == NULL)
|
|
||||||
goto done;
|
|
||||||
if (nvec != 2 && nvec != 3){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "format error \"%s\" - expected <dbname> <xpath> [<attr>] got %d arg", str, nvec);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* Dont get attr here, take it from arg instead */
|
|
||||||
db = vec[0];
|
|
||||||
if (strcmp(db, "running") != 0 &&
|
|
||||||
strcmp(db, "candidate") != 0 &&
|
|
||||||
strcmp(db, "startup") != 0) {
|
|
||||||
clicon_err(OE_PLUGIN, 0, "No such db name: %s", db);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
xpath = vec[1];
|
|
||||||
if ((cbx = cbuf_new()) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, errno, "cbuf_new");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (nvec == 3){
|
|
||||||
attr = vec[2];
|
|
||||||
j = 0;
|
|
||||||
for (i=0; i<strlen(xpath); i++)
|
|
||||||
if (xpath[i] == '%')
|
|
||||||
j++;
|
|
||||||
if (j != 1){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "xpath '%s' does not have a single '%%'");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((cvattr = cvec_find_var(cvv, attr)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "attr '%s' not found in cligen var list", attr);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((val = cv2str_dup(cvattr)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, errno, "cv2str_dup");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
cprintf(cbx, xpath, val);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cprintf(cbx, "%s", xpath);
|
|
||||||
if (clicon_rpc_get_config(h, db, cbuf_get(cbx), xt) < 0)
|
|
||||||
goto done;
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (val)
|
|
||||||
free(val);
|
|
||||||
if (cbx)
|
|
||||||
cbuf_free(cbx);
|
|
||||||
if (vec)
|
|
||||||
free(vec);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! Show a configuration database on stdout using XML format
|
|
||||||
* Utility function used by cligen spec file
|
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] cvv Vector of variables from CLIgen command-line
|
|
||||||
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
|
||||||
* @param[in] netconf If set print as netconf edit-config, otherwise just xml
|
|
||||||
* @see show_conf_as the main function
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
show_conf_as_xml1(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cg_var *arg,
|
|
||||||
int netconf)
|
|
||||||
{
|
|
||||||
cxobj *xt = NULL;
|
|
||||||
cxobj *xc;
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
if (show_conf_as(h, cvv, arg, &xt) < 0)
|
|
||||||
goto done;
|
|
||||||
if (netconf) /* netconf prefix */
|
|
||||||
fprintf(stdout, "<rpc><edit-config><target><candidate/></target><config>\n");
|
|
||||||
xc = NULL; /* Dont print xt itself */
|
|
||||||
while ((xc = xml_child_each(xt, xc, -1)) != NULL)
|
|
||||||
clicon_xml2file(stdout, xc, netconf?2:0, 1);
|
|
||||||
if (netconf) /* netconf postfix */
|
|
||||||
fprintf(stdout, "</config></edit-config></rpc>]]>]]>\n");
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (xt)
|
|
||||||
xml_free(xt);
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Show configuration as prettyprinted xml
|
|
||||||
* Utility function used by cligen spec file
|
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] cvv Vector of variables from CLIgen command-line
|
|
||||||
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
|
||||||
* @see show_conf_as the main function
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
show_conf_as_xml(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cg_var *arg)
|
|
||||||
{
|
|
||||||
return show_conf_as_xml1(h, cvv, arg, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Show configuration as prettyprinted xml with netconf hdr/tail
|
|
||||||
* Utility function used by cligen spec file
|
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] cvv Vector of variables from CLIgen command-line
|
|
||||||
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
|
||||||
* @see show_conf_as the main function
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
show_conf_as_netconf(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cg_var *arg)
|
|
||||||
{
|
|
||||||
return show_conf_as_xml1(h, cvv, arg, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Show configuration as JSON
|
|
||||||
* Utility function used by cligen spec file
|
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] cvv Vector of variables from CLIgen command-line
|
|
||||||
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
|
||||||
* @see show_conf_as the main function
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
show_conf_as_json(clicon_handle h,
|
|
||||||
cvec *cvv,
|
|
||||||
cg_var *arg)
|
|
||||||
{
|
|
||||||
cxobj *xt = NULL;
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
if (show_conf_as(h, cvv, arg, &xt) < 0)
|
|
||||||
goto done;
|
|
||||||
xml2json(stdout, xt, 1);
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (xt)
|
|
||||||
xml_free(xt);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! Show configuration as text
|
|
||||||
* Utility function used by cligen spec file
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
show_conf_as_text1(clicon_handle h, cvec *cvv, cg_var *arg)
|
|
||||||
{
|
|
||||||
cxobj *xt = NULL;
|
|
||||||
cxobj *xc;
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
if (show_conf_as(h, cvv, arg, &xt) < 0)
|
|
||||||
goto done;
|
|
||||||
xc = NULL; /* Dont print xt itself */
|
|
||||||
while ((xc = xml_child_each(xt, xc, -1)) != NULL)
|
|
||||||
xml2txt(stdout, xc, 0); /* tree-formed text */
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (xt)
|
|
||||||
xml_free(xt);
|
|
||||||
unchunk_group(__FUNCTION__);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Show configuration as commands, ie not tree format but as one-line commands
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
show_conf_as_command(clicon_handle h, cvec *cvv, cg_var *arg, char *prepend)
|
|
||||||
{
|
|
||||||
cxobj *xt = NULL;
|
|
||||||
cxobj *xc;
|
|
||||||
enum genmodel_type gt;
|
|
||||||
int retval = -1;
|
|
||||||
|
|
||||||
if ((xt = xml_new("tmp", NULL)) == NULL)
|
|
||||||
goto done;
|
|
||||||
if (show_conf_as(h, cvv, arg, &xt) < 0)
|
|
||||||
goto done;
|
|
||||||
xc = NULL; /* Dont print xt itself */
|
|
||||||
while ((xc = xml_child_each(xt, xc, -1)) != NULL){
|
|
||||||
if ((gt = clicon_cli_genmodel_type(h)) == GT_ERR)
|
|
||||||
goto done;
|
|
||||||
xml2cli(stdout, xc, prepend, gt); /* cli syntax */
|
|
||||||
}
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (xt)
|
|
||||||
xml_free(xt);
|
|
||||||
unchunk_group(__FUNCTION__);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
show_conf_as_text(clicon_handle h, cvec *cvv, cg_var *arg)
|
|
||||||
{
|
|
||||||
return show_conf_as_text1(h, cvv, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
show_conf_as_cli(clicon_handle h, cvec *cvv, cg_var *arg)
|
|
||||||
{
|
|
||||||
return show_conf_as_command(h, cvv, arg, NULL); /* XXX: how to set prepend? */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
show_conf_as_csv1(clicon_handle h, cvec *cvv0, cg_var *arg)
|
|
||||||
{
|
|
||||||
cxobj *xt = NULL;
|
|
||||||
cxobj *xc;
|
|
||||||
int retval = -1;
|
|
||||||
cvec *cvv=NULL;
|
|
||||||
char *str;
|
|
||||||
|
|
||||||
if (show_conf_as(h, cvv0, arg, &xt) < 0)
|
|
||||||
goto done;
|
|
||||||
xc = NULL; /* Dont print xt itself */
|
|
||||||
while ((xc = xml_child_each(xt, xc, -1)) != NULL){
|
|
||||||
if ((str = chunk_sprintf(__FUNCTION__, "%s[]", xml_name(xc))) == NULL)
|
|
||||||
goto done;
|
|
||||||
#ifdef NOTYET /* yang-spec? */
|
|
||||||
if (ds==NULL && (ds = key2spec_key(dbspec, str)) != NULL){
|
|
||||||
cg_var *vs;
|
|
||||||
fprintf(stdout, "Type");
|
|
||||||
cvv = db_spec2cvec(ds);
|
|
||||||
vs = NULL;
|
|
||||||
while ((vs = cvec_each(cvv, vs)))
|
|
||||||
fprintf(stdout, ";%s", cv_name_get(vs));
|
|
||||||
fprintf(stdout, "\n");
|
|
||||||
} /* Now values just need to follow,... */
|
|
||||||
#endif /* yang-spec? */
|
|
||||||
if (cvv== NULL)
|
|
||||||
goto done;
|
|
||||||
xml2csv(stdout, xc, cvv); /* csv syntax */
|
|
||||||
}
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (xt)
|
|
||||||
xml_free(xt);
|
|
||||||
unchunk_group(__FUNCTION__);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
show_conf_as_csv(clicon_handle h, cvec *cvv, cg_var *arg)
|
|
||||||
{
|
|
||||||
return show_conf_as_csv1(h, cvv, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,67 +74,76 @@ int cli_notification_register(clicon_handle h, char *stream, enum format_enum fo
|
||||||
|
|
||||||
#define cli_output cligen_output
|
#define cli_output cligen_output
|
||||||
/* cli_common.c: CLIgen new vector callbacks */
|
/* cli_common.c: CLIgen new vector callbacks */
|
||||||
|
|
||||||
|
|
||||||
|
int cli_set(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int cli_setv(clicon_handle h, cvec *vars, cvec *argv);
|
int cli_setv(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int cli_merge(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int cli_mergev(clicon_handle h, cvec *vars, cvec *argv);
|
int cli_mergev(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int cli_del(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int cli_delv(clicon_handle h, cvec *vars, cvec *argv);
|
int cli_delv(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int cli_debug_cli(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int cli_debug_cliv(clicon_handle h, cvec *vars, cvec *argv);
|
int cli_debug_cliv(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int cli_debug_backend(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int cli_debug_backendv(clicon_handle h, cvec *vars, cvec *argv);
|
int cli_debug_backendv(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int cli_set_mode(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int cli_set_modev(clicon_handle h, cvec *vars, cvec *argv);
|
int cli_set_modev(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int cli_start_shell(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int cli_start_shellv(clicon_handle h, cvec *vars, cvec *argv);
|
int cli_start_shellv(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int cli_quit(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int cli_quitv(clicon_handle h, cvec *vars, cvec *argv);
|
int cli_quitv(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int cli_commit(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int cli_commitv(clicon_handle h, cvec *vars, cvec *argv);
|
int cli_commitv(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int cli_validate(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int cli_validatev(clicon_handle h, cvec *vars, cvec *argv);
|
int cli_validatev(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int compare_dbs(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int compare_dbsv(clicon_handle h, cvec *vars, cvec *argv);
|
int compare_dbsv(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int load_config_file(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int load_config_filev(clicon_handle h, cvec *vars, cvec *argv);
|
int load_config_filev(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int save_config_file(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int save_config_filev(clicon_handle h, cvec *vars, cvec *argv);
|
int save_config_filev(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int delete_all(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int delete_allv(clicon_handle h, cvec *vars, cvec *argv);
|
int delete_allv(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int discard_changes(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int discard_changesv(clicon_handle h, cvec *vars, cvec *argv);
|
int discard_changesv(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int cli_notify(clicon_handle h, cvec *cvv, cvec *argv);
|
||||||
int cli_notifyv(clicon_handle h, cvec *cvv, cvec *argv);
|
int cli_notifyv(clicon_handle h, cvec *cvv, cvec *argv);
|
||||||
|
|
||||||
|
int db_copy(clicon_handle h, cvec *cvv, cvec *argv);
|
||||||
|
|
||||||
int cli_lock(clicon_handle h, cvec *cvv, cvec *argv);
|
int cli_lock(clicon_handle h, cvec *cvv, cvec *argv);
|
||||||
int cli_unlock(clicon_handle h, cvec *cvv, cvec *argv);
|
int cli_unlock(clicon_handle h, cvec *cvv, cvec *argv);
|
||||||
int cli_copy_object(clicon_handle h, cvec *cvv, cvec *argv);
|
int cli_copy_config(clicon_handle h, cvec *cvv, cvec *argv);
|
||||||
|
|
||||||
/* cli_common.c: CLIgen old single arg callbacks */
|
|
||||||
int cli_set(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int cli_merge(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int cli_del(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int cli_debug_cli(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int cli_debug_backend(clicon_handle h, cvec *vars, cg_var *argv);
|
|
||||||
int cli_set_mode(clicon_handle h, cvec *vars, cg_var *argv);
|
|
||||||
int cli_start_shell(clicon_handle h, cvec *vars, cg_var *argv);
|
|
||||||
int cli_quit(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int cli_commit(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int cli_validate(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int compare_dbs(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int load_config_file(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int save_config_file(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int delete_all(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int discard_changes(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int cli_notify(clicon_handle h, cvec *cvv, cg_var *arg);
|
|
||||||
|
|
||||||
/* In cli_show.c */
|
/* In cli_show.c */
|
||||||
int expand_dir(char *dir, int *nr, char ***commands, mode_t flags, int detail);
|
int expand_dir(char *dir, int *nr, char ***commands, mode_t flags, int detail);
|
||||||
|
int expand_dbvar(void *h, char *name, cvec *cvv, cvec *argv,
|
||||||
|
cvec *commands, cvec *helptexts);
|
||||||
int expandv_dbvar(void *h, char *name, cvec *cvv, cvec *argv,
|
int expandv_dbvar(void *h, char *name, cvec *cvv, cvec *argv,
|
||||||
cvec *commands, cvec *helptexts);
|
cvec *commands, cvec *helptexts);
|
||||||
|
|
||||||
/* cli_show.c: CLIgen new vector arg callbacks */
|
/* cli_show.c: CLIgen new vector arg callbacks */
|
||||||
int show_confv_as_xml(clicon_handle h, cvec *vars, cvec *argv);
|
int show_yang(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
int show_confv_as_netconf(clicon_handle h, cvec *vars, cvec *argv);
|
|
||||||
int show_confv_as_json(clicon_handle h, cvec *vars, cvec *argv);
|
|
||||||
int show_confv_as_text(clicon_handle h, cvec *vars, cvec *argv);
|
|
||||||
int show_confv_as_cli(clicon_handle h, cvec *vars, cvec *argv);
|
|
||||||
int show_confv_as_csv(clicon_handle h, cvec *vars, cvec *argv);
|
|
||||||
int show_yangv(clicon_handle h, cvec *vars, cvec *argv);
|
int show_yangv(clicon_handle h, cvec *vars, cvec *argv);
|
||||||
|
|
||||||
|
int show_conf_xpath(clicon_handle h, cvec *cvv, cvec *argv);
|
||||||
int show_confv_xpath(clicon_handle h, cvec *cvv, cvec *argv);
|
int show_confv_xpath(clicon_handle h, cvec *cvv, cvec *argv);
|
||||||
|
|
||||||
int show_configuration(clicon_handle h, cvec *cvv, cvec *argv);
|
int cli_show_config(clicon_handle h, cvec *cvv, cvec *argv);
|
||||||
|
|
||||||
/* cli_show.c: CLIgen old single arg callbacks */
|
|
||||||
int show_conf_as_xml(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int show_conf_as_netconf(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int show_conf_as_json(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int show_conf_as_text(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int show_conf_as_cli(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int show_conf_as_csv(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
int show_yang(clicon_handle h, cvec *vars, cg_var *arg);
|
|
||||||
|
|
||||||
#endif /* _CLIXON_CLI_API_H_ */
|
#endif /* _CLIXON_CLI_API_H_ */
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,8 @@ api_data(clicon_handle h,
|
||||||
retval = api_data_post(h, r, api_path, pcvec, pi, qvec, data);
|
retval = api_data_post(h, r, api_path, pcvec, pi, qvec, data);
|
||||||
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);
|
||||||
|
else if (strcmp(request_method, "PATCH")==0)
|
||||||
|
retval = api_data_patch(h, r, api_path, pcvec, pi, qvec, data);
|
||||||
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
|
||||||
|
|
@ -180,7 +182,7 @@ request_process(clicon_handle h,
|
||||||
else
|
else
|
||||||
retval = notfound(r);
|
retval = notfound(r);
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s retval:%d K", __FUNCTION__, retval);
|
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||||
if (pvec)
|
if (pvec)
|
||||||
free(pvec);
|
free(pvec);
|
||||||
if (dvec)
|
if (dvec)
|
||||||
|
|
|
||||||
|
|
@ -347,14 +347,14 @@ api_data_edit(clicon_handle h,
|
||||||
cbuf *cbx = NULL;
|
cbuf *cbx = NULL;
|
||||||
cxobj *x;
|
cxobj *x;
|
||||||
|
|
||||||
clicon_debug(1, "%s api_path:%s json:%s",
|
clicon_debug(1, "%s api_path:\"%s\" json:\"%s\"",
|
||||||
__FUNCTION__,
|
__FUNCTION__,
|
||||||
api_path, data);
|
api_path, data);
|
||||||
for (i=0; i<pi; i++)
|
for (i=0; i<pi; i++)
|
||||||
api_path = index(api_path+1, '/');
|
api_path = index(api_path+1, '/');
|
||||||
/* Parse input data as json into xml */
|
/* Parse input data as json into xml */
|
||||||
if (json_parse_str(data, &xdata) < 0){
|
if (json_parse_str(data, &xdata) < 0){
|
||||||
clicon_debug(1, "%s json fail", __FUNCTION__);
|
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((cbx = cbuf_new()) == NULL)
|
if ((cbx = cbuf_new()) == NULL)
|
||||||
|
|
|
||||||
|
|
@ -128,15 +128,3 @@ CLICON_XMLDB_DIR localstatedir/APPNAME
|
||||||
# Eg in nginx: fastcgi_pass unix:/www-data/clicon_restconf.sock;
|
# Eg in nginx: fastcgi_pass unix:/www-data/clicon_restconf.sock;
|
||||||
CLICON_RESTCONF_PATH /www-data/fastcgi_restconf.sock
|
CLICON_RESTCONF_PATH /www-data/fastcgi_restconf.sock
|
||||||
|
|
||||||
# Set if you want to use old obsolete cligen expand variable syntax
|
|
||||||
# Migration: Set to 0 and change all user-defined cli completion callbacks
|
|
||||||
# E.g. expand_dbvar("db fmt") ->expandv_dbvar("db","fmt") in all your cli spec files
|
|
||||||
CLICON_CLIGEN_EXPAND_SINGLE_ARG 0
|
|
||||||
|
|
||||||
# Set if you want to use old obsolete cligen callback variable syntax
|
|
||||||
# Migration: Set to 0 and change all user-defined cli callbacks in your cli spec files
|
|
||||||
# E.g cmd, callback("single arg"); -> cmd, callback("two" "args");
|
|
||||||
# And change predefined callbacks, eg cli_commit -> cli_commitv in all cli files
|
|
||||||
CLICON_CLIGEN_CALLBACK_SINGLE_ARG 1
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,48 +4,53 @@ CLICON_PROMPT="%U@%H> ";
|
||||||
CLICON_PLUGIN="routing_cli";
|
CLICON_PLUGIN="routing_cli";
|
||||||
|
|
||||||
# Note, when switching to PT, change datamodel to only @datamodel
|
# Note, when switching to PT, change datamodel to only @datamodel
|
||||||
set @datamodel:ietf-ip, cli_mergev();
|
set @datamodel:ietf-ip, cli_merge();
|
||||||
|
|
||||||
#delete("Delete a configuration item") @datamodel:ietf-ipv4-unicast-routing, cli_del();
|
#delete("Delete a configuration item") @datamodel:ietf-ipv4-unicast-routing, cli_del();
|
||||||
delete("Delete a configuration item") @datamodel:ietf-ip, cli_delv();
|
delete("Delete a configuration item") @datamodel:ietf-ip, cli_del();
|
||||||
|
|
||||||
validate("Validate changes"), cli_validatev();
|
validate("Validate changes"), cli_validate();
|
||||||
commit("Commit the changes"), cli_commitv();
|
commit("Commit the changes"), cli_commit();
|
||||||
quit("Quit Hello"), cli_quitv();
|
quit("Quit Hello"), cli_quit();
|
||||||
delete("Delete a configuration item") all("Delete whole candidate configuration"), delete_allv("candidate");
|
delete("Delete a configuration item") all("Delete whole candidate configuration"), delete_all("candidate");
|
||||||
|
|
||||||
startup("Store running as startup config"), db_copy("running", "startup");
|
startup("Store running as startup config"), db_copy("running", "startup");
|
||||||
no("Negate or remove") debug("Debugging parts of the system"), cli_debug_cliv((int32)0);
|
no("Negate or remove") debug("Debugging parts of the system"), cli_debug_cli((int32)0);
|
||||||
debug("Debugging parts of the system"), cli_debug_cliv((int32)1);{
|
debug("Debugging parts of the system"), cli_debug_cli((int32)1);{
|
||||||
level("Set debug level: 1..n") <level:int32>("Set debug level (0..n)"), cli_debug_backendv();
|
level("Set debug level: 1..n") <level:int32>("Set debug level (0..n)"), cli_debug_backend();
|
||||||
}
|
}
|
||||||
|
copy("Copy and create a new object") {
|
||||||
discard("Discard edits (rollback 0)"), discard_changesv();
|
interface("Copy interface"){
|
||||||
compare("Compare running and candidate"), compare_dbsv((int32)1);
|
<name:string expand_dbvar("candidate","/interfaces/interface/name")>("name of interface to copy from") to("Copy to interface") <toname:string>("Name of interface to copy to"), cli_copy_config("candidate","//interface[%s=%s]","name","name","toname");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
discard("Discard edits (rollback 0)"), discard_changes();
|
||||||
|
compare("Compare running and candidate"), compare_dbs((int32)1);
|
||||||
|
compare("Compare running and candidate"), compare_dbs((int32)1);
|
||||||
|
|
||||||
show("Show a particular state of the system"){
|
show("Show a particular state of the system"){
|
||||||
xpath("Show configuration") <xpath:string>("XPATH expression"), show_confv_xpath("candidate");
|
xpath("Show configuration") <xpath:string>("XPATH expression"), show_conf_xpath("candidate");
|
||||||
compare("Compare candidate and running databases"), compare_dbsv((int32)0);{
|
compare("Compare candidate and running databases"), compare_dbs((int32)0);{
|
||||||
xml("Show comparison in xml"), compare_dbsv((int32)0);
|
xml("Show comparison in xml"), compare_dbs((int32)0);
|
||||||
text("Show comparison in text"), compare_dbsv((int32)1);
|
text("Show comparison in text"), compare_dbs((int32)1);
|
||||||
}
|
}
|
||||||
configuration("Show configuration"), show_confv_as_text("candidate", "/");{
|
configuration("Show configuration"), cli_show_config("candidate", "text", "/");{
|
||||||
xml("Show configuration as XML"), show_confv_as_xml("candidate", "/");
|
xml("Show configuration as XML"), cli_show_config("candidate", "xml", "/");
|
||||||
netconf("Show configuration as netconf edit-config operation"), show_confv_as_netconf("candidate", "/");
|
netconf("Show configuration as netconf edit-config operation"), cli_show_config("candidate", "netconf", "/");
|
||||||
text("Show configuration as text"), show_confv_as_text("candidate","/");
|
text("Show configuration as text"), cli_show_config("candidate","text","/");
|
||||||
cli("Show configuration as cli commands"), show_confv_as_cli("candidate", "/");
|
cli("Show configuration as cli commands"), cli_show_config("candidate", "cli", "/");
|
||||||
json("Show configuration as cli commands"), show_confv_as_json("candidate", "/");
|
json("Show configuration as cli commands"), cli_show_config("candidate", "json", "/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
save("Save candidate configuration to XML file") <filename:string>("Filename (local filename)"), save_config_filev("candidate","filename");
|
save("Save candidate configuration to XML file") <filename:string>("Filename (local filename)"), save_config_file("candidate","filename");
|
||||||
load("Load configuration from XML file") <filename:string>("Filename (local filename)"),load_config_filev("filename", "replace");{
|
load("Load configuration from XML file") <filename:string>("Filename (local filename)"),load_config_file("filename", "replace");{
|
||||||
replace("Replace candidate with file contents"), load_config_filev("filename", "replace");
|
replace("Replace candidate with file contents"), load_config_file("filename", "replace");
|
||||||
merge("Merge file with existent candidate"), load_config_filev("filename", "merge");
|
merge("Merge file with existent candidate"), load_config_file("filename", "merge");
|
||||||
}
|
}
|
||||||
example("This is a comment") <var:int32>("Just a random number"), mycallback("myarg");
|
example("This is a comment") <var:int32>("Just a random number"), mycallback("myarg");
|
||||||
downcall("This is a downcall") <str:rest>, downcall();
|
downcall("This is a downcall") <str:rest>, downcall();
|
||||||
notify("Get notifications from backend"), cli_notifyv("ROUTING", "1", "text");
|
notify("Get notifications from backend"), cli_notify("ROUTING", "1", "text");
|
||||||
no("Negate") notify("Get notifications from backend"), cli_notifyv("ROUTING", "0", "xml");
|
no("Negate") notify("Get notifications from backend"), cli_notify("ROUTING", "0", "xml");
|
||||||
lock,cli_lock("candidate");
|
lock,cli_lock("candidate");
|
||||||
unlock,cli_unlock("candidate");
|
unlock,cli_unlock("candidate");
|
||||||
|
|
@ -220,6 +220,8 @@ clicon_rpc_generate_error(cxobj *xerr)
|
||||||
clicon_err_fn("Clixon", 0, OE_XML, 0, "%s", cbuf_get(cb));
|
clicon_err_fn("Clixon", 0, OE_XML, 0, "%s", cbuf_get(cb));
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1479,6 +1479,8 @@ xml_operation(char *opstr,
|
||||||
*op = OP_DELETE;
|
*op = OP_DELETE;
|
||||||
else if (strcmp("remove", opstr) == 0)
|
else if (strcmp("remove", opstr) == 0)
|
||||||
*op = OP_REMOVE;
|
*op = OP_REMOVE;
|
||||||
|
else if (strcmp("none", opstr) == 0)
|
||||||
|
*op = OP_NONE;
|
||||||
else{
|
else{
|
||||||
clicon_err(OE_XML, 0, "Bad-attribute operation: %s", opstr);
|
clicon_err(OE_XML, 0, "Bad-attribute operation: %s", opstr);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,27 @@ expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><validate><source><candidate/><
|
||||||
new "netconf commit"
|
new "netconf commit"
|
||||||
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf edit config replace"
|
||||||
|
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth2</name><type>eth</type></interface></interfaces></config><default-operation>merge</default-operation> </edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf get replaced config"
|
||||||
|
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><config><interfaces><interface><name>eth1</name><type>eth</type><enabled>true</enabled></interface><interface><name>eth2</name><type>eth</type><enabled>true</enabled></interface></interfaces></config></data></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf edit config create"
|
||||||
|
expecteof "$clixon_netconf -qf $clixon_cf" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth3</name><type>eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf edit config create 2nd"
|
||||||
|
expecteof "$clixon_netconf -qf $clixon_cf" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth3</name><type>eth</type></interface></interfaces></config><default-operation>merge</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><rpc-error>"
|
||||||
|
|
||||||
|
new "netconf edit config delete"
|
||||||
|
expecteof "$clixon_netconf -qf $clixon_cf" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="delete"><name>eth3</name><type>eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf get delete config"
|
||||||
|
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><config><interfaces><interface><name>eth1</name><type>eth</type><enabled>true</enabled></interface><interface><name>eth2</name><type>eth</type><enabled>true</enabled></interface></interfaces></config></data></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf discard-changes"
|
||||||
|
expecteof "$clixon_netconf -qf $clixon_cf" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></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>]]>]]>$"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
# kill old backend (if any)
|
# kill old backend (if any)
|
||||||
new "kill old backend"
|
new "kill old backend"
|
||||||
#sudo clixon_backend -zf $clixon_cf
|
sudo clixon_backend -zf $clixon_cf
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
|
|
@ -40,17 +40,22 @@ $'
|
||||||
new "restconf head"
|
new "restconf head"
|
||||||
expectfn "curl -s -I http://localhost/restconf/data" "Content-Type: application/yang.data\+json"
|
expectfn "curl -s -I http://localhost/restconf/data" "Content-Type: application/yang.data\+json"
|
||||||
|
|
||||||
new "restconf patch config"
|
new "restconf POST config"
|
||||||
expectfn 'curl -sX POST -d {"type":"eth"} http://localhost/restconf/data/interfaces/interface=eth4' ""
|
expectfn 'curl -sX POST -d {"type":"eth"} http://localhost/restconf/data/interfaces/interface=eth4' ""
|
||||||
# XXX POST/PUT/PATCH
|
|
||||||
|
|
||||||
new "restconf delete config"
|
new "restconf DELETE config"
|
||||||
expectfn 'curl -sX DELETE http://localhost/restconf/data/interfaces/interface=eth0' ""
|
expectfn 'curl -sX DELETE http://localhost/restconf/data/interfaces/interface=eth0' ""
|
||||||
|
|
||||||
new "restconf get config"
|
new "restconf get config"
|
||||||
expectfn "curl -sG http://localhost/restconf/data" '{"interfaces": {"interface": \[{"name": "eth1","type": "eth","enabled": "true"},{ "name": "eth4","type": "eth","enabled": "true"}\]}}
|
expectfn "curl -sG http://localhost/restconf/data" '{"interfaces": {"interface": \[{"name": "eth1","type": "eth","enabled": "true"},{ "name": "eth4","type": "eth","enabled": "true"}\]}}
|
||||||
$'
|
$'
|
||||||
|
|
||||||
|
new "restconf PATCH config"
|
||||||
|
expectfn 'curl -sX PATCH -d {"type":"eth"} http://localhost/restconf/data/interfaces/interface=eth4' ""
|
||||||
|
|
||||||
|
new "restconf PUT"
|
||||||
|
expectfn 'curl -sX PUT -d {"type":"eth"} http://localhost/restconf/data/interfaces/interface=eth5' ""
|
||||||
|
|
||||||
new "Kill restconf daemon"
|
new "Kill restconf daemon"
|
||||||
#sudo pkill -u www-data clixon_restconf
|
#sudo pkill -u www-data clixon_restconf
|
||||||
|
|
||||||
|
|
|
||||||
65
test/test4.sh
Executable file
65
test/test4.sh
Executable file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Test2: backend and netconf basic functionality
|
||||||
|
|
||||||
|
# include err() and new() functions
|
||||||
|
. ./lib.sh
|
||||||
|
|
||||||
|
# For memcheck
|
||||||
|
# clixon_netconf="valgrind --leak-check=full --show-leak-kinds=all clixon_netconf"
|
||||||
|
clixon_netconf=clixon_netconf
|
||||||
|
|
||||||
|
cat <<EOF > /tmp/test.yang
|
||||||
|
module ietf-ip{
|
||||||
|
container x {
|
||||||
|
list y {
|
||||||
|
key "a b";
|
||||||
|
leaf a {
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf b {
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf c {
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leaf d {
|
||||||
|
type empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# kill old backend (if any)
|
||||||
|
new "kill old backend"
|
||||||
|
sudo clixon_backend -zf $clixon_cf -y /tmp/test
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
err
|
||||||
|
fi
|
||||||
|
|
||||||
|
new "start backend"
|
||||||
|
# start new backend
|
||||||
|
sudo clixon_backend -If $clixon_cf -y /tmp/test
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
err
|
||||||
|
fi
|
||||||
|
new "netconf edit config"
|
||||||
|
expecteof "$clixon_netconf -qf $clixon_cf -y /tmp/test" "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>2</b><c>5</c></y><d/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf commit"
|
||||||
|
expecteof "$clixon_netconf -qf $clixon_cf -y /tmp/test" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf get config xpath"
|
||||||
|
expecteof "$clixon_netconf -qf $clixon_cf -y /tmp/test" "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/y[a=1][b=2]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><config><x><y><a>1</a><b>2</b><c>5</c></y></x></config></data></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "Kill backend"
|
||||||
|
# Check if still alive
|
||||||
|
pid=`pgrep clixon_backend`
|
||||||
|
if [ -z "$pid" ]; then
|
||||||
|
err "backend already dead"
|
||||||
|
fi
|
||||||
|
# kill backend
|
||||||
|
sudo clixon_backend -zf $clixon_cf
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
err "kill backend"
|
||||||
|
fi
|
||||||
Loading…
Add table
Add a link
Reference in a new issue