Confirm commit:
- Removed confirm-commit 1.0 capability (only 1.1 present) - Made startup capability conditional (as confirmed-commit) - Fixed startup error when rollback did not exist - Adjust snmp commit calls - Move failsafe to lib - Test: Minimized test application, test capability
This commit is contained in:
parent
8abcda6f85
commit
11eccd5478
16 changed files with 177 additions and 349 deletions
|
|
@ -87,10 +87,6 @@ INCLUDES = -I. -I$(top_srcdir)/lib/src -I$(top_srcdir)/lib -I$(top_srcdir)/inclu
|
||||||
# Name of application
|
# Name of application
|
||||||
APPL = clixon_backend
|
APPL = clixon_backend
|
||||||
|
|
||||||
# Source / objects called from plugin and otherwise
|
|
||||||
COMMONSRC = backend_failsafe.c
|
|
||||||
COMMONOBJ = $(COMMONSRC:.c=.o)
|
|
||||||
|
|
||||||
# Not accessible from plugin
|
# Not accessible from plugin
|
||||||
APPSRC = backend_main.c
|
APPSRC = backend_main.c
|
||||||
APPSRC += backend_socket.c
|
APPSRC += backend_socket.c
|
||||||
|
|
@ -98,14 +94,14 @@ APPSRC += backend_client.c
|
||||||
APPSRC += backend_get.c
|
APPSRC += backend_get.c
|
||||||
APPSRC += backend_plugin_restconf.c # Pseudo plugin for restconf daemon
|
APPSRC += backend_plugin_restconf.c # Pseudo plugin for restconf daemon
|
||||||
APPSRC += backend_startup.c
|
APPSRC += backend_startup.c
|
||||||
APPOBJ = $(APPSRC:.c=.o) $(COMMONOBJ)
|
APPOBJ = $(APPSRC:.c=.o)
|
||||||
|
|
||||||
# Accessible from plugin
|
# Accessible from plugin
|
||||||
LIBSRC = clixon_backend_transaction.c
|
LIBSRC = clixon_backend_transaction.c
|
||||||
LIBSRC += clixon_backend_handle.c
|
LIBSRC += clixon_backend_handle.c
|
||||||
LIBSRC += backend_commit.c
|
LIBSRC += backend_commit.c
|
||||||
LIBSRC += backend_plugin.c
|
LIBSRC += backend_plugin.c
|
||||||
LIBOBJ = $(LIBSRC:.c=.o) $(COMMONOBJ)
|
LIBOBJ = $(LIBSRC:.c=.o)
|
||||||
|
|
||||||
# Name of lib
|
# Name of lib
|
||||||
MYNAME = clixon_backend
|
MYNAME = clixon_backend
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,6 @@
|
||||||
#include "backend_handle.h"
|
#include "backend_handle.h"
|
||||||
#include "clixon_backend_commit.h"
|
#include "clixon_backend_commit.h"
|
||||||
#include "backend_client.h"
|
#include "backend_client.h"
|
||||||
#include "backend_failsafe.h"
|
|
||||||
|
|
||||||
/* a global instance of the confirmed_commit struct for reference throughout the procedure */
|
/* a global instance of the confirmed_commit struct for reference throughout the procedure */
|
||||||
struct confirmed_commit confirmed_commit = {
|
struct confirmed_commit confirmed_commit = {
|
||||||
|
|
@ -1577,3 +1576,58 @@ from_client_restart_one(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Reset running and start in failsafe mode. If no failsafe then quit.
|
||||||
|
*
|
||||||
|
* param[in] h Clixon handle
|
||||||
|
* param[in] phase Debug string
|
||||||
|
Typically done when startup status is not OK so
|
||||||
|
|
||||||
|
failsafe ----------------------+
|
||||||
|
reset \ commit
|
||||||
|
running ----|-------+---------------> RUNNING FAILSAFE
|
||||||
|
\
|
||||||
|
tmp |---------------------->
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
load_failsafe(clicon_handle h,
|
||||||
|
char *phase)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
int ret;
|
||||||
|
char *db = "failsafe";
|
||||||
|
cbuf *cbret = NULL;
|
||||||
|
|
||||||
|
phase = phase == NULL ? "(unknown)" : phase;
|
||||||
|
|
||||||
|
if ((cbret = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ((ret = xmldb_exists(h, db)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 0){ /* No it does not exist, fail */
|
||||||
|
clicon_err(OE_DB, 0, "%s failed and no Failsafe database found, exiting", phase);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* Copy original running to tmp as backup (restore if error) */
|
||||||
|
if (xmldb_copy(h, "running", "tmp") < 0)
|
||||||
|
goto done;
|
||||||
|
if (xmldb_db_reset(h, "running") < 0)
|
||||||
|
goto done;
|
||||||
|
ret = candidate_commit(h, db, cbret);
|
||||||
|
if (ret != 1)
|
||||||
|
if (xmldb_copy(h, "tmp", "running") < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 0){
|
||||||
|
clicon_err(OE_DB, 0, "%s failed, Failsafe database validation failed %s", phase, cbuf_get(cbret));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
clicon_log(LOG_NOTICE, "%s failed, Failsafe database loaded ", phase);
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (cbret)
|
||||||
|
cbuf_free(cbret);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
***** BEGIN LICENSE BLOCK *****
|
|
||||||
|
|
||||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
|
||||||
Copyright (C) 2017-2019 Olof Hagsand
|
|
||||||
Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
|
||||||
|
|
||||||
This file is part of CLIXON.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
Alternatively, the contents of this file may be used under the terms of
|
|
||||||
the GNU General Public License Version 3 or later (the "GPL"),
|
|
||||||
in which case the provisions of the GPL are applicable instead
|
|
||||||
of those above. If you wish to allow use of your version of this file only
|
|
||||||
under the terms of the GPL, and not to allow others to
|
|
||||||
use your version of this file under the terms of Apache License version 2,
|
|
||||||
indicate your decision by deleting the provisions above and replace them with
|
|
||||||
the notice and other provisions required by the GPL. If you do not delete
|
|
||||||
the provisions above, a recipient may use your version of this file under
|
|
||||||
the terms of any one of the Apache License version 2 or the GPL.
|
|
||||||
|
|
||||||
***** END LICENSE BLOCK *****
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "clixon_config.h" /* generated by config & autoconf */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
/* cligen */
|
|
||||||
#include <cligen/cligen.h>
|
|
||||||
|
|
||||||
/* clixon */
|
|
||||||
#include <clixon/clixon.h>
|
|
||||||
|
|
||||||
#include "clixon_backend_commit.h"
|
|
||||||
#include "backend_failsafe.h"
|
|
||||||
|
|
||||||
/*! Reset running and start in failsafe mode. If no failsafe then quit.
|
|
||||||
Typically done when startup status is not OK so
|
|
||||||
|
|
||||||
failsafe ----------------------+
|
|
||||||
reset \ commit
|
|
||||||
running ----|-------+---------------> RUNNING FAILSAFE
|
|
||||||
\
|
|
||||||
tmp |---------------------->
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
load_failsafe(clicon_handle h, char *phase)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
int ret;
|
|
||||||
char *db = "failsafe";
|
|
||||||
cbuf *cbret = NULL;
|
|
||||||
|
|
||||||
phase = phase == NULL ? "(unknown)" : phase;
|
|
||||||
|
|
||||||
if ((cbret = cbuf_new()) == NULL){
|
|
||||||
clicon_err(OE_XML, errno, "cbuf_new");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((ret = xmldb_exists(h, db)) < 0)
|
|
||||||
goto done;
|
|
||||||
if (ret == 0){ /* No it does not exist, fail */
|
|
||||||
clicon_err(OE_DB, 0, "%s failed and no Failsafe database found, exiting", phase);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* Copy original running to tmp as backup (restore if error) */
|
|
||||||
if (xmldb_copy(h, "running", "tmp") < 0)
|
|
||||||
goto done;
|
|
||||||
if (xmldb_db_reset(h, "running") < 0)
|
|
||||||
goto done;
|
|
||||||
ret = candidate_commit(h, db, cbret);
|
|
||||||
if (ret != 1)
|
|
||||||
if (xmldb_copy(h, "tmp", "running") < 0)
|
|
||||||
goto done;
|
|
||||||
if (ret < 0)
|
|
||||||
goto done;
|
|
||||||
if (ret == 0){
|
|
||||||
clicon_err(OE_DB, 0, "%s failed, Failsafe database validation failed %s", phase, cbuf_get(cbret));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
clicon_log(LOG_NOTICE, "%s failed, Failsafe database loaded ", phase);
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (cbret)
|
|
||||||
cbuf_free(cbret);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
***** BEGIN LICENSE BLOCK *****
|
|
||||||
|
|
||||||
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
|
|
||||||
Copyright (C) 2017-2019 Olof Hagsand
|
|
||||||
Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
|
||||||
|
|
||||||
This file is part of CLIXON.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
Alternatively, the contents of this file may be used under the terms of
|
|
||||||
the GNU General Public License Version 3 or later (the "GPL"),
|
|
||||||
in which case the provisions of the GPL are applicable instead
|
|
||||||
of those above. If you wish to allow use of your version of this file only
|
|
||||||
under the terms of the GPL, and not to allow others to
|
|
||||||
use your version of this file under the terms of Apache License version 2,
|
|
||||||
indicate your decision by deleting the provisions above and replace them with
|
|
||||||
the notice and other provisions required by the GPL. If you do not delete
|
|
||||||
the provisions above, a recipient may use your version of this file under
|
|
||||||
the terms of any one of the Apache License version 2 or the GPL.
|
|
||||||
|
|
||||||
***** END LICENSE BLOCK *****
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CLIXON_BACKEND_FAILSAFE_H
|
|
||||||
#define CLIXON_BACKEND_FAILSAFE_H
|
|
||||||
int load_failsafe(clicon_handle h, char *phase);
|
|
||||||
|
|
||||||
#endif //CLIXON_BACKEND_FAILSAFE_H
|
|
||||||
|
|
@ -962,7 +962,7 @@ main(int argc,
|
||||||
if (status != STARTUP_OK){
|
if (status != STARTUP_OK){
|
||||||
if (cbuf_len(cbret))
|
if (cbuf_len(cbret))
|
||||||
clicon_log(LOG_NOTICE, "%s: %u %s", __PROGRAM__, getpid(), cbuf_get(cbret));
|
clicon_log(LOG_NOTICE, "%s: %u %s", __PROGRAM__, getpid(), cbuf_get(cbret));
|
||||||
if (startup_failsafe(h) < 0){
|
if (load_failsafe(h, "Startup") < 0){
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
status = STARTUP_OK;
|
status = STARTUP_OK;
|
||||||
|
|
|
||||||
|
|
@ -132,9 +132,10 @@ startup_mode_startup(clicon_handle h,
|
||||||
char *db,
|
char *db,
|
||||||
cbuf *cbret)
|
cbuf *cbret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int db_exists;
|
int rollback_exists;
|
||||||
|
yang_stmt *yspec = clicon_dbspec_yang(h);
|
||||||
|
|
||||||
if (strcmp(db, "running")==0){
|
if (strcmp(db, "running")==0){
|
||||||
clicon_err(OE_FATAL, 0, "Invalid startup db: %s", db);
|
clicon_err(OE_FATAL, 0, "Invalid startup db: %s", db);
|
||||||
|
|
@ -153,13 +154,12 @@ startup_mode_startup(clicon_handle h,
|
||||||
* database was deleted, either clixon_backend crashed or the machine
|
* database was deleted, either clixon_backend crashed or the machine
|
||||||
* rebooted.
|
* rebooted.
|
||||||
*/
|
*/
|
||||||
yang_stmt *yspec = clicon_dbspec_yang(h);
|
|
||||||
if (if_feature(yspec, "ietf-netconf", "confirmed-commit")) {
|
if (if_feature(yspec, "ietf-netconf", "confirmed-commit")) {
|
||||||
db_exists = xmldb_exists(h, "rollback");
|
if ((rollback_exists = xmldb_exists(h, "rollback")) < 0) {
|
||||||
if (db_exists < 0) {
|
|
||||||
clicon_err(OE_DAEMON, 0, "Error checking for the existence of the rollback database");
|
clicon_err(OE_DAEMON, 0, "Error checking for the existence of the rollback database");
|
||||||
goto done;
|
goto done;
|
||||||
} else if (db_exists == 1) {
|
}
|
||||||
|
if (rollback_exists == 1) {
|
||||||
ret = startup_commit(h, "rollback", cbret);
|
ret = startup_commit(h, "rollback", cbret);
|
||||||
switch(ret) {
|
switch(ret) {
|
||||||
case -1:
|
case -1:
|
||||||
|
|
@ -170,23 +170,30 @@ startup_mode_startup(clicon_handle h,
|
||||||
|
|
||||||
/* Rename the errored rollback database so that it is not tried on a subsequent startup */
|
/* Rename the errored rollback database so that it is not tried on a subsequent startup */
|
||||||
xmldb_rename(h, db, NULL, ".error");
|
xmldb_rename(h, db, NULL, ".error");
|
||||||
|
goto ok;
|
||||||
retval = 1;
|
|
||||||
goto done;
|
|
||||||
case 1:
|
case 1:
|
||||||
/* validation ok */
|
/* validation ok */
|
||||||
retval = 1;
|
|
||||||
xmldb_delete(h, "rollback");
|
xmldb_delete(h, "rollback");
|
||||||
goto done;
|
goto ok;
|
||||||
default:
|
default:
|
||||||
/* Unexpected response */
|
/* Unexpected response */
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ((ret = startup_commit(h, db, cbret)) < 0)
|
else {
|
||||||
goto done;
|
if ((ret = startup_commit(h, db, cbret)) < 0)
|
||||||
if (ret == 0)
|
goto done;
|
||||||
goto fail;
|
if (ret == 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ((ret = startup_commit(h, db, cbret)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
ok:
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -332,56 +339,6 @@ startup_extraxml(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Reset running and start in failsafe mode. If no failsafe then quit.
|
|
||||||
Typically done when startup status is not OK so
|
|
||||||
|
|
||||||
failsafe ----------------------+
|
|
||||||
reset \ commit
|
|
||||||
running ----|-------+---------------> RUNNING FAILSAFE
|
|
||||||
\
|
|
||||||
tmp |---------------------->
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
startup_failsafe(clicon_handle h)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
int ret;
|
|
||||||
char *db = "failsafe";
|
|
||||||
cbuf *cbret = NULL;
|
|
||||||
|
|
||||||
if ((cbret = cbuf_new()) == NULL){
|
|
||||||
clicon_err(OE_XML, errno, "cbuf_new");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((ret = xmldb_exists(h, db)) < 0)
|
|
||||||
goto done;
|
|
||||||
if (ret == 0){ /* No it does not exist, fail */
|
|
||||||
clicon_err(OE_DB, 0, "Startup failed and no Failsafe database found, exiting");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* Copy original running to tmp as backup (restore if error) */
|
|
||||||
if (xmldb_copy(h, "running", "tmp") < 0)
|
|
||||||
goto done;
|
|
||||||
if (xmldb_db_reset(h, "running") < 0)
|
|
||||||
goto done;
|
|
||||||
ret = candidate_commit(h, db, cbret);
|
|
||||||
if (ret != 1)
|
|
||||||
if (xmldb_copy(h, "tmp", "running") < 0)
|
|
||||||
goto done;
|
|
||||||
if (ret < 0)
|
|
||||||
goto done;
|
|
||||||
if (ret == 0){
|
|
||||||
clicon_err(OE_DB, 0, "Startup failed, Failsafe database validation failed %s", cbuf_get(cbret));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
clicon_log(LOG_NOTICE, "Startup failed, Failsafe database loaded ");
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (cbret)
|
|
||||||
cbuf_free(cbret);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Init modules state of the backend (server). To compare with startup XML
|
/*! Init modules state of the backend (server). To compare with startup XML
|
||||||
* Set the modules state as setopt to the datastore module.
|
* Set the modules state as setopt to the datastore module.
|
||||||
* Only if CLICON_XMLDB_MODSTATE is enabled
|
* Only if CLICON_XMLDB_MODSTATE is enabled
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@
|
||||||
*/
|
*/
|
||||||
int startup_mode_startup(clicon_handle h, char *db, cbuf *cbret);
|
int startup_mode_startup(clicon_handle h, char *db, cbuf *cbret);
|
||||||
int startup_extraxml(clicon_handle h, char *file, cbuf *cbret);
|
int startup_extraxml(clicon_handle h, char *file, cbuf *cbret);
|
||||||
int startup_failsafe(clicon_handle h);
|
|
||||||
int startup_module_state(clicon_handle h, yang_stmt *yspec);
|
int startup_module_state(clicon_handle h, yang_stmt *yspec);
|
||||||
|
|
||||||
#endif /* _BACKEND_STARTUP_H_ */
|
#endif /* _BACKEND_STARTUP_H_ */
|
||||||
|
|
|
||||||
|
|
@ -83,5 +83,6 @@ int from_client_discard_changes(clicon_handle h, cxobj *xe, cbuf *cbret, void *a
|
||||||
int from_client_cancel_commit(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
|
int from_client_cancel_commit(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
|
||||||
int from_client_validate(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
|
int from_client_validate(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
|
||||||
int from_client_restart_one(clicon_handle h, clixon_plugin_t *cp, cbuf *cbret);
|
int from_client_restart_one(clicon_handle h, clixon_plugin_t *cp, cbuf *cbret);
|
||||||
|
int load_failsafe(clicon_handle h, char *phase);
|
||||||
|
|
||||||
#endif /* _CLIXON_BACKEND_COMMIT_H_ */
|
#endif /* _CLIXON_BACKEND_COMMIT_H_ */
|
||||||
|
|
|
||||||
|
|
@ -750,7 +750,7 @@ clixon_snmp_scalar_handler1(netsnmp_mib_handler *handler,
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
case MODE_SET_COMMIT: /* 3 */
|
case MODE_SET_COMMIT: /* 3 */
|
||||||
if (clicon_rpc_commit(sh->sh_h) < 0)
|
if (clicon_rpc_commit(sh->sh_h, 0, 0, 0, NULL, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
case MODE_SET_FREE: /* 4 */
|
case MODE_SET_FREE: /* 4 */
|
||||||
|
|
@ -1303,7 +1303,7 @@ clixon_snmp_table_handler1(netsnmp_mib_handler *handler,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MODE_SET_COMMIT: // 3
|
case MODE_SET_COMMIT: // 3
|
||||||
if (clicon_rpc_commit(sh->sh_h) < 0)
|
if (clicon_rpc_commit(sh->sh_h, 0, 0, 0, NULL, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
case MODE_SET_FREE: // 4
|
case MODE_SET_FREE: // 4
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* t
|
|
||||||
*
|
*
|
||||||
***** BEGIN LICENSE BLOCK *****
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1752,7 +1752,8 @@ netconf_content_int2str(netconf_content nr)
|
||||||
* backend, and backend may implement more modules - please consider if using
|
* backend, and backend may implement more modules - please consider if using
|
||||||
* library routines for detecting capabilities here. In contrast, yang module
|
* library routines for detecting capabilities here. In contrast, yang module
|
||||||
* list (RFC7895) is processed by the backend.
|
* list (RFC7895) is processed by the backend.
|
||||||
* @note encode bodies, see xml_chardata_encode()
|
* @note If you add new, remember to encode bodies if needed, see xml_chardata_encode()
|
||||||
|
* @note
|
||||||
* @see yang_modules_state_get
|
* @see yang_modules_state_get
|
||||||
* @see netconf_module_load
|
* @see netconf_module_load
|
||||||
*/
|
*/
|
||||||
|
|
@ -1779,6 +1780,7 @@ netconf_hello_server(clicon_handle h,
|
||||||
/* A peer MAY include capabilities for previous NETCONF versions, to indicate
|
/* A peer MAY include capabilities for previous NETCONF versions, to indicate
|
||||||
that it supports multiple protocol versions. */
|
that it supports multiple protocol versions. */
|
||||||
cprintf(cb, "<capability>%s</capability>", NETCONF_BASE_CAPABILITY_1_0);
|
cprintf(cb, "<capability>%s</capability>", NETCONF_BASE_CAPABILITY_1_0);
|
||||||
|
|
||||||
/* Check if RFC7895 loaded and revision found */
|
/* Check if RFC7895 loaded and revision found */
|
||||||
if ((ietf_yang_library_revision = yang_modules_revision(h)) != NULL){
|
if ((ietf_yang_library_revision = yang_modules_revision(h)) != NULL){
|
||||||
if (xml_chardata_encode(&encstr, "urn:ietf:params:netconf:capability:yang-library:1.0?revision=%s&module-set-id=%s",
|
if (xml_chardata_encode(&encstr, "urn:ietf:params:netconf:capability:yang-library:1.0?revision=%s&module-set-id=%s",
|
||||||
|
|
@ -1791,21 +1793,25 @@ netconf_hello_server(clicon_handle h,
|
||||||
encstr = NULL;
|
encstr = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* RFC6241 Sec 8.3. Candidate Configuration Capability */
|
||||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>");
|
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>");
|
||||||
|
/* RFC6241 Sec 8.6. Validate Capability */
|
||||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:validate:1.1</capability>");
|
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:validate:1.1</capability>");
|
||||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:startup:1.0</capability>");
|
/* rfc 6241 Sec 8.7 Distinct Startup Capability */
|
||||||
|
if (if_feature(yspec, "ietf-netconf", "startup"))
|
||||||
|
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:startup:1.0</capability>");
|
||||||
|
/* RFC6241 Sec 8.9. XPath Capability */
|
||||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:xpath:1.0</capability>");
|
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:xpath:1.0</capability>");
|
||||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:notification:1.0</capability>");
|
|
||||||
/* rfc6243 with-defaults capability modes */
|
/* rfc6243 with-defaults capability modes */
|
||||||
cprintf(cb, "<capability>");
|
cprintf(cb, "<capability>");
|
||||||
xml_chardata_cbuf_append(cb, "urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&also-supported=report-all,trim,report-all-tagged");
|
xml_chardata_cbuf_append(cb, "urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&also-supported=report-all,trim,report-all-tagged");
|
||||||
cprintf(cb, "</capability>");
|
cprintf(cb, "</capability>");
|
||||||
|
/* RFC5277 Notification Capability */
|
||||||
/* rfc 4741 and 6241 confirmed-commit capabilities */
|
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:notification:1.0</capability>");
|
||||||
if (if_feature(yspec, "ietf-netconf", "confirmed-commit")) {
|
/* It is somewhat arbitrary why some features/capabilities are hardocded and why some are not
|
||||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:confirmed-commit:1.0</capability>");
|
* rfc 6241 Sec 8.4 confirmed-commit capabilities */
|
||||||
|
if (if_feature(yspec, "ietf-netconf", "confirmed-commit"))
|
||||||
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:confirmed-commit:1.1</capability>");
|
cprintf(cb, "<capability>urn:ietf:params:netconf:capability:confirmed-commit:1.1</capability>");
|
||||||
}
|
|
||||||
|
|
||||||
cprintf(cb, "</capabilities>");
|
cprintf(cb, "</capabilities>");
|
||||||
if (session_id)
|
if (session_id)
|
||||||
|
|
|
||||||
|
|
@ -1266,8 +1266,14 @@ clicon_rpc_validate(clicon_handle h,
|
||||||
|
|
||||||
/*! Commit changes send a commit request to backend daemon
|
/*! Commit changes send a commit request to backend daemon
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @retval 0 OK
|
* @param[in] confirmed If set, send commit/confirmed
|
||||||
* @retval -1 Error and logged to syslog
|
* @param[in] cancel If set, send cancle-commit
|
||||||
|
* @param[in] timeout For confirmed, a timeout in seconds (default 600s)
|
||||||
|
* @param[in] persist A persist identifier to use
|
||||||
|
* @param[in] persist_id If cancel or confirmed, the persist id
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error and logged to syslog
|
||||||
|
* @see rfc6241 Sec 8.4 Confirmed Commit Capability
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_rpc_commit(clicon_handle h,
|
clicon_rpc_commit(clicon_handle h,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
# The SKIPLIST has precedence over the 'pattern' variable that you can use to
|
# The SKIPLIST has precedence over the 'pattern' variable that you can use to
|
||||||
# specify included file when running the various test scripts such as "all.sh".
|
# specify included file when running the various test scripts such as "all.sh".
|
||||||
#SKIPLIST="test_[a-t]*\.sh test_openconfig.sh test_yangmodels.sh"
|
#SKIPLIST="test_[a-t]*\.sh test_openconfig.sh test_yangmodels.sh"
|
||||||
SKIPLIST="test_http_data.sh test_netconf_ssh_callhome.sh test_privileges.sh test_restconf.sh test_yang_models_ieee.sh"
|
|
||||||
#
|
#
|
||||||
# Parse yang openconfig models from https://github.com/openconfig/public
|
# Parse yang openconfig models from https://github.com/openconfig/public
|
||||||
OPENCONFIG=/usr/local/share/openconfig/public
|
OPENCONFIG=/usr/local/share/openconfig/public
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Basic Netconf functionality
|
# Netconf confirm commit capability
|
||||||
# Mainly default/null prefix, but also xx: prefix
|
# See RFC 6241 Section 8.4
|
||||||
# XXX: could add tests for dual prefixes xx and xy with doppelganger names, ie xy:filter that is
|
# Test uses privileges drop
|
||||||
# syntactic correct but wrong
|
# TODO:
|
||||||
|
# - privileges drop
|
||||||
|
# - restconf
|
||||||
|
# - lock check
|
||||||
|
|
||||||
# Magic line must be first in script (see README.md)
|
# Magic line must be first in script (see README.md)
|
||||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
@ -13,13 +16,17 @@ cfg=$dir/conf_yang.xml
|
||||||
tmp=$dir/tmp.x
|
tmp=$dir/tmp.x
|
||||||
fyang=$dir/clixon-example.yang
|
fyang=$dir/clixon-example.yang
|
||||||
|
|
||||||
# Use yang in example
|
# Backend user for priv drop, otherwise root
|
||||||
|
USER=root #${BUSER}
|
||||||
|
|
||||||
|
# Define default restconfig config: RESTCONFIG
|
||||||
|
RESTCONFIG=$(restconf_config none false)
|
||||||
|
|
||||||
cat <<EOF > $cfg
|
cat <<EOF > $cfg
|
||||||
<clixon-config xmlns="http://clicon.org/config">
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
<CLICON_FEATURE>ietf-netconf:startup</CLICON_FEATURE>
|
|
||||||
<CLICON_FEATURE>ietf-netconf:confirmed-commit</CLICON_FEATURE>
|
<CLICON_FEATURE>ietf-netconf:confirmed-commit</CLICON_FEATURE>
|
||||||
|
<CLICON_FEATURE>clixon-restconf:allow-auth-none</CLICON_FEATURE> <!-- Use auth-type=none -->
|
||||||
<CLICON_MODULE_SET_ID>42</CLICON_MODULE_SET_ID>
|
<CLICON_MODULE_SET_ID>42</CLICON_MODULE_SET_ID>
|
||||||
<CLICON_YANG_DIR>${YANG_INSTALLDIR}</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>${YANG_INSTALLDIR}</CLICON_YANG_DIR>
|
||||||
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
||||||
|
|
@ -37,6 +44,7 @@ cat <<EOF > $cfg
|
||||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||||
<CLICON_BACKEND_USER>$USER</CLICON_BACKEND_USER>
|
<CLICON_BACKEND_USER>$USER</CLICON_BACKEND_USER>
|
||||||
<CLICON_BACKEND_PRIVILEGES>drop_perm</CLICON_BACKEND_PRIVILEGES>
|
<CLICON_BACKEND_PRIVILEGES>drop_perm</CLICON_BACKEND_PRIVILEGES>
|
||||||
|
$RESTCONFIG
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
@ -45,16 +53,7 @@ module clixon-example{
|
||||||
yang-version 1.1;
|
yang-version 1.1;
|
||||||
namespace "urn:example:clixon";
|
namespace "urn:example:clixon";
|
||||||
prefix ex;
|
prefix ex;
|
||||||
import ietf-interfaces {
|
|
||||||
prefix if;
|
|
||||||
}
|
|
||||||
import ietf-ip {
|
|
||||||
prefix ip;
|
|
||||||
}
|
|
||||||
/* Example interface type for tests, local callbacks, etc */
|
|
||||||
identity eth {
|
|
||||||
base if:interface-type;
|
|
||||||
}
|
|
||||||
/* Generic config data */
|
/* Generic config data */
|
||||||
container table{
|
container table{
|
||||||
list parameter{
|
list parameter{
|
||||||
|
|
@ -64,74 +63,6 @@ module clixon-example{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* State data (not config) for the example application*/
|
|
||||||
container state {
|
|
||||||
config false;
|
|
||||||
description "state data for the example application (must be here for example get operation)";
|
|
||||||
leaf-list op {
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
augment "/if:interfaces/if:interface" {
|
|
||||||
container my-status {
|
|
||||||
config false;
|
|
||||||
description "For testing augment+state";
|
|
||||||
leaf int {
|
|
||||||
type int32;
|
|
||||||
}
|
|
||||||
leaf str {
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rpc client-rpc {
|
|
||||||
description "Example local client-side RPC that is processed by the
|
|
||||||
the netconf/restconf and not sent to the backend.
|
|
||||||
This is a clixon implementation detail: some rpc:s
|
|
||||||
are better processed by the client for API or perf reasons";
|
|
||||||
input {
|
|
||||||
leaf x {
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output {
|
|
||||||
leaf x {
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rpc empty {
|
|
||||||
description "Smallest possible RPC with no input or output sections";
|
|
||||||
}
|
|
||||||
rpc example {
|
|
||||||
description "Some example input/output for testing RFC7950 7.14.
|
|
||||||
RPC simply echoes the input for debugging.";
|
|
||||||
input {
|
|
||||||
leaf x {
|
|
||||||
description
|
|
||||||
"If a leaf in the input tree has a 'mandatory' statement with
|
|
||||||
the value 'true', the leaf MUST be present in an RPC invocation.";
|
|
||||||
type string;
|
|
||||||
mandatory true;
|
|
||||||
}
|
|
||||||
leaf y {
|
|
||||||
description
|
|
||||||
"If a leaf in the input tree has a 'mandatory' statement with the
|
|
||||||
value 'true', the leaf MUST be present in an RPC invocation.";
|
|
||||||
type string;
|
|
||||||
default "42";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output {
|
|
||||||
leaf x {
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
leaf y {
|
|
||||||
type string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
@ -176,6 +107,7 @@ function edit_config() {
|
||||||
function assert_config_equals() {
|
function assert_config_equals() {
|
||||||
TARGET="$1"
|
TARGET="$1"
|
||||||
EXPECTED="$2"
|
EXPECTED="$2"
|
||||||
|
# new "get-config: $TARGET"
|
||||||
rpc "<get-config><source><$TARGET/></source></get-config>" "$(data "$EXPECTED")"
|
rpc "<get-config><source><$TARGET/></source></get-config>" "$(data "$EXPECTED")"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,15 +123,12 @@ RUNNING_PATH="/usr/local/var/$APPNAME/running_db"
|
||||||
ROLLBACK_PATH="/usr/local/var/$APPNAME/rollback_db"
|
ROLLBACK_PATH="/usr/local/var/$APPNAME/rollback_db"
|
||||||
FAILSAFE_PATH="/usr/local/var/$APPNAME/failsafe_db"
|
FAILSAFE_PATH="/usr/local/var/$APPNAME/failsafe_db"
|
||||||
|
|
||||||
CONFIGB="<interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\"><interface><name>eth0</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces>"
|
CONFIGB="<table xmlns=\"urn:example:clixon\"><parameter><name>eth0</name></parameter></table>"
|
||||||
CONFIGC="<interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\"><interface><name>eth1</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces>"
|
CONFIGC="<table xmlns=\"urn:example:clixon\"><parameter><name>eth1</name></parameter></table>"
|
||||||
CONFIGBPLUSC="<interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\"><interface><name>eth0</name><type>ex:eth</type><enabled>true</enabled></interface><interface><name>eth1</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces>"
|
CONFIGBPLUSC="<table xmlns=\"urn:example:clixon\"><parameter><name>eth0</name></parameter><parameter><name>eth1</name></parameter></table>"
|
||||||
FAILSAFE_CFG="<interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\"><interface><name>eth99</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces>"
|
FAILSAFE_CFG="<table xmlns=\"urn:example:clixon\"><parameter><name>eth99</name></parameter></table>"
|
||||||
|
|
||||||
# TODO this test suite is somewhat brittle as it relies on the presence of the example configuration that one gets with
|
new "test params: -f $cfg"
|
||||||
# make install-example in the Clixon distribution. It would be better if the dependencies were entirely self contained.
|
|
||||||
|
|
||||||
new "test params: -f $cfg -- -s"
|
|
||||||
# Bring your own backend
|
# Bring your own backend
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
# kill old backend (if any)
|
# kill old backend (if any)
|
||||||
|
|
@ -208,15 +137,19 @@ if [ $BE -ne 0 ]; then
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
new "start backend -s init -f $cfg -- -s"
|
new "start backend -s init -f $cfg"
|
||||||
start_backend -s init -f $cfg -- -s
|
start_backend -s init -f $cfg
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "wait backend"
|
new "wait backend"
|
||||||
wait_backend
|
wait_backend
|
||||||
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
|
|
||||||
|
new "Hello check confirm-commit capability"
|
||||||
|
expecteof "$clixon_netconf -f $cfg" 0 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><hello $DEFAULTONLY><capabilities><capability>urn:ietf:params:netconf:base:1.1</capability></capabilities></hello>]]>]]>" "<capability>urn:ietf:params:netconf:capability:confirmed-commit:1.1</capability>" '^$'
|
||||||
|
|
||||||
|
################################################################################
|
||||||
new "netconf ephemeral confirmed-commit rolls back after disconnect"
|
new "netconf ephemeral confirmed-commit rolls back after disconnect"
|
||||||
reset
|
reset
|
||||||
edit_config "candidate" "$CONFIGB"
|
edit_config "candidate" "$CONFIGB"
|
||||||
|
|
@ -305,13 +238,13 @@ commit "<persist>abcdefg</persist><confirmed/>"
|
||||||
assert_config_equals "running" "$CONFIGBPLUSC"
|
assert_config_equals "running" "$CONFIGBPLUSC"
|
||||||
stop_backend -f $cfg # kill backend and restart
|
stop_backend -f $cfg # kill backend and restart
|
||||||
[ -f "$ROLLBACK_PATH" ] || err "rollback_db doesn't exist!" # assert rollback_db exists
|
[ -f "$ROLLBACK_PATH" ] || err "rollback_db doesn't exist!" # assert rollback_db exists
|
||||||
start_backend -s running -f $cfg -- -s
|
start_backend -s running -f $cfg
|
||||||
wait_backend
|
wait_backend
|
||||||
assert_config_equals "running" "$CONFIGB"
|
assert_config_equals "running" "$CONFIGB"
|
||||||
[ -f "ROLLBACK_PATH" ] && err "rollback_db still exists!" # assert rollback_db doesn't exist
|
[ -f "ROLLBACK_PATH" ] && err "rollback_db still exists!" # assert rollback_db doesn't exist
|
||||||
|
|
||||||
stop_backend -f $cfg
|
stop_backend -f $cfg
|
||||||
start_backend -s init -f $cfg -- -s
|
start_backend -s init -f $cfg
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
|
|
@ -334,12 +267,12 @@ sudo tee "$ROLLBACK_PATH" > /dev/null << EOF
|
||||||
</bar>
|
</bar>
|
||||||
</foo>
|
</foo>
|
||||||
EOF
|
EOF
|
||||||
start_backend -s running -f $cfg -- -s
|
start_backend -s running -f $cfg
|
||||||
wait_backend
|
wait_backend
|
||||||
assert_config_equals "running" "$FAILSAFE_CFG"
|
assert_config_equals "running" "$FAILSAFE_CFG"
|
||||||
|
|
||||||
stop_backend -f $cfg
|
stop_backend -f $cfg
|
||||||
start_backend -s init -f $cfg -lf/tmp/clixon.log -D1 -- -s
|
start_backend -s init -f $cfg -lf/tmp/clixon.log -D1
|
||||||
wait_backend
|
wait_backend
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
@ -364,14 +297,15 @@ reset
|
||||||
|
|
||||||
tmppipe=$(mktemp -u)
|
tmppipe=$(mktemp -u)
|
||||||
mkfifo -m 600 "$tmppipe"
|
mkfifo -m 600 "$tmppipe"
|
||||||
|
|
||||||
cat << EOF | clixon_cli -f $cfg >> /dev/null &
|
cat << EOF | clixon_cli -f $cfg >> /dev/null &
|
||||||
set interfaces interface eth0 type ex:eth
|
set table parameter eth0
|
||||||
set interfaces interface eth0 enabled true
|
|
||||||
commit confirmed 60
|
commit confirmed 60
|
||||||
shell echo >> $tmppipe
|
shell echo >> $tmppipe
|
||||||
shell cat $tmppipe
|
shell cat $tmppipe
|
||||||
quit
|
quit
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat $tmppipe >> /dev/null
|
cat $tmppipe >> /dev/null
|
||||||
assert_config_equals "running" "$CONFIGB"
|
assert_config_equals "running" "$CONFIGB"
|
||||||
echo >> $tmppipe
|
echo >> $tmppipe
|
||||||
|
|
@ -383,17 +317,17 @@ rm $tmppipe
|
||||||
|
|
||||||
new "cli persistent confirmed-commit"
|
new "cli persistent confirmed-commit"
|
||||||
reset
|
reset
|
||||||
|
|
||||||
cat << EOF | clixon_cli -f $cfg >> /dev/null
|
cat << EOF | clixon_cli -f $cfg >> /dev/null
|
||||||
set interfaces interface eth0 type ex:eth
|
set table parameter eth0
|
||||||
set interfaces interface eth0 enabled true
|
|
||||||
commit confirmed persist a
|
commit confirmed persist a
|
||||||
quit
|
quit
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
assert_config_equals "running" "$CONFIGB"
|
assert_config_equals "running" "$CONFIGB"
|
||||||
|
|
||||||
cat << EOF | clixon_cli -f $cfg >> /dev/null
|
cat << EOF | clixon_cli -f $cfg >> /dev/null
|
||||||
set interfaces interface eth1 type ex:eth
|
set table parameter eth1
|
||||||
set interfaces interface eth1 enabled true
|
|
||||||
commit persist-id a confirmed persist ab
|
commit persist-id a confirmed persist ab
|
||||||
quit
|
quit
|
||||||
EOF
|
EOF
|
||||||
|
|
@ -420,8 +354,7 @@ expectpart "$($clixon_cli -lo -1 -f $cfg commit persist-id ab cancel)" 255 "no c
|
||||||
new "cli persistent confirmed-commit with timeout"
|
new "cli persistent confirmed-commit with timeout"
|
||||||
reset
|
reset
|
||||||
cat << EOF | clixon_cli -f $cfg >> /dev/null
|
cat << EOF | clixon_cli -f $cfg >> /dev/null
|
||||||
set interfaces interface eth0 type ex:eth
|
set table parameter eth0
|
||||||
set interfaces interface eth0 enabled true
|
|
||||||
commit confirmed persist abcd 2
|
commit confirmed persist abcd 2
|
||||||
EOF
|
EOF
|
||||||
assert_config_equals "running" "$CONFIGB"
|
assert_config_equals "running" "$CONFIGB"
|
||||||
|
|
@ -433,16 +366,16 @@ assert_config_equals "running" ""
|
||||||
new "cli persistent confirmed-commit with reset timeout"
|
new "cli persistent confirmed-commit with reset timeout"
|
||||||
reset
|
reset
|
||||||
cat << EOF | clixon_cli -f $cfg >> /dev/null
|
cat << EOF | clixon_cli -f $cfg >> /dev/null
|
||||||
set interfaces interface eth0 type ex:eth
|
set table parameter eth0
|
||||||
set interfaces interface eth0 enabled true
|
|
||||||
commit confirmed persist abcd 5
|
commit confirmed persist abcd 5
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
assert_config_equals "running" "$CONFIGB"
|
assert_config_equals "running" "$CONFIGB"
|
||||||
cat << EOF | clixon_cli -f $cfg >> /dev/null
|
cat << EOF | clixon_cli -f $cfg >> /dev/null
|
||||||
set interfaces interface eth1 type ex:eth
|
set table parameter eth1
|
||||||
set interfaces interface eth1 enabled true
|
|
||||||
commit persist-id abcd confirmed persist abcdef 10
|
commit persist-id abcd confirmed persist abcdef 10
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
sleep 6
|
sleep 6
|
||||||
assert_config_equals "running" "$CONFIGBPLUSC"
|
assert_config_equals "running" "$CONFIGBPLUSC"
|
||||||
# now sleep long enough for rollback to happen; get config, assert == A
|
# now sleep long enough for rollback to happen; get config, assert == A
|
||||||
|
|
@ -452,7 +385,21 @@ assert_config_equals "running" ""
|
||||||
|
|
||||||
# TODO test restconf receives "409 conflict" when there is a persistent confirmed-commit active
|
# TODO test restconf receives "409 conflict" when there is a persistent confirmed-commit active
|
||||||
# TODO test restconf causes confirming-commit for ephemeral confirmed-commit
|
# TODO test restconf causes confirming-commit for ephemeral confirmed-commit
|
||||||
|
if [ $RC -ne 0 ]; then
|
||||||
|
new "kill old restconf daemon"
|
||||||
|
stop_restconf_pre
|
||||||
|
|
||||||
|
new "start restconf daemon"
|
||||||
|
start_restconf -f $cfg
|
||||||
|
fi
|
||||||
|
|
||||||
|
new "wait restconf"
|
||||||
|
wait_restconf
|
||||||
|
|
||||||
|
if [ $RC -ne 0 ]; then
|
||||||
|
new "Kill restconf daemon"
|
||||||
|
stop_restconf
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
|
|
@ -465,5 +412,8 @@ if [ $BE -ne 0 ]; then
|
||||||
stop_backend -f $cfg
|
stop_backend -f $cfg
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Set by restconf_config
|
||||||
|
unset RESTCONFIG
|
||||||
|
|
||||||
new "endtest"
|
new "endtest"
|
||||||
endtest
|
endtest
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,15 @@ new "Netconf snd hello with prefix"
|
||||||
expecteof "$clixon_netconf -qef $cfg" 0 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><nc:hello xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><nc:capabilities><nc:capability>urn:ietf:params:netconf:base:1.1</nc:capability></nc:capabilities></nc:hello>]]>]]>" '^$'
|
expecteof "$clixon_netconf -qef $cfg" 0 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><nc:hello xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><nc:capabilities><nc:capability>urn:ietf:params:netconf:base:1.1</nc:capability></nc:capabilities></nc:hello>]]>]]>" '^$'
|
||||||
|
|
||||||
new "netconf snd + rcv hello"
|
new "netconf snd + rcv hello"
|
||||||
expecteof "$clixon_netconf -f $cfg" 0 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><hello $DEFAULTONLY><capabilities><capability>urn:ietf:params:netconf:base:1.1</capability></capabilities></hello>]]>]]>" "^<hello $DEFAULTONLY><capabilities><capability>urn:ietf:params:netconf:base:1.1</capability><capability>urn:ietf:params:netconf:base:1.0</capability><capability>urn:ietf:params:netconf:capability:yang-library:1.0?revision=2019-01-04&module-set-id=42</capability><capability>urn:ietf:params:netconf:capability:candidate:1.0</capability><capability>urn:ietf:params:netconf:capability:validate:1.1</capability><capability>urn:ietf:params:netconf:capability:startup:1.0</capability><capability>urn:ietf:params:netconf:capability:xpath:1.0</capability><capability>urn:ietf:params:netconf:capability:notification:1.0</capability><capability>urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&also-supported=report-all,trim,report-all-tagged</capability></capabilities><session-id>[0-9]*</session-id></hello>]]>]]>$" '^$'
|
expecteof "$clixon_netconf -f $cfg" 0 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><hello $DEFAULTONLY><capabilities><capability>urn:ietf:params:netconf:base:1.1</capability></capabilities></hello>]]>]]>" "^<hello $DEFAULTONLY><capabilities><capability>urn:ietf:params:netconf:base:1.1</capability><capability>urn:ietf:params:netconf:base:1.0</capability>
|
||||||
|
<capability>urn:ietf:params:netconf:capability:yang-library:1.0?revision=2019-01-04&module-set-id=42</capability>
|
||||||
|
<capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>
|
||||||
|
<capability>urn:ietf:params:netconf:capability:validate:1.1</capability>
|
||||||
|
<capability>urn:ietf:params:netconf:capability:xpath:1.0</capability>
|
||||||
|
<capability>urn:ietf:params:netconf:capability:notification:1.0</capability>
|
||||||
|
<capability>urn:ietf:params:netconf:capability:startup:1.0</capability>
|
||||||
|
<capability>urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&also-supported=report-all,trim,report-all-tagged</capability>
|
||||||
|
</capabilities><session-id>[0-9]*</session-id></hello>]]>]]>$" '^$'
|
||||||
|
|
||||||
# Actually non-standard to reply on wrong hello with rpc-error, but may be useful
|
# Actually non-standard to reply on wrong hello with rpc-error, but may be useful
|
||||||
new "Netconf snd hello with extra element"
|
new "Netconf snd hello with extra element"
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ EOF
|
||||||
new "Start Listener client"
|
new "Start Listener client"
|
||||||
echo "ssh -s -F $sshcfg -v -i $key -o ProxyUseFdpass=yes -o ProxyCommand=\"clixon_netconf_ssh_callhome_client -a 127.0.0.1\" . netconf"
|
echo "ssh -s -F $sshcfg -v -i $key -o ProxyUseFdpass=yes -o ProxyCommand=\"clixon_netconf_ssh_callhome_client -a 127.0.0.1\" . netconf"
|
||||||
#-F $sshcfg
|
#-F $sshcfg
|
||||||
expectpart "$(ssh -s -F $sshcfg -v -i $key -o ProxyUseFdpass=yes -o ProxyCommand="${clixon_netconf_ssh_callhome_client} -a 127.0.0.1" . netconf < $rpccmd)" 0 "<hello $DEFAULTONLY><capabilities><capability>urn:ietf:params:netconf:base:1.1</capability><capability>urn:ietf:params:netconf:base:1.0</capability><capability>urn:ietf:params:netconf:capability:yang-library:1.0?revision=2019-01-04&module-set-id=42</capability><capability>urn:ietf:params:netconf:capability:candidate:1.0</capability><capability>urn:ietf:params:netconf:capability:validate:1.1</capability><capability>urn:ietf:params:netconf:capability:startup:1.0</capability><capability>urn:ietf:params:netconf:capability:xpath:1.0</capability><capability>urn:ietf:params:netconf:capability:notification:1.0</capability><capability>urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&also-supported=report-all,trim,report-all-tagged</capability></capabilities><session-id>2</session-id></hello>" "<rpc-reply $DEFAULTNS><data/></rpc-reply>"
|
expectpart "$(ssh -s -F $sshcfg -v -i $key -o ProxyUseFdpass=yes -o ProxyCommand="${clixon_netconf_ssh_callhome_client} -a 127.0.0.1" . netconf < $rpccmd)" 0 "<hello $DEFAULTONLY><capabilities><capability>urn:ietf:params:netconf:base:1.1</capability><capability>urn:ietf:params:netconf:base:1.0</capability><capability>urn:ietf:params:netconf:capability:yang-library:1.0?revision=2019-01-04&module-set-id=42</capability><capability>urn:ietf:params:netconf:capability:candidate:1.0</capability><capability>urn:ietf:params:netconf:capability:validate:1.1</capability><capability>urn:ietf:params:netconf:capability:xpath:1.0</capability><capability>urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&also-supported=report-all,trim,report-all-tagged</capability><capability>urn:ietf:params:netconf:capability:notification:1.0</capability></capabilities><session-id>2</session-id></hello>" "<rpc-reply $DEFAULTNS><data/></rpc-reply>"
|
||||||
|
|
||||||
# Wait
|
# Wait
|
||||||
wait
|
wait
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue