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 running. Added .. as valid step in xpath
This commit is contained in:
parent
30a479de68
commit
4461cc9598
20 changed files with 116 additions and 159 deletions
|
|
@ -29,6 +29,10 @@
|
||||||
#
|
#
|
||||||
# ***** END LICENSE BLOCK *****
|
# ***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
|
- 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
|
||||||
|
running.
|
||||||
|
- 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.
|
- List keys with special characters are RFC 3986 encoded.
|
||||||
- Changed example to use multiple cli callbacks
|
- Changed example to use multiple cli callbacks
|
||||||
|
|
|
||||||
|
|
@ -297,16 +297,10 @@ from_client_commit(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *candidate;
|
char *candidate;
|
||||||
char *running;
|
char *running;
|
||||||
uint32_t snapshot;
|
|
||||||
uint32_t startup;
|
|
||||||
char *archive_dir;
|
|
||||||
char *startup_config;
|
|
||||||
|
|
||||||
if (clicon_msg_commit_decode(msg,
|
if (clicon_msg_commit_decode(msg,
|
||||||
&candidate,
|
&candidate,
|
||||||
&running,
|
&running,
|
||||||
&snapshot,
|
|
||||||
&startup,
|
|
||||||
label) < 0)
|
label) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
|
@ -325,30 +319,6 @@ from_client_commit(clicon_handle h,
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
clicon_debug(1, "Commit %s", candidate);
|
clicon_debug(1, "Commit %s", candidate);
|
||||||
if (snapshot){
|
|
||||||
if ((archive_dir = clicon_archive_dir(h)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "snapshot set and clicon_archive_dir not defined");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (config_snapshot(h, running, archive_dir) < 0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startup){
|
|
||||||
if ((archive_dir = clicon_archive_dir(h)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "startup set but clicon_archive_dir not defined");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if ((startup_config = clicon_startup_config(h)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "startup set but startup_config not defined");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (clicon_file_copy("snapshot", "startup") < 0){
|
|
||||||
clicon_err(OE_PROTO, errno, "%s: Error when creating startup",
|
|
||||||
__FUNCTION__);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
if (send_msg_ok(s) < 0)
|
if (send_msg_ok(s) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@
|
||||||
#include "backend_handle.h"
|
#include "backend_handle.h"
|
||||||
|
|
||||||
/* Command line options to be passed to getopt(3) */
|
/* Command line options to be passed to getopt(3) */
|
||||||
#define BACKEND_OPTS "hD:f:d:Fzu:P:1IRCc::rg:ptx:"
|
#define BACKEND_OPTS "hD:f:d:Fzu:P:1IRCc:rg:ptx:"
|
||||||
|
|
||||||
/*! Terminate. Cannot use h after this */
|
/*! Terminate. Cannot use h after this */
|
||||||
static int
|
static int
|
||||||
|
|
@ -121,7 +121,6 @@ usage(char *argv0, clicon_handle h)
|
||||||
char *plgdir = clicon_backend_dir(h);
|
char *plgdir = clicon_backend_dir(h);
|
||||||
char *confsock = clicon_sock(h);
|
char *confsock = clicon_sock(h);
|
||||||
char *confpid = clicon_backend_pidfile(h);
|
char *confpid = clicon_backend_pidfile(h);
|
||||||
char *startup = clicon_startup_config(h);
|
|
||||||
char *group = clicon_sock_group(h);
|
char *group = clicon_sock_group(h);
|
||||||
|
|
||||||
fprintf(stderr, "usage:%s\n"
|
fprintf(stderr, "usage:%s\n"
|
||||||
|
|
@ -138,8 +137,7 @@ usage(char *argv0, clicon_handle h)
|
||||||
" -I\t\tInitialize running state database\n"
|
" -I\t\tInitialize running state database\n"
|
||||||
" -R\t\tCall plugin_reset() in plugins to reset system state in running db (use with -I)\n"
|
" -R\t\tCall plugin_reset() in plugins to reset system state in running db (use with -I)\n"
|
||||||
" -C\t\tCall plugin_reset() in plugins to reset system state in candidate db (use with -I)\n"
|
" -C\t\tCall plugin_reset() in plugins to reset system state in candidate db (use with -I)\n"
|
||||||
" -c [<file>]\tLoad specified application config. Default is\n"
|
" -c <file>\tLoad specified application config.\n"
|
||||||
" \t\"CLICON_STARTUP_CONFIG\" = %s\n"
|
|
||||||
" -r\t\tReload running database\n"
|
" -r\t\tReload running database\n"
|
||||||
" -p \t\tPrint database yang specification\n"
|
" -p \t\tPrint database yang specification\n"
|
||||||
" -t \t\tPrint alternate spec translation (eg if YANG print KEY, if KEY print YANG)\n"
|
" -t \t\tPrint alternate spec translation (eg if YANG print KEY, if KEY print YANG)\n"
|
||||||
|
|
@ -149,7 +147,6 @@ usage(char *argv0, clicon_handle h)
|
||||||
plgdir ? plgdir : "none",
|
plgdir ? plgdir : "none",
|
||||||
confsock ? confsock : "none",
|
confsock ? confsock : "none",
|
||||||
confpid ? confpid : "none",
|
confpid ? confpid : "none",
|
||||||
startup ? startup : "none",
|
|
||||||
group ? group : "none"
|
group ? group : "none"
|
||||||
);
|
);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|
@ -415,11 +412,7 @@ main(int argc, char **argv)
|
||||||
reset_state_candidate++;
|
reset_state_candidate++;
|
||||||
break;
|
break;
|
||||||
case 'c': /* Load application config */
|
case 'c': /* Load application config */
|
||||||
app_config_file = optarg ? optarg : clicon_startup_config(h);
|
app_config_file = optarg;
|
||||||
if (app_config_file == NULL) {
|
|
||||||
fprintf(stderr, "Option \"CLICON_STARTUP_CONFIG\" not set\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'r': /* Reload running */
|
case 'r': /* Reload running */
|
||||||
reload_running++;
|
reload_running++;
|
||||||
|
|
@ -510,6 +503,19 @@ 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;
|
||||||
|
|
||||||
|
/* First check for starup config
|
||||||
|
XXX the options below have become out-of-hand.
|
||||||
|
Too complex, need to simplify*/
|
||||||
|
if (clicon_option_int(h, "CLICON_USE_STARTUP_CONFIG") > 0){
|
||||||
|
if (xmldb_exists(h, "startup") == 1){
|
||||||
|
/* copy startup config -> running */
|
||||||
|
if (xmldb_copy(h, "startup", "running") < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (rundb_init(h) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
/* If running exists and reload_running set, make a copy to candidate */
|
/* If running exists and reload_running set, make a copy to candidate */
|
||||||
if (reload_running){
|
if (reload_running){
|
||||||
if (xmldb_exists(h, "running") != 1){
|
if (xmldb_exists(h, "running") != 1){
|
||||||
|
|
@ -549,14 +555,13 @@ main(int argc, char **argv)
|
||||||
*(argv-1) = tmp;
|
*(argv-1) = tmp;
|
||||||
|
|
||||||
if (reload_running){
|
if (reload_running){
|
||||||
if (candidate_commit(h, "candidate") < 0)
|
/* This could be afailed validation, and we should not fail for that */
|
||||||
goto done;
|
(void)candidate_commit(h, "candidate");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Have we specified a config file to load? eg
|
/* Have we specified a config file to load? eg
|
||||||
-c <file>
|
* -c [<file>]
|
||||||
-r replace running (obsolete)
|
*/
|
||||||
*/
|
|
||||||
if (app_config_file)
|
if (app_config_file)
|
||||||
if (rundb_main(h, app_config_file) < 0)
|
if (rundb_main(h, app_config_file) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,7 @@ cli_dbxmlv(clicon_handle h,
|
||||||
if (clicon_rpc_change(h, "candidate", op, xk, str) < 0)
|
if (clicon_rpc_change(h, "candidate", op, xk, str) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_autocommit(h)) {
|
if (clicon_autocommit(h)) {
|
||||||
if (clicon_rpc_commit(h, "candidate", "running", 0, 0) < 0)
|
if (clicon_rpc_commit(h, "candidate", "running") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -456,7 +456,7 @@ cli_quitv(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Generic commit callback
|
/*! Generic commit callback
|
||||||
* @param[in] arg If 1, then snapshot and copy to startup config
|
* @param[in] argv No arguments expected
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cli_commitv(clicon_handle h,
|
cli_commitv(clicon_handle h,
|
||||||
|
|
@ -464,21 +464,10 @@ cli_commitv(clicon_handle h,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int snapshot;
|
|
||||||
|
|
||||||
if (cvec_len(argv) > 1){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "%s: Requires 0 or 1 element. If given: snapshot flag 0|1", __FUNCTION__);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (cvec_len(argv))
|
|
||||||
snapshot = cv_int32_get(cvec_i(argv, 0));
|
|
||||||
else
|
|
||||||
snapshot = 0;
|
|
||||||
if ((retval = clicon_rpc_commit(h,
|
if ((retval = clicon_rpc_commit(h,
|
||||||
"candidate",
|
"candidate",
|
||||||
"running",
|
"running")) < 0){ /* startup */
|
||||||
snapshot, /* snapshot */
|
|
||||||
snapshot)) < 0){ /* startup */
|
|
||||||
cli_output(stderr, "Commit failed. Edit and try again or discard changes");
|
cli_output(stderr, "Commit failed. Edit and try again or discard changes");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -702,8 +691,8 @@ load_config_filev(clicon_handle h,
|
||||||
* Utility function used by cligen spec file
|
* Utility function used by cligen spec file
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] cvv variable vector (containing <varname>)
|
* @param[in] cvv variable vector (containing <varname>)
|
||||||
* @param[in] arg a string: "<dbname> <varname>"
|
* @param[in] argv a string: "<dbname> <varname>"
|
||||||
* <dbname> is running or candidate
|
* <dbname> is running, candidate, or startup
|
||||||
* <varname> is name of cligen variable in the "cvv" vector containing file name
|
* <varname> is name of cligen variable in the "cvv" vector containing file name
|
||||||
* Note that "filename" is local on client filesystem not backend.
|
* Note that "filename" is local on client filesystem not backend.
|
||||||
* The function can run without a local database
|
* The function can run without a local database
|
||||||
|
|
@ -735,23 +724,11 @@ save_config_filev(clicon_handle h,
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
|
|
||||||
clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (nvec != 2){
|
|
||||||
clicon_err(OE_PLUGIN, 0, "Arg syntax is <dbname> <varname>");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
dbstr = cv_string_get(cvec_i(argv, 0));
|
dbstr = cv_string_get(cvec_i(argv, 0));
|
||||||
varstr = cv_string_get(cvec_i(argv, 1));
|
varstr = cv_string_get(cvec_i(argv, 1));
|
||||||
if (strcmp(dbstr, "running") != 0 && strcmp(dbstr, "candidate") != 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);
|
clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -799,7 +776,9 @@ delete_allv(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
dbstr = cv_string_get(cvec_i(argv, 0));
|
dbstr = cv_string_get(cvec_i(argv, 0));
|
||||||
if (strcmp(dbstr, "running") != 0 && strcmp(dbstr, "candidate") != 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);
|
clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -822,6 +801,22 @@ discard_changesv(clicon_handle h,
|
||||||
return clicon_rpc_copy(h, "running", "candidate");
|
return clicon_rpc_copy(h, "running", "candidate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Copy from one database to another, eg running->startup
|
||||||
|
* @param[in] argv a string: "<db1> <db2>" Copy from db1 to db2
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
db_copy(clicon_handle h,
|
||||||
|
cvec *cvv,
|
||||||
|
cvec *argv)
|
||||||
|
{
|
||||||
|
char *db1;
|
||||||
|
char *db2;
|
||||||
|
|
||||||
|
db1 = cv_string_get(cvec_i(argv, 0));
|
||||||
|
db2 = cv_string_get(cvec_i(argv, 1));
|
||||||
|
return clicon_rpc_copy(h, db1, db2);
|
||||||
|
}
|
||||||
|
|
||||||
/* These are strings that can be used as 3rd argument to cli_setlog */
|
/* These are strings that can be used as 3rd argument to cli_setlog */
|
||||||
static const char *SHOWAS_TXT = "txt";
|
static const char *SHOWAS_TXT = "txt";
|
||||||
static const char *SHOWAS_XML = "xml";
|
static const char *SHOWAS_XML = "xml";
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,8 @@ expandv_dbvar(void *h,
|
||||||
}
|
}
|
||||||
dbstr = cv_string_get(cv);
|
dbstr = cv_string_get(cv);
|
||||||
if (strcmp(dbstr, "running") != 0 &&
|
if (strcmp(dbstr, "running") != 0 &&
|
||||||
strcmp(dbstr, "candidate") != 0){
|
strcmp(dbstr, "candidate") != 0 &&
|
||||||
|
strcmp(dbstr, "startup") != 0){
|
||||||
clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);
|
clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -407,7 +408,7 @@ xml2csv(FILE *f, cxobj *x, cvec *cvv)
|
||||||
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
||||||
* @param[out] xt Configuration as xml tree.
|
* @param[out] xt Configuration as xml tree.
|
||||||
* Format of arg:
|
* Format of arg:
|
||||||
* <dbname> "running", "candidate"
|
* <dbname> "running", "candidate", "startup"
|
||||||
* <xpath> xpath expression
|
* <xpath> xpath expression
|
||||||
* <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
|
||||||
|
|
@ -440,7 +441,9 @@ show_confv_as(clicon_handle h,
|
||||||
}
|
}
|
||||||
/* Dont get attr here, take it from arg instead */
|
/* Dont get attr here, take it from arg instead */
|
||||||
db = cv_string_get(cvec_i(argv, 0));
|
db = cv_string_get(cvec_i(argv, 0));
|
||||||
if (strcmp(db, "running") != 0 && strcmp(db, "candidate") != 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);
|
clicon_err(OE_PLUGIN, 0, "No such db name: %s", db);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -703,8 +706,8 @@ show_confv_as_csv(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
show_confv_xpath(clicon_handle h,
|
show_confv_xpath(clicon_handle h,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *argv)
|
cvec *argv)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *str;
|
char *str;
|
||||||
|
|
@ -721,7 +724,9 @@ show_confv_xpath(clicon_handle h,
|
||||||
}
|
}
|
||||||
str = cv_string_get(cvec_i(argv, 0));
|
str = cv_string_get(cvec_i(argv, 0));
|
||||||
/* Dont get attr here, take it from arg instead */
|
/* Dont get attr here, take it from arg instead */
|
||||||
if (strcmp(str, "running") != 0 && strcmp(str, "candidate") != 0){
|
if (strcmp(str, "running") != 0 &&
|
||||||
|
strcmp(str, "candidate") != 0 &&
|
||||||
|
strcmp(str, "startup") != 0){
|
||||||
clicon_err(OE_PLUGIN, 0, "No such db name: %s", str);
|
clicon_err(OE_PLUGIN, 0, "No such db name: %s", str);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -790,7 +795,8 @@ expand_dbvar(void *h,
|
||||||
}
|
}
|
||||||
dbstr = vec[0];
|
dbstr = vec[0];
|
||||||
if (strcmp(dbstr, "running") != 0 &&
|
if (strcmp(dbstr, "running") != 0 &&
|
||||||
strcmp(dbstr, "candidate") != 0){
|
strcmp(dbstr, "candidate") != 0 &&
|
||||||
|
strcmp(dbstr, "startup") != 0){
|
||||||
clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);
|
clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -869,7 +875,7 @@ expand_dbvar(void *h,
|
||||||
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
* @param[in] arg A string: <dbname> <xpath> [<varname>]
|
||||||
* @param[out] xt Configuration as xml tree.
|
* @param[out] xt Configuration as xml tree.
|
||||||
* Format of arg:
|
* Format of arg:
|
||||||
* <dbname> "running", "candidate"
|
* <dbname> "running", "candidate", "startup"
|
||||||
* <xpath> xpath expression
|
* <xpath> xpath expression
|
||||||
* <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
|
||||||
|
|
@ -909,7 +915,9 @@ show_conf_as(clicon_handle h,
|
||||||
}
|
}
|
||||||
/* Dont get attr here, take it from arg instead */
|
/* Dont get attr here, take it from arg instead */
|
||||||
db = vec[0];
|
db = vec[0];
|
||||||
if (strcmp(db, "running") != 0 && strcmp(db, "candidate") != 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);
|
clicon_err(OE_PLUGIN, 0, "No such db name: %s", db);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -1178,7 +1186,9 @@ show_conf_xpath(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Dont get attr here, take it from arg instead */
|
/* Dont get attr here, take it from arg instead */
|
||||||
if (strcmp(str, "running") != 0 && strcmp(str, "candidate") != 0){
|
if (strcmp(str, "running") != 0 &&
|
||||||
|
strcmp(str, "candidate") != 0 &&
|
||||||
|
strcmp(str, "startup") != 0){
|
||||||
clicon_err(OE_PLUGIN, 0, "No such db name: %s", str);
|
clicon_err(OE_PLUGIN, 0, "No such db name: %s", str);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ usage(char *argv0)
|
||||||
"\t-h\t\tHelp\n"
|
"\t-h\t\tHelp\n"
|
||||||
"\t-D\t\tDebug\n"
|
"\t-D\t\tDebug\n"
|
||||||
"\t-S\t\tLog on syslog\n"
|
"\t-S\t\tLog on syslog\n"
|
||||||
"\t-d <db>\tDatabase name (default: running)\n"
|
"\t-d <db>\t\tDatabase name (default: running)\n"
|
||||||
"\t-p\t\tDump database on stdout\n"
|
"\t-p\t\tDump database on stdout\n"
|
||||||
"\t-b\t\tBrief output, just print keys. Combine with -p or -m\n"
|
"\t-b\t\tBrief output, just print keys. Combine with -p or -m\n"
|
||||||
"\t-n \"<key> <val>\" Add database entry\n"
|
"\t-n \"<key> <val>\" Add database entry\n"
|
||||||
|
|
|
||||||
|
|
@ -120,9 +120,7 @@ netconf_create_hello(cbuf *xf, /* msg buffer */
|
||||||
cprintf(xf, "<capability>urn:ietf:params:xml:ns:netconf:capability:validate:1.0</capability>\n");
|
cprintf(xf, "<capability>urn:ietf:params:xml:ns:netconf:capability:validate:1.0</capability>\n");
|
||||||
cprintf(xf, "<capability>urn:ietf:params:netconf:capability:xpath:1.0</capability>\n");
|
cprintf(xf, "<capability>urn:ietf:params:netconf:capability:xpath:1.0</capability>\n");
|
||||||
cprintf(xf, "<capability>urn:ietf:params:netconf:capability:notification:1.0</capability>\n");
|
cprintf(xf, "<capability>urn:ietf:params:netconf:capability:notification:1.0</capability>\n");
|
||||||
|
cprintf(xf, "<capability>urn:ietf:params:netconf:capability:startup:1.0</capability>\n");
|
||||||
|
|
||||||
// cprintf(xf, "<capability>urn:rnr:rnrapi:1:0</capability>");
|
|
||||||
cprintf(xf, "</capabilities>");
|
cprintf(xf, "</capabilities>");
|
||||||
cprintf(xf, "<session-id>%lu</session-id>", 42+session_id);
|
cprintf(xf, "<session-id>%lu</session-id>", 42+session_id);
|
||||||
cprintf(xf, "</hello>");
|
cprintf(xf, "</hello>");
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,9 @@ netconf_get_target(clicon_handle h,
|
||||||
else
|
else
|
||||||
if (xpath_first(x, "running") != NULL)
|
if (xpath_first(x, "running") != NULL)
|
||||||
target = "running";
|
target = "running";
|
||||||
|
else
|
||||||
|
if (xpath_first(x, "startup") != NULL)
|
||||||
|
target = "startup";
|
||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -247,11 +247,11 @@ netconf_get_config(clicon_handle h,
|
||||||
cbuf *cb_err,
|
cbuf *cb_err,
|
||||||
cxobj *xorig)
|
cxobj *xorig)
|
||||||
{
|
{
|
||||||
cxobj *xfilter; /* filter */
|
cxobj *xfilter; /* filter */
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *source;
|
char *source;
|
||||||
enum filter_option foption = FILTER_SUBTREE;
|
enum filter_option foption = FILTER_SUBTREE;
|
||||||
char *ftype = NULL;
|
char *ftype = NULL;
|
||||||
|
|
||||||
if ((source = netconf_get_target(h, xn, "source")) == NULL){
|
if ((source = netconf_get_target(h, xn, "source")) == NULL){
|
||||||
netconf_create_rpc_error(cb_err, xorig,
|
netconf_create_rpc_error(cb_err, xorig,
|
||||||
|
|
@ -568,7 +568,7 @@ netconf_delete_config(clicon_handle h,
|
||||||
"<bad-element>target</bad-element>");
|
"<bad-element>target</bad-element>");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (strcmp(target, "candidate")){
|
if (strcmp(target, "running") == 0){
|
||||||
netconf_create_rpc_error(cb_err, xorig,
|
netconf_create_rpc_error(cb_err, xorig,
|
||||||
"bad-element",
|
"bad-element",
|
||||||
"protocol",
|
"protocol",
|
||||||
|
|
@ -577,7 +577,7 @@ netconf_delete_config(clicon_handle h,
|
||||||
"<bad-element>target</bad-element>");
|
"<bad-element>target</bad-element>");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (clicon_rpc_change(h, "candidate",
|
if (clicon_rpc_change(h, target,
|
||||||
OP_REMOVE,
|
OP_REMOVE,
|
||||||
"/", "") < 0){
|
"/", "") < 0){
|
||||||
netconf_create_rpc_error(cb_err, xorig,
|
netconf_create_rpc_error(cb_err, xorig,
|
||||||
|
|
@ -745,8 +745,7 @@ netconf_commit(clicon_handle h,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
||||||
if (clicon_rpc_commit(h, "candidate", "running",
|
if (clicon_rpc_commit(h, "candidate", "running") < 0){
|
||||||
0, 0) < 0){
|
|
||||||
netconf_create_rpc_error(cb_err, xorig,
|
netconf_create_rpc_error(cb_err, xorig,
|
||||||
"operation-failed",
|
"operation-failed",
|
||||||
"protocol", "error",
|
"protocol", "error",
|
||||||
|
|
|
||||||
|
|
@ -273,8 +273,7 @@ api_data_delete(clicon_handle h,
|
||||||
api_path,
|
api_path,
|
||||||
"") < 0)
|
"") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_commit(h, "candidate", "running",
|
if (clicon_rpc_commit(h, "candidate", "running") < 0)
|
||||||
0, 0) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
FCGX_SetExitStatus(201, r->out);
|
FCGX_SetExitStatus(201, r->out);
|
||||||
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
||||||
|
|
@ -348,8 +347,7 @@ api_data_put(clicon_handle h,
|
||||||
api_path,
|
api_path,
|
||||||
cbuf_get(cbx)) < 0)
|
cbuf_get(cbx)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_commit(h, "candidate", "running",
|
if (clicon_rpc_commit(h, "candidate", "running") < 0)
|
||||||
0, 0) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
FCGX_SetExitStatus(201, r->out); /* Created */
|
FCGX_SetExitStatus(201, r->out); /* Created */
|
||||||
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
||||||
|
|
|
||||||
|
|
@ -77,8 +77,8 @@ CLICON_CLISPEC_DIR libdir/APPNAME/clispec
|
||||||
# are saved chronologically
|
# are saved chronologically
|
||||||
CLICON_ARCHIVE_DIR localstatedir/APPNAME/archive
|
CLICON_ARCHIVE_DIR localstatedir/APPNAME/archive
|
||||||
|
|
||||||
# XXX Name of startup configuration file (in XML)
|
# Enabled uses "startup" configuration on boot
|
||||||
CLICON_STARTUP_CONFIG localstatedir/APPNAME/startup-config
|
CLICON_USE_STARTUP_CONFIG 0
|
||||||
|
|
||||||
# Address family for communicating with clixon_backend (UNIX|IPv4|IPv6)
|
# Address family for communicating with clixon_backend (UNIX|IPv4|IPv6)
|
||||||
CLICON_SOCK_FAMILY UNIX
|
CLICON_SOCK_FAMILY UNIX
|
||||||
|
|
@ -118,7 +118,7 @@ CLICON_BACKEND_PIDFILE localstatedir/APPNAME/APPNAME.pidfile
|
||||||
# How to generate and show CLI syntax: VARS|ALL
|
# How to generate and show CLI syntax: VARS|ALL
|
||||||
# CLICON_CLI_GENMODEL_TYPE VARS
|
# CLICON_CLI_GENMODEL_TYPE VARS
|
||||||
|
|
||||||
# Directory where "running" and "candidate" are placed
|
# Directory where "running", "candidate" and "startup" are placed
|
||||||
CLICON_XMLDB_DIR localstatedir/APPNAME
|
CLICON_XMLDB_DIR localstatedir/APPNAME
|
||||||
|
|
||||||
# Set if xmldb runs in a separate process (clixon_xmldb).
|
# Set if xmldb runs in a separate process (clixon_xmldb).
|
||||||
|
|
@ -149,3 +149,4 @@ CLICON_CLIGEN_EXPAND_SINGLE_ARG 0
|
||||||
# And change predefined callbacks, eg cli_commit -> cli_commitv in all cli files
|
# And change predefined callbacks, eg cli_commit -> cli_commitv in all cli files
|
||||||
CLICON_CLIGEN_CALLBACK_SINGLE_ARG 1
|
CLICON_CLIGEN_CALLBACK_SINGLE_ARG 1
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,11 @@ set @datamodel:ietf-ip, cli_mergev();
|
||||||
delete("Delete a configuration item") @datamodel:ietf-ip, cli_delv();
|
delete("Delete a configuration item") @datamodel:ietf-ip, cli_delv();
|
||||||
|
|
||||||
validate("Validate changes"), cli_validatev();
|
validate("Validate changes"), cli_validatev();
|
||||||
commit("Commit the changes"), cli_commitv((int32)0); # snapshot
|
commit("Commit the changes"), cli_commitv();
|
||||||
quit("Quit Hello"), cli_quitv();
|
quit("Quit Hello"), cli_quitv();
|
||||||
delete("Delete a configuration item") all("Delete whole candidate configuration"), delete_allv("candidate");
|
delete("Delete a configuration item") all("Delete whole candidate configuration"), delete_allv("candidate");
|
||||||
|
|
||||||
|
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_cliv((int32)0);
|
||||||
debug("Debugging parts of the system"), cli_debug_cliv((int32)1);{
|
debug("Debugging parts of the system"), cli_debug_cliv((int32)1);{
|
||||||
level("Set debug level: 1..n") <level:int32>("Set debug level (0..n)"), cli_debug_cliv();
|
level("Set debug level: 1..n") <level:int32>("Set debug level (0..n)"), cli_debug_cliv();
|
||||||
|
|
@ -22,7 +23,7 @@ debug("Debugging parts of the system"), cli_debug_cliv((int32)1);{
|
||||||
discard("Discard edits (rollback 0)"), discard_changesv();
|
discard("Discard edits (rollback 0)"), discard_changesv();
|
||||||
|
|
||||||
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_confv_xpath("candidate","/");
|
||||||
compare("Compare candidate and running databases"), compare_dbsv((int32)0);{
|
compare("Compare candidate and running databases"), compare_dbsv((int32)0);{
|
||||||
xml("Show comparison in xml"), compare_dbsv((int32)0);
|
xml("Show comparison in xml"), compare_dbsv((int32)0);
|
||||||
text("Show comparison in text"), compare_dbsv((int32)1);
|
text("Show comparison in text"), compare_dbsv((int32)1);
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,6 @@ char *clicon_clispec_dir(clicon_handle h);
|
||||||
char *clicon_netconf_dir(clicon_handle h);
|
char *clicon_netconf_dir(clicon_handle h);
|
||||||
char *clicon_restconf_dir(clicon_handle h);
|
char *clicon_restconf_dir(clicon_handle h);
|
||||||
char *clicon_archive_dir(clicon_handle h);
|
char *clicon_archive_dir(clicon_handle h);
|
||||||
char *clicon_startup_config(clicon_handle h);
|
|
||||||
int clicon_sock_family(clicon_handle h);
|
int clicon_sock_family(clicon_handle h);
|
||||||
char *clicon_sock(clicon_handle h);
|
char *clicon_sock(clicon_handle h);
|
||||||
int clicon_sock_port(clicon_handle h);
|
int clicon_sock_port(clicon_handle h);
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,7 @@
|
||||||
#ifndef _CLIXON_PROTO_CLIENT_H_
|
#ifndef _CLIXON_PROTO_CLIENT_H_
|
||||||
#define _CLIXON_PROTO_CLIENT_H_
|
#define _CLIXON_PROTO_CLIENT_H_
|
||||||
|
|
||||||
int clicon_rpc_commit(clicon_handle h, char *from, char *to,
|
int clicon_rpc_commit(clicon_handle h, char *from, char *to);
|
||||||
int snapshot, int startup);
|
|
||||||
int clicon_rpc_validate(clicon_handle h, char *db);
|
int clicon_rpc_validate(clicon_handle h, char *db);
|
||||||
int clicon_rpc_change(clicon_handle h, char *db,
|
int clicon_rpc_change(clicon_handle h, char *db,
|
||||||
enum operation_type op, char *key, char *val);
|
enum operation_type op, char *key, char *val);
|
||||||
|
|
|
||||||
|
|
@ -44,13 +44,11 @@
|
||||||
*/
|
*/
|
||||||
struct clicon_msg *
|
struct clicon_msg *
|
||||||
clicon_msg_commit_encode(char *dbsrc, char *dbdst,
|
clicon_msg_commit_encode(char *dbsrc, char *dbdst,
|
||||||
uint32_t snapshot, uint32_t startup,
|
|
||||||
const char *label);
|
const char *label);
|
||||||
|
|
||||||
int
|
int
|
||||||
clicon_msg_commit_decode(struct clicon_msg *msg,
|
clicon_msg_commit_decode(struct clicon_msg *msg,
|
||||||
char **dbsrc, char **dbdst,
|
char **dbsrc, char **dbdst,
|
||||||
uint32_t *snapshot, uint32_t *startup,
|
|
||||||
const char *label);
|
const char *label);
|
||||||
|
|
||||||
struct clicon_msg *
|
struct clicon_msg *
|
||||||
|
|
|
||||||
|
|
@ -241,10 +241,6 @@ clicon_option_sanity(clicon_hash_t *copt)
|
||||||
clicon_err(OE_UNIX, 0, "CLICON_ARCHIVE_DIR not defined in config file");
|
clicon_err(OE_UNIX, 0, "CLICON_ARCHIVE_DIR not defined in config file");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (!hash_lookup(copt, "CLICON_STARTUP_CONFIG")){
|
|
||||||
clicon_err(OE_UNIX, 0, "CLICON_STARTUP_CONFIG not defined in config file");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (!hash_lookup(copt, "CLICON_SOCK")){
|
if (!hash_lookup(copt, "CLICON_SOCK")){
|
||||||
clicon_err(OE_UNIX, 0, "CLICON_SOCK not defined in config file");
|
clicon_err(OE_UNIX, 0, "CLICON_SOCK not defined in config file");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -461,12 +457,6 @@ clicon_archive_dir(clicon_handle h)
|
||||||
return clicon_option_str(h, "CLICON_ARCHIVE_DIR");
|
return clicon_option_str(h, "CLICON_ARCHIVE_DIR");
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
clicon_startup_config(clicon_handle h)
|
|
||||||
{
|
|
||||||
return clicon_option_str(h, "CLICON_STARTUP_CONFIG");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get family of backend socket: AF_UNIX, AF_INET or AF_INET6 */
|
/* get family of backend socket: AF_UNIX, AF_INET or AF_INET6 */
|
||||||
int
|
int
|
||||||
clicon_sock_family(clicon_handle h)
|
clicon_sock_family(clicon_handle h)
|
||||||
|
|
|
||||||
|
|
@ -128,22 +128,17 @@ clicon_rpc_msg(clicon_handle h,
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] from name of 'from' database (eg "candidate")
|
* @param[in] from name of 'from' database (eg "candidate")
|
||||||
* @param[in] db name of 'to' database (eg "running")
|
* @param[in] db name of 'to' database (eg "running")
|
||||||
* @param[in] snapshot Make a snapshot copy of db state
|
|
||||||
* @param[in] startup Make a copy to startup.
|
|
||||||
* @retval 0 Copy current->candidate
|
* @retval 0 Copy current->candidate
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_rpc_commit(clicon_handle h,
|
clicon_rpc_commit(clicon_handle h,
|
||||||
char *from,
|
char *from,
|
||||||
char *to,
|
char *to)
|
||||||
int snapshot,
|
|
||||||
int startup)
|
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
struct clicon_msg *msg;
|
struct clicon_msg *msg;
|
||||||
|
|
||||||
if ((msg=clicon_msg_commit_encode(from, to, snapshot, startup,
|
if ((msg=clicon_msg_commit_encode(from, to, __FUNCTION__)) == NULL)
|
||||||
__FUNCTION__)) == NULL)
|
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, NULL, NULL, NULL, __FUNCTION__) < 0)
|
if (clicon_rpc_msg(h, msg, NULL, NULL, NULL, __FUNCTION__) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -73,18 +73,16 @@
|
||||||
|
|
||||||
struct clicon_msg *
|
struct clicon_msg *
|
||||||
clicon_msg_commit_encode(char *dbsrc, char *dbdst,
|
clicon_msg_commit_encode(char *dbsrc, char *dbdst,
|
||||||
uint32_t snapshot, uint32_t startup,
|
|
||||||
const char *label)
|
const char *label)
|
||||||
{
|
{
|
||||||
struct clicon_msg *msg;
|
struct clicon_msg *msg;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
int hdrlen = sizeof(*msg);
|
int hdrlen = sizeof(*msg);
|
||||||
int p;
|
int p;
|
||||||
uint32_t tmp;
|
|
||||||
|
|
||||||
clicon_debug(2, "%s: snapshot: %d startup: %d dbsrc: %s dbdst: %s",
|
clicon_debug(2, "%s: dbsrc: %s dbdst: %s",
|
||||||
__FUNCTION__,
|
__FUNCTION__,
|
||||||
snapshot, startup, dbsrc, dbdst);
|
dbsrc, dbdst);
|
||||||
p = 0;
|
p = 0;
|
||||||
len = sizeof(*msg) + 2*sizeof(uint32_t) + strlen(dbsrc) + 1 +
|
len = sizeof(*msg) + 2*sizeof(uint32_t) + strlen(dbsrc) + 1 +
|
||||||
strlen(dbdst) + 1;
|
strlen(dbdst) + 1;
|
||||||
|
|
@ -97,12 +95,6 @@ clicon_msg_commit_encode(char *dbsrc, char *dbdst,
|
||||||
msg->op_type = htons(CLICON_MSG_COMMIT);
|
msg->op_type = htons(CLICON_MSG_COMMIT);
|
||||||
msg->op_len = htons(len);
|
msg->op_len = htons(len);
|
||||||
/* body */
|
/* body */
|
||||||
tmp = htonl(snapshot);
|
|
||||||
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
|
|
||||||
p += sizeof(uint32_t);
|
|
||||||
tmp = htonl(startup);
|
|
||||||
memcpy(msg->op_body+p, &tmp, sizeof(uint32_t));
|
|
||||||
p += sizeof(uint32_t);
|
|
||||||
strncpy(msg->op_body+p, dbsrc, len-p-hdrlen);
|
strncpy(msg->op_body+p, dbsrc, len-p-hdrlen);
|
||||||
p += strlen(dbsrc)+1;
|
p += strlen(dbsrc)+1;
|
||||||
strncpy(msg->op_body+p, dbdst, len-p-hdrlen);
|
strncpy(msg->op_body+p, dbdst, len-p-hdrlen);
|
||||||
|
|
@ -113,20 +105,12 @@ clicon_msg_commit_encode(char *dbsrc, char *dbdst,
|
||||||
int
|
int
|
||||||
clicon_msg_commit_decode(struct clicon_msg *msg,
|
clicon_msg_commit_decode(struct clicon_msg *msg,
|
||||||
char **dbsrc, char **dbdst,
|
char **dbsrc, char **dbdst,
|
||||||
uint32_t *snapshot, uint32_t *startup,
|
|
||||||
const char *label)
|
const char *label)
|
||||||
{
|
{
|
||||||
int p;
|
int p;
|
||||||
uint32_t tmp;
|
|
||||||
|
|
||||||
p = 0;
|
p = 0;
|
||||||
/* body */
|
/* body */
|
||||||
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
|
|
||||||
*snapshot = ntohl(tmp);
|
|
||||||
p += sizeof(uint32_t);
|
|
||||||
memcpy(&tmp, msg->op_body+p, sizeof(uint32_t));
|
|
||||||
*startup = ntohl(tmp);
|
|
||||||
p += sizeof(uint32_t);
|
|
||||||
if ((*dbsrc = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
|
if ((*dbsrc = chunk_sprintf(label, "%s", msg->op_body+p)) == NULL){
|
||||||
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
|
clicon_err(OE_PROTO, errno, "%s: chunk_sprintf",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
|
|
@ -139,9 +123,7 @@ clicon_msg_commit_decode(struct clicon_msg *msg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p += strlen(*dbdst)+1;
|
p += strlen(*dbdst)+1;
|
||||||
clicon_debug(2, "%s: snapshot: %d startup: %d dbsrc: %s dbdst: %s",
|
clicon_debug(2, "%s: dbsrc: %s dbdst: %s", __FUNCTION__, *dbsrc, *dbdst);
|
||||||
__FUNCTION__,
|
|
||||||
*snapshot, *startup, *dbsrc, *dbdst);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -414,6 +414,7 @@ xmlkeyfmt2xpath(char *xkfmt,
|
||||||
*/
|
*/
|
||||||
static int _running_locked = 0;
|
static int _running_locked = 0;
|
||||||
static int _candidate_locked = 0;
|
static int _candidate_locked = 0;
|
||||||
|
static int _startup_locked = 0;
|
||||||
|
|
||||||
/*! Lock database
|
/*! Lock database
|
||||||
*/
|
*/
|
||||||
|
|
@ -425,6 +426,8 @@ db_lock(char *db,
|
||||||
_running_locked = pid;
|
_running_locked = pid;
|
||||||
else if (strcmp("candidate", db) == 0)
|
else if (strcmp("candidate", db) == 0)
|
||||||
_candidate_locked = pid;
|
_candidate_locked = pid;
|
||||||
|
else if (strcmp("startup", db) == 0)
|
||||||
|
_startup_locked = pid;
|
||||||
clicon_debug(1, "%s: locked by %u", db, pid);
|
clicon_debug(1, "%s: locked by %u", db, pid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -438,6 +441,8 @@ db_unlock(char *db)
|
||||||
_running_locked = 0;
|
_running_locked = 0;
|
||||||
else if (strcmp("candidate", db) == 0)
|
else if (strcmp("candidate", db) == 0)
|
||||||
_candidate_locked = 0;
|
_candidate_locked = 0;
|
||||||
|
else if (strcmp("startup", db) == 0)
|
||||||
|
_startup_locked = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -452,6 +457,8 @@ db_islocked(char *db)
|
||||||
return (_running_locked);
|
return (_running_locked);
|
||||||
else if (strcmp("candidate", db) == 0)
|
else if (strcmp("candidate", db) == 0)
|
||||||
return(_candidate_locked);
|
return(_candidate_locked);
|
||||||
|
else if (strcmp("startup", db) == 0)
|
||||||
|
return(_startup_locked);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -485,6 +492,7 @@ db2file(clicon_handle h,
|
||||||
}
|
}
|
||||||
if (strcmp(db, "running") != 0 &&
|
if (strcmp(db, "running") != 0 &&
|
||||||
strcmp(db, "candidate") != 0 &&
|
strcmp(db, "candidate") != 0 &&
|
||||||
|
strcmp(db, "startup") != 0 &&
|
||||||
strcmp(db, "tmp") != 0){
|
strcmp(db, "tmp") != 0){
|
||||||
clicon_err(OE_XML, 0, "Unexpected database: %s", db);
|
clicon_err(OE_XML, 0, "Unexpected database: %s", db);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1016,8 +1024,10 @@ xmldb_get_local(clicon_handle h,
|
||||||
if (xvec != NULL)
|
if (xvec != NULL)
|
||||||
for (i=0; i<xlen; i++)
|
for (i=0; i<xlen; i++)
|
||||||
xml_flag_set(xvec[i], XML_FLAG_MARK);
|
xml_flag_set(xvec[i], XML_FLAG_MARK);
|
||||||
if (xml_tree_prune_unmarked(xt, NULL) < 0)
|
/* Top is special case */
|
||||||
goto done;
|
if (!xml_flag(xt, XML_FLAG_MARK))
|
||||||
|
if (xml_tree_prune_unmarked(xt, NULL) < 0)
|
||||||
|
goto done;
|
||||||
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xvec0 && xlen0){
|
if (xvec0 && xlen0){
|
||||||
|
|
@ -1741,7 +1751,7 @@ xmldb_put_xkey_local(clicon_handle h,
|
||||||
/*! Modify database provided an XML database key and an operation
|
/*! Modify database provided an XML database key and an operation
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] db Database name
|
* @param[in] db Database name
|
||||||
* @param[in] xk XML Key, eg /aa/bb/17/name
|
* @param[in] xk XML Key, eg /aa/bb=17/name
|
||||||
* @param[in] val Key value, eg "17"
|
* @param[in] val Key value, eg "17"
|
||||||
* @param[in] op OP_MERGE, OP_REPLACE, OP_REMOVE, etc
|
* @param[in] op OP_MERGE, OP_REPLACE, OP_REMOVE, etc
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
|
|
|
||||||
|
|
@ -326,7 +326,7 @@ xpath_parse(char *xpath,
|
||||||
s = s0;
|
s = s0;
|
||||||
if (strlen(s))
|
if (strlen(s))
|
||||||
nvec = 1;
|
nvec = 1;
|
||||||
/* Chop up LocatoinPath in Steps delimited by '/' (unless [] predicate)
|
/* Chop up LocationPath in Steps delimited by '/' (unless [] predicate)
|
||||||
* Eg, "/a/b[/c]/d" -> "a" "b[/c]" "d"
|
* Eg, "/a/b[/c]/d" -> "a" "b[/c]" "d"
|
||||||
*/
|
*/
|
||||||
esc = 0;
|
esc = 0;
|
||||||
|
|
@ -358,12 +358,12 @@ xpath_parse(char *xpath,
|
||||||
else if (strncmp(s,"descendant-or-self::", strlen("descendant-or-self::"))==0){
|
else if (strncmp(s,"descendant-or-self::", strlen("descendant-or-self::"))==0){
|
||||||
xpath_element_new(A_DESCENDANT_OR_SELF, s+strlen("descendant-or-self::"), &xpnext);
|
xpath_element_new(A_DESCENDANT_OR_SELF, s+strlen("descendant-or-self::"), &xpnext);
|
||||||
}
|
}
|
||||||
else if (strncmp(s,".", strlen("."))==0)
|
else if (strncmp(s,".", strlen(s))==0) /* abbreviatedstep */
|
||||||
xpath_element_new(A_SELF, s+strlen("."), &xpnext);
|
xpath_element_new(A_SELF, NULL, &xpnext);
|
||||||
else if (strncmp(s,"self::", strlen("self::"))==0)
|
else if (strncmp(s,"self::", strlen("self::"))==0)
|
||||||
xpath_element_new(A_SELF, s+strlen("self::"), &xpnext);
|
xpath_element_new(A_SELF, s+strlen("self::"), &xpnext);
|
||||||
else if (strncmp(s,"..", strlen(".."))==0)
|
else if (strncmp(s,"..", strlen(s))==0) /* abbreviatedstep */
|
||||||
xpath_element_new(A_PARENT, s+strlen(".."), &xpnext);
|
xpath_element_new(A_PARENT, NULL, &xpnext);
|
||||||
else if (strncmp(s,"parent::", strlen("parent::"))==0)
|
else if (strncmp(s,"parent::", strlen("parent::"))==0)
|
||||||
xpath_element_new(A_PARENT, s+strlen("parent::"), &xpnext);
|
xpath_element_new(A_PARENT, s+strlen("parent::"), &xpnext);
|
||||||
else if (strncmp(s,"ancestor::", strlen("ancestor::"))==0)
|
else if (strncmp(s,"ancestor::", strlen("ancestor::"))==0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue