* Made backend transaction and commit/validate API available to plugin code.

* This enables that RPOC handles can call commit and validate via lib
  * The commit/validate API is now: `candidate_validate()` and `candidate_commit()`
This commit is contained in:
Olof hagsand 2021-06-17 19:20:27 +02:00
parent 1f7fc3afcb
commit dd8883420c
14 changed files with 110 additions and 110 deletions

View file

@ -81,6 +81,9 @@ Users may have to change how they access the system
Developers may need to change their code Developers may need to change their code
* Made backend transaction and commit/validate API available to plugin code.
* This enables that RPOC handles can call commit and validate via lib
* The commit/validate API is now: `candidate_validate()` and `candidate_commit()`
* Event exit API changed to a single decrementing counter where 1 means exit. * Event exit API changed to a single decrementing counter where 1 means exit.
* Removed: `clicon_exit_reset()` * Removed: `clicon_exit_reset()`
* Changed: `clicon_exit_set()` --> `clixon_exit_set(int nr)` * Changed: `clicon_exit_set()` --> `clixon_exit_set(int nr)`

View file

@ -85,14 +85,15 @@ APPL = clixon_backend
APPSRC = backend_main.c APPSRC = backend_main.c
APPSRC += backend_socket.c APPSRC += backend_socket.c
APPSRC += backend_client.c APPSRC += backend_client.c
APPSRC += backend_commit.c
APPSRC += backend_plugin.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) APPOBJ = $(APPSRC:.c=.o)
# Accessible from plugin # Accessible from plugin
LIBSRC = clixon_backend_transaction.c clixon_backend_handle.c LIBSRC = clixon_backend_transaction.c
LIBSRC += clixon_backend_handle.c
LIBSRC += backend_commit.c
LIBSRC += backend_plugin.c
LIBOBJ = $(LIBSRC:.c=.o) LIBOBJ = $(LIBSRC:.c=.o)
# Name of lib # Name of lib
@ -143,7 +144,7 @@ uninstall:
rm -f $(DESTDIR)$(libdir)/$(MYLIBLINK)* rm -f $(DESTDIR)$(libdir)/$(MYLIBLINK)*
rm -f $(DESTDIR)$(includedir)/clixon/* rm -f $(DESTDIR)$(includedir)/clixon/*
install-include: clixon_backend.h clixon_backend_handle.h clixon_backend_transaction.h install-include: clixon_backend.h clixon_backend_handle.h clixon_backend_transaction.h clixon_backend_plugin.h clixon_backend_commit.h
install -d -m 0755 $(DESTDIR)$(includedir)/clixon install -d -m 0755 $(DESTDIR)$(includedir)/clixon
install -m 0644 $^ $(DESTDIR)$(includedir)/clixon install -m 0644 $^ $(DESTDIR)$(includedir)/clixon

View file

@ -67,8 +67,8 @@
#include <clixon/clixon.h> #include <clixon/clixon.h>
#include "clixon_backend_handle.h" #include "clixon_backend_handle.h"
#include "backend_plugin.h" #include "clixon_backend_plugin.h"
#include "backend_commit.h" #include "clixon_backend_commit.h"
#include "backend_client.h" #include "backend_client.h"
#include "backend_handle.h" #include "backend_handle.h"

View file

@ -66,9 +66,9 @@
#include <clixon/clixon.h> #include <clixon/clixon.h>
#include "clixon_backend_transaction.h" #include "clixon_backend_transaction.h"
#include "backend_plugin.h" #include "clixon_backend_plugin.h"
#include "backend_handle.h" #include "backend_handle.h"
#include "backend_commit.h" #include "clixon_backend_commit.h"
#include "backend_client.h" #include "backend_client.h"
/*! Key values are checked for validity independent of user-defined callbacks /*! Key values are checked for validity independent of user-defined callbacks
@ -177,7 +177,7 @@ generic_validate(clicon_handle h,
* 4. Validate startup db. (valid) * 4. Validate startup db. (valid)
* 5. If valid fails, call startup-cb(Invalid, msdiff), keep startup in candidate and commit failsafe db. Done. * 5. If valid fails, call startup-cb(Invalid, msdiff), keep startup in candidate and commit failsafe db. Done.
* 6. Call startup-cb(OK, msdiff) and commit. * 6. Call startup-cb(OK, msdiff) and commit.
* @see from_validate_common for incoming validate/commit * @see validate_common for incoming validate/commit
*/ */
static int static int
startup_common(clicon_handle h, startup_common(clicon_handle h,
@ -489,8 +489,8 @@ startup_commit(clicon_handle h,
* @see startup_common for startup scenario * @see startup_common for startup scenario
*/ */
static int static int
from_validate_common(clicon_handle h, validate_common(clicon_handle h,
char *candidate, char *db,
transaction_data_t *td, transaction_data_t *td,
cxobj **xret) cxobj **xret)
{ {
@ -505,7 +505,7 @@ from_validate_common(clicon_handle h,
goto done; goto done;
} }
/* This is the state we are going to */ /* This is the state we are going to */
if (xmldb_get0(h, candidate, YB_MODULE, NULL, "/", 0, &td->td_target, NULL, NULL) < 0) if (xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, &td->td_target, NULL, NULL) < 0)
goto done; goto done;
/* Clear flags xpath for get */ /* Clear flags xpath for get */
@ -579,20 +579,73 @@ from_validate_common(clicon_handle h,
goto done; goto done;
} }
/*! Start a validate transaction
*
* @param[in] h Clicon handle
* @param[in] db A candidate database, typically "candidate" but not necessarily so
* @retval -1 Error - or validation failed
* @retval 0 Validation failed (with cbret set)
* @retval 1 Validation OK
*/
int
candidate_validate(clicon_handle h,
char *db,
cbuf *cbret)
{
int retval = -1;
transaction_data_t *td = NULL;
cxobj *xret = NULL;
int ret;
clicon_debug(1, "%s", __FUNCTION__);
if (db == NULL || cbret == NULL){
clicon_err(OE_CFG, EINVAL, "db or cbret is NULL");
goto done;
}
/* 1. Start transaction */
if ((td = transaction_new()) == NULL)
goto done;
/* Common steps (with commit) */
if ((ret = validate_common(h, db, td, &xret)) < 1){
/* A little complex due to several sources of validation fails or errors.
* (1) xerr is set -> translate to cbret; (2) cbret set use that; otherwise
* use clicon_err. */
if (xret && clicon_xml2cbuf(cbret, xret, 0, 0, -1) < 0)
goto done;
plugin_transaction_abort_all(h, td);
if (!cbuf_len(cbret) &&
netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
goto done;
goto fail;
}
if (xmldb_get0_clear(h, td->td_src) < 0 ||
xmldb_get0_clear(h, td->td_target) < 0){
plugin_transaction_abort_all(h, td);
goto done;
}
plugin_transaction_end_all(h, td);
retval = 1;
done:
return retval;
fail:
retval = 0;
goto done;
}
/*! Do a diff between candidate and running, then start a commit transaction /*! Do a diff between candidate and running, then start a commit transaction
* *
* The code reverts changes if the commit fails. But if the revert * The code reverts changes if the commit fails. But if the revert
* fails, we just ignore the errors and proceed. Maybe we should * fails, we just ignore the errors and proceed. Maybe we should
* do something more drastic? * do something more drastic?
* @param[in] h Clicon handle * @param[in] h Clicon handle
* @param[in] candidate A candidate database, not necessarily "candidate" * @param[in] db A candidate database, not necessarily "candidate"
* @retval -1 Error - or validation failed * @retval -1 Error - or validation failed
* @retval 0 Validation failed (with cbret set) * @retval 0 Validation failed (with cbret set)
* @retval 1 Validation OK * @retval 1 Validation OK
*/ */
int int
candidate_commit(clicon_handle h, candidate_commit(clicon_handle h,
char *candidate, char *db,
cbuf *cbret) cbuf *cbret)
{ {
int retval = -1; int retval = -1;
@ -607,7 +660,7 @@ candidate_commit(clicon_handle h,
/* Common steps (with validate). Load candidate and running and compute diffs /* Common steps (with validate). Load candidate and running and compute diffs
* Note this is only call that uses 3-values * Note this is only call that uses 3-values
*/ */
if ((ret = from_validate_common(h, candidate, td, &xret)) < 0) if ((ret = validate_common(h, db, td, &xret)) < 0)
goto done; goto done;
if (ret == 0){ if (ret == 0){
if (clicon_xml2cbuf(cbret, xret, 0, 0, -1) < 0) if (clicon_xml2cbuf(cbret, xret, 0, 0, -1) < 0)
@ -630,9 +683,9 @@ candidate_commit(clicon_handle h,
/* 8. Success: Copy candidate to running /* 8. Success: Copy candidate to running
*/ */
if (xmldb_copy(h, candidate, "running") < 0) if (xmldb_copy(h, db, "running") < 0)
goto done; goto done;
xmldb_modified_set(h, candidate, 0); /* reset dirty bit */ xmldb_modified_set(h, db, 0); /* reset dirty bit */
/* Here pointers to old (source) tree are obsolete */ /* Here pointers to old (source) tree are obsolete */
if (td->td_dvec){ if (td->td_dvec){
td->td_dlen = 0; td->td_dlen = 0;
@ -819,56 +872,22 @@ from_client_validate(clicon_handle h,
void *regarg) void *regarg)
{ {
int retval = -1; int retval = -1;
transaction_data_t *td = NULL;
int ret; int ret;
char *db; char *db;
cxobj *xret = NULL;
clicon_debug(1, "%s", __FUNCTION__);
if ((db = netconf_db_find(xe, "source")) == NULL){ if ((db = netconf_db_find(xe, "source")) == NULL){
if (netconf_missing_element(cbret, "protocol", "source", NULL) < 0) if (netconf_missing_element(cbret, "protocol", "source", NULL) < 0)
goto done; goto done;
goto ok; goto ok;
} }
clicon_debug(1, "Validate %s", db); if ((ret = candidate_validate(h, db, cbret)) < 0)
/* 1. Start transaction */
if ((td = transaction_new()) == NULL)
goto done; goto done;
/* Common steps (with commit) */ if (ret == 1)
if ((ret = from_validate_common(h, db, td, &xret)) < 1){
/* A little complex due to several sources of validation fails or errors.
* (1) xerr is set -> translate to cbret; (2) cbret set use that; otherwise
* use clicon_err. */
if (xret && clicon_xml2cbuf(cbret, xret, 0, 0, -1) < 0)
goto done;
plugin_transaction_abort_all(h, td);
if (!cbuf_len(cbret) &&
netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
goto done;
goto ok;
}
if (xmldb_get0_clear(h, td->td_src) < 0 ||
xmldb_get0_clear(h, td->td_target) < 0){
plugin_transaction_abort_all(h, td);
goto done;
}
cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", NETCONF_BASE_NAMESPACE); cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", NETCONF_BASE_NAMESPACE);
/* Call plugin transaction end callbacks */
plugin_transaction_end_all(h, td);
ok: ok:
retval = 0; retval = 0;
done: done:
if (td){
if (retval < 0)
plugin_transaction_abort_all(h, td);
xmldb_get0_free(h, &td->td_target);
xmldb_get0_free(h, &td->td_src);
transaction_free(td);
}
if (xret)
xml_free(xret);
return retval; return retval;
} /* from_client_validate */ } /* from_client_validate */

View file

@ -72,8 +72,8 @@
#include "clixon_backend_transaction.h" #include "clixon_backend_transaction.h"
#include "backend_socket.h" #include "backend_socket.h"
#include "backend_client.h" #include "backend_client.h"
#include "backend_plugin.h" #include "clixon_backend_plugin.h"
#include "backend_commit.h" #include "clixon_backend_commit.h"
#include "backend_handle.h" #include "backend_handle.h"
#include "backend_startup.h" #include "backend_startup.h"
#include "backend_plugin_restconf.h" #include "backend_plugin_restconf.h"

View file

@ -62,8 +62,8 @@
#include <clixon/clixon.h> #include <clixon/clixon.h>
#include "clixon_backend_transaction.h" #include "clixon_backend_transaction.h"
#include "backend_plugin.h" #include "clixon_backend_plugin.h"
#include "backend_commit.h" #include "clixon_backend_commit.h"
/*! Request plugins to reset system state /*! Request plugins to reset system state
* The system 'state' should be the same as the contents of running_db * The system 'state' should be the same as the contents of running_db

View file

@ -66,9 +66,9 @@
#include <clixon/clixon.h> #include <clixon/clixon.h>
#include "clixon_backend_transaction.h" #include "clixon_backend_transaction.h"
#include "backend_plugin.h" #include "clixon_backend_plugin.h"
#include "backend_handle.h" #include "backend_handle.h"
#include "backend_commit.h" #include "clixon_backend_commit.h"
#include "backend_startup.h" #include "backend_startup.h"
/*! Merge db1 into db2 without commit /*! Merge db1 into db2 without commit

View file

@ -52,6 +52,8 @@ extern "C" {
/* Common code (API and Backend daemon) */ /* Common code (API and Backend daemon) */
#include <clixon/clixon_backend_handle.h> #include <clixon/clixon_backend_handle.h>
#include <clixon/clixon_backend_transaction.h> #include <clixon/clixon_backend_transaction.h>
#include <clixon/clixon_backend_commit.h>
#include <clixon/clixon_backend_plugin.h>
#endif /* _CLIXON_BACKEND_H_ */ #endif /* _CLIXON_BACKEND_H_ */

View file

@ -36,14 +36,15 @@
*/ */
#ifndef _BACKEND_COMMIT_H_ #ifndef _CLIXON_BACKEND_COMMIT_H_
#define _BACKEND_COMMIT_H_ #define _CLIXON_BACKEND_COMMIT_H_
/* /*
* Prototypes * Prototypes
*/ */
int startup_validate(clicon_handle h, char *db, cxobj **xtr, cbuf *cbret); int startup_validate(clicon_handle h, char *db, cxobj **xtr, cbuf *cbret);
int startup_commit(clicon_handle h, char *db, cbuf *cbret); int startup_commit(clicon_handle h, char *db, cbuf *cbret);
int candidate_validate(clicon_handle h, char *db, cbuf *cbret);
int candidate_commit(clicon_handle h, char *db, cbuf *cbret); int candidate_commit(clicon_handle h, char *db, cbuf *cbret);
int from_client_commit(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg); int from_client_commit(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
@ -52,4 +53,4 @@ int from_client_cancel_commit(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg
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);
#endif /* _BACKEND_COMMIT_H_ */ #endif /* _CLIXON_BACKEND_COMMIT_H_ */

View file

@ -35,8 +35,8 @@
*/ */
#ifndef _BACKEND_PLUGIN_H_ #ifndef _CLIXON_BACKEND_PLUGIN_H_
#define _BACKEND_PLUGIN_H_ #define _CLIXON_BACKEND_PLUGIN_H_
/* /*
* Types * Types
@ -101,4 +101,4 @@ int plugin_transaction_end_all(clicon_handle h, transaction_data_t *td);
int plugin_transaction_abort_one(clixon_plugin_t *cp, clicon_handle h, transaction_data_t *td); int plugin_transaction_abort_one(clixon_plugin_t *cp, clicon_handle h, transaction_data_t *td);
int plugin_transaction_abort_all(clicon_handle h, transaction_data_t *td); int plugin_transaction_abort_all(clicon_handle h, transaction_data_t *td);
#endif /* _BACKEND_PLUGIN_H_ */ #endif /* _CLIXON_BACKEND_PLUGIN_H_ */

View file

@ -61,7 +61,7 @@
#include <clixon/clixon.h> #include <clixon/clixon.h>
#include "clixon_backend_transaction.h" #include "clixon_backend_transaction.h"
#include "backend_plugin.h" #include "clixon_backend_plugin.h"
/* Access functions for transaction-data handle in callbacks /* Access functions for transaction-data handle in callbacks
* Expressed in a transition from an current -> wanted state. * Expressed in a transition from an current -> wanted state.

View file

@ -1,6 +0,0 @@
#!/bin/sh
# Travis pre-config script.
# Clone and install CLIgen (needed for clixon configure and make)
# Note travis builds and installs, then starts a clixon container where all tests are run from.
git clone https://github.com/clicon/cligen.git
(cd cligen && ./configure && make && sudo make install)

View file

@ -1,5 +0,0 @@
#!/usr/bin/env bash
# Travis pre-config script.
# build libevhtp
git clone https://github.com/clicon/libevhtp.git
(cd libevhtp/build && cmake -DEVHTP_DISABLE_REGEX=ON -DEVHTP_DISABLE_EVTHR=ON .. && make && sudo make install)

View file

@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -eux
./configure --with-restconf=fcgi
make
sudo make install
(cd example; make; sudo make install)
(cd util; make; sudo make install)
sudo ldconfig
ps aux|grep clixon
cd test;
./test_api_path.sh
ps aux|grep clixon
./test_augment.sh
ps aux|grep clixon
./all.sh