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:
Olof hagsand 2022-10-07 10:02:07 +02:00
parent 8abcda6f85
commit 11eccd5478
16 changed files with 177 additions and 349 deletions

View file

@ -87,10 +87,6 @@ INCLUDES = -I. -I$(top_srcdir)/lib/src -I$(top_srcdir)/lib -I$(top_srcdir)/inclu
# Name of application
APPL = clixon_backend
# Source / objects called from plugin and otherwise
COMMONSRC = backend_failsafe.c
COMMONOBJ = $(COMMONSRC:.c=.o)
# Not accessible from plugin
APPSRC = backend_main.c
APPSRC += backend_socket.c
@ -98,14 +94,14 @@ APPSRC += backend_client.c
APPSRC += backend_get.c
APPSRC += backend_plugin_restconf.c # Pseudo plugin for restconf daemon
APPSRC += backend_startup.c
APPOBJ = $(APPSRC:.c=.o) $(COMMONOBJ)
APPOBJ = $(APPSRC:.c=.o)
# Accessible from plugin
LIBSRC = clixon_backend_transaction.c
LIBSRC += clixon_backend_handle.c
LIBSRC += backend_commit.c
LIBSRC += backend_plugin.c
LIBOBJ = $(LIBSRC:.c=.o) $(COMMONOBJ)
LIBOBJ = $(LIBSRC:.c=.o)
# Name of lib
MYNAME = clixon_backend

View file

@ -70,7 +70,6 @@
#include "backend_handle.h"
#include "clixon_backend_commit.h"
#include "backend_client.h"
#include "backend_failsafe.h"
/* a global instance of the confirmed_commit struct for reference throughout the procedure */
struct confirmed_commit confirmed_commit = {
@ -1577,3 +1576,58 @@ from_client_restart_one(clicon_handle h,
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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -962,7 +962,7 @@ main(int argc,
if (status != STARTUP_OK){
if (cbuf_len(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;
}
status = STARTUP_OK;

View file

@ -132,9 +132,10 @@ startup_mode_startup(clicon_handle h,
char *db,
cbuf *cbret)
{
int retval = -1;
int ret = 0;
int db_exists;
int retval = -1;
int ret = 0;
int rollback_exists;
yang_stmt *yspec = clicon_dbspec_yang(h);
if (strcmp(db, "running")==0){
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
* rebooted.
*/
yang_stmt *yspec = clicon_dbspec_yang(h);
if (if_feature(yspec, "ietf-netconf", "confirmed-commit")) {
db_exists = xmldb_exists(h, "rollback");
if (db_exists < 0) {
if ((rollback_exists = xmldb_exists(h, "rollback")) < 0) {
clicon_err(OE_DAEMON, 0, "Error checking for the existence of the rollback database");
goto done;
} else if (db_exists == 1) {
}
if (rollback_exists == 1) {
ret = startup_commit(h, "rollback", cbret);
switch(ret) {
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 */
xmldb_rename(h, db, NULL, ".error");
retval = 1;
goto done;
goto ok;
case 1:
/* validation ok */
retval = 1;
xmldb_delete(h, "rollback");
goto done;
goto ok;
default:
/* Unexpected response */
goto fail;
}
}
} else if ((ret = startup_commit(h, db, cbret)) < 0)
goto done;
if (ret == 0)
goto fail;
else {
if ((ret = startup_commit(h, db, cbret)) < 0)
goto done;
if (ret == 0)
goto fail;
}
}
else {
if ((ret = startup_commit(h, db, cbret)) < 0)
goto done;
if (ret == 0)
goto fail;
}
ok:
retval = 1;
done:
return retval;
@ -332,56 +339,6 @@ startup_extraxml(clicon_handle h,
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
* Set the modules state as setopt to the datastore module.
* Only if CLICON_XMLDB_MODSTATE is enabled

View file

@ -44,7 +44,6 @@
*/
int startup_mode_startup(clicon_handle h, char *db, 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);
#endif /* _BACKEND_STARTUP_H_ */

View file

@ -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_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 load_failsafe(clicon_handle h, char *phase);
#endif /* _CLIXON_BACKEND_COMMIT_H_ */

View file

@ -750,7 +750,7 @@ clixon_snmp_scalar_handler1(netsnmp_mib_handler *handler,
goto done;
break;
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;
break;
case MODE_SET_FREE: /* 4 */
@ -1303,7 +1303,7 @@ clixon_snmp_table_handler1(netsnmp_mib_handler *handler,
}
break;
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;
break;
case MODE_SET_FREE: // 4