* C-API: Added vlev validate level parameter to candidate_commit
* `vlev` : validate level
This commit is contained in:
parent
a8e13047fc
commit
034ab632f1
13 changed files with 98 additions and 60 deletions
|
|
@ -173,7 +173,10 @@ Developers may need to change their code
|
||||||
* Added three-value return.
|
* Added three-value return.
|
||||||
* Code need to be changed from: checking for `<0` to `<1` to keep same semantics
|
* Code need to be changed from: checking for `<0` to `<1` to keep same semantics
|
||||||
* Added `skiptop` parameter to `xml2json_vec()`
|
* Added `skiptop` parameter to `xml2json_vec()`
|
||||||
* Added `xe` argument to `candidate_commit` for confirmed commit extra parameters
|
* Added two arguments to `candidate_commit`
|
||||||
|
* `myid` : Client-id of incoming message
|
||||||
|
* `vlev` : validate level
|
||||||
|
* Both parameters are default `0` for backward-compatibility
|
||||||
|
|
||||||
### Minor features
|
### Minor features
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -567,7 +567,7 @@ from_client_edit_config(clicon_handle h,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((ret = candidate_commit(h, NULL, "candidate", myid, cbret)) < 0){ /* Assume validation fail, nofatal */
|
if ((ret = candidate_commit(h, NULL, "candidate", myid, VL_FULL, cbret)) < 0){ /* Assume validation fail, nofatal */
|
||||||
if (netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
|
if (netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
|
||||||
goto done;
|
goto done;
|
||||||
xmldb_copy(h, "running", "candidate");
|
xmldb_copy(h, "running", "candidate");
|
||||||
|
|
|
||||||
|
|
@ -518,7 +518,7 @@ validate_common(clicon_handle h,
|
||||||
&td->td_tcvec, /* changed: wanted values */
|
&td->td_tcvec, /* changed: wanted values */
|
||||||
&td->td_clen) < 0)
|
&td->td_clen) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
transaction_dbg(h, CLIXON_DBG_DEFAULT, td, __FUNCTION__);
|
transaction_dbg(h, CLIXON_DBG_DETAIL, td, __FUNCTION__);
|
||||||
/* Mark as changed in tree */
|
/* Mark as changed in tree */
|
||||||
for (i=0; i<td->td_dlen; i++){ /* Also down */
|
for (i=0; i<td->td_dlen; i++){ /* Also down */
|
||||||
xn = td->td_dvec[i];
|
xn = td->td_dvec[i];
|
||||||
|
|
@ -648,6 +648,7 @@ candidate_validate(clicon_handle h,
|
||||||
* @param[in] xe Request: <rpc><xn></rpc> (or NULL)
|
* @param[in] xe Request: <rpc><xn></rpc> (or NULL)
|
||||||
* @param[in] db A candidate database, not necessarily "candidate"
|
* @param[in] db A candidate database, not necessarily "candidate"
|
||||||
* @param[in] myid Client id of triggering incoming message (or 0)
|
* @param[in] myid Client id of triggering incoming message (or 0)
|
||||||
|
* @param[in] vlev Validation level (0: full validation)
|
||||||
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. (if retval = 0)
|
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error.. (if retval = 0)
|
||||||
* @retval 1 Validation OK
|
* @retval 1 Validation OK
|
||||||
* @retval 0 Validation failed (with cbret set)
|
* @retval 0 Validation failed (with cbret set)
|
||||||
|
|
@ -658,6 +659,7 @@ candidate_commit(clicon_handle h,
|
||||||
cxobj *xe,
|
cxobj *xe,
|
||||||
char *db,
|
char *db,
|
||||||
uint32_t myid,
|
uint32_t myid,
|
||||||
|
validate_level vlev,
|
||||||
cbuf *cbret)
|
cbuf *cbret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -666,15 +668,22 @@ candidate_commit(clicon_handle h,
|
||||||
cxobj *xret = NULL;
|
cxobj *xret = NULL;
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
|
|
||||||
/* 1. Start transaction */
|
/* 1. Start transaction */
|
||||||
if ((td = transaction_new()) == NULL)
|
if ((td = transaction_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* 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 = validate_common(h, db, td, &xret)) < 0)
|
switch (vlev){
|
||||||
goto done;
|
case VL_FULL:
|
||||||
|
if ((ret = validate_common(h, db, td, &xret)) < 0)
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the confirmed-commit feature is enabled, execute phase 2:
|
/* If the confirmed-commit feature is enabled, execute phase 2:
|
||||||
* - If a valid confirming-commit, cancel the rollback event
|
* - If a valid confirming-commit, cancel the rollback event
|
||||||
|
|
@ -703,51 +712,51 @@ candidate_commit(clicon_handle h,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 7. Call plugin transaction commit callbacks */
|
/* 7. Call plugin transaction commit callbacks */
|
||||||
if (plugin_transaction_commit_all(h, td) < 0)
|
if (plugin_transaction_commit_all(h, td) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* After commit, make a post-commit call (sure that all plugins have committed) */
|
/* After commit, make a post-commit call (sure that all plugins have committed) */
|
||||||
if (plugin_transaction_commit_done_all(h, td) < 0)
|
if (plugin_transaction_commit_done_all(h, td) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Clear cached trees from default values and marking */
|
/* Clear cached trees from default values and marking */
|
||||||
if (xmldb_get0_clear(h, td->td_target) < 0)
|
if (xmldb_get0_clear(h, td->td_target) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xmldb_get0_clear(h, td->td_src) < 0)
|
if (xmldb_get0_clear(h, td->td_src) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* 8. Success: Copy candidate to running
|
/* 8. Success: Copy candidate to running
|
||||||
*/
|
*/
|
||||||
if (xmldb_copy(h, db, "running") < 0)
|
if (xmldb_copy(h, db, "running") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
xmldb_modified_set(h, db, 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;
|
||||||
free(td->td_dvec);
|
free(td->td_dvec);
|
||||||
td->td_dvec = NULL;
|
td->td_dvec = NULL;
|
||||||
}
|
}
|
||||||
if (td->td_scvec){
|
if (td->td_scvec){
|
||||||
free(td->td_scvec);
|
free(td->td_scvec);
|
||||||
td->td_scvec = NULL;
|
td->td_scvec = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 9. Call plugin transaction end callbacks */
|
/* 9. Call plugin transaction end callbacks */
|
||||||
plugin_transaction_end_all(h, td);
|
plugin_transaction_end_all(h, td);
|
||||||
|
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
/* In case of failure (or error), call plugin transaction termination callbacks */
|
/* In case of failure (or error), call plugin transaction termination callbacks */
|
||||||
if (td){
|
if (td){
|
||||||
if (retval < 1)
|
if (retval < 1)
|
||||||
plugin_transaction_abort_all(h, td);
|
plugin_transaction_abort_all(h, td);
|
||||||
xmldb_get0_free(h, &td->td_target);
|
xmldb_get0_free(h, &td->td_target);
|
||||||
xmldb_get0_free(h, &td->td_src);
|
xmldb_get0_free(h, &td->td_src);
|
||||||
transaction_free(td);
|
transaction_free(td);
|
||||||
}
|
}
|
||||||
if (xret)
|
if (xret)
|
||||||
xml_free(xret);
|
xml_free(xret);
|
||||||
return retval;
|
return retval;
|
||||||
fail:
|
fail:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -818,7 +827,7 @@ from_client_commit(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
if ((ret = candidate_commit(h, xe, "candidate", myid, cbret)) < 0){ /* Assume validation fail, nofatal */
|
if ((ret = candidate_commit(h, xe, "candidate", myid, VL_FULL, cbret)) < 0){ /* Assume validation fail, nofatal */
|
||||||
clicon_debug(1, "Commit candidate failed");
|
clicon_debug(1, "Commit candidate failed");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
if (netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
|
if (netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
|
||||||
|
|
@ -1085,7 +1094,7 @@ load_failsafe(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
if (xmldb_db_reset(h, "running") < 0)
|
if (xmldb_db_reset(h, "running") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
ret = candidate_commit(h, NULL, db, 0, cbret);
|
ret = candidate_commit(h, NULL, db, 0, VL_FULL, cbret);
|
||||||
if (ret != 1)
|
if (ret != 1)
|
||||||
if (xmldb_copy(h, "tmp", "running") < 0)
|
if (xmldb_copy(h, "tmp", "running") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -653,7 +653,7 @@ do_rollback(clicon_handle h,
|
||||||
confirmed_commit_persist_id_set(h, NULL);
|
confirmed_commit_persist_id_set(h, NULL);
|
||||||
}
|
}
|
||||||
confirmed_commit_state_set(h, ROLLBACK);
|
confirmed_commit_state_set(h, ROLLBACK);
|
||||||
if (candidate_commit(h, NULL, "rollback", 0, cbret) < 0) { /* Assume validation fail, nofatal */
|
if (candidate_commit(h, NULL, "rollback", 0, VL_FULL, cbret) < 0) { /* Assume validation fail, nofatal */
|
||||||
/* theoretically, this should never error, since the rollback database was previously active and therefore
|
/* theoretically, this should never error, since the rollback database was previously active and therefore
|
||||||
* had itself been previously and successfully committed.
|
* had itself been previously and successfully committed.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,8 @@ int from_client_confirmed_commit(clicon_handle h, cxobj *xe, uint32_t myid, cbuf
|
||||||
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_validate(clicon_handle h, char *db, cbuf *cbret);
|
||||||
int candidate_commit(clicon_handle h, cxobj *xe, char *db, uint32_t myid, cbuf *cbret);
|
int candidate_commit(clicon_handle h, cxobj *xe, char *db, uint32_t myid,
|
||||||
|
validate_level vlev, 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);
|
||||||
int from_client_discard_changes(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
|
int from_client_discard_changes(clicon_handle h, cxobj *xe, cbuf *cbret, void *arg, void *regarg);
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,16 @@
|
||||||
#ifndef _CLIXON_VALIDATE_H_
|
#ifndef _CLIXON_VALIDATE_H_
|
||||||
#define _CLIXON_VALIDATE_H_
|
#define _CLIXON_VALIDATE_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types
|
||||||
|
*/
|
||||||
|
/* Validation level at commit */
|
||||||
|
enum validate_level_t {
|
||||||
|
VL_FULL = 0, /* Do full RFC 7950 validation , 0 : backward-compatible */
|
||||||
|
VL_NONE, /* Do not do any validation */
|
||||||
|
};
|
||||||
|
typedef enum validate_level_t validate_level;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@
|
||||||
yang_stmt *yang_parse_file(FILE *fp, const char *name, yang_stmt *ysp);
|
yang_stmt *yang_parse_file(FILE *fp, const char *name, yang_stmt *ysp);
|
||||||
int yang_file_find_match(clicon_handle h, const char *module, const char *revision, cbuf *fbuf);
|
int yang_file_find_match(clicon_handle h, const char *module, const char *revision, cbuf *fbuf);
|
||||||
yang_stmt *yang_parse_filename(const char *filename, yang_stmt *ysp);
|
yang_stmt *yang_parse_filename(const char *filename, yang_stmt *ysp);
|
||||||
|
yang_stmt *yang_parse_module(clicon_handle h, const char *module, const char *revision, yang_stmt *yspec, char *origname);
|
||||||
int yang_parse_post(clicon_handle h, yang_stmt *yspec, int modmin);
|
int yang_parse_post(clicon_handle h, yang_stmt *yspec, int modmin);
|
||||||
int yang_spec_parse_module(clicon_handle h, const char *module,
|
int yang_spec_parse_module(clicon_handle h, const char *module,
|
||||||
const char *revision, yang_stmt *yspec);
|
const char *revision, yang_stmt *yspec);
|
||||||
|
|
|
||||||
|
|
@ -50,11 +50,6 @@
|
||||||
*/
|
*/
|
||||||
#define YANG_SCHEMA_MOUNT_ONLY_PRESENCE_CONTAINERS
|
#define YANG_SCHEMA_MOUNT_ONLY_PRESENCE_CONTAINERS
|
||||||
|
|
||||||
/*! Force add ietf-yang-library@2019-01-04 on all mount-points
|
|
||||||
* This is a limitation of othe current implementation
|
|
||||||
*/
|
|
||||||
#define YANG_SCHEMA_MOUNT_YANG_LIB_FORCE
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@
|
||||||
#include "clixon_xpath.h"
|
#include "clixon_xpath.h"
|
||||||
#include "clixon_yang_module.h"
|
#include "clixon_yang_module.h"
|
||||||
#include "clixon_yang_type.h"
|
#include "clixon_yang_type.h"
|
||||||
|
#include "clixon_yang_schema_mount.h"
|
||||||
#include "clixon_xml_default.h"
|
#include "clixon_xml_default.h"
|
||||||
#include "clixon_xml_map.h"
|
#include "clixon_xml_map.h"
|
||||||
#include "clixon_xml_bind.h"
|
#include "clixon_xml_bind.h"
|
||||||
|
|
@ -1007,6 +1008,15 @@ xml_yang_validate_add(clicon_handle h,
|
||||||
cg_var *cv0;
|
cg_var *cv0;
|
||||||
enum cv_type cvtype;
|
enum cv_type cvtype;
|
||||||
|
|
||||||
|
#ifdef YANG_SCHEMA_MOUNT
|
||||||
|
/* Do not validate beyond mountpoints */
|
||||||
|
if ((ret = xml_yang_mount_get(xt, NULL)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 1){
|
||||||
|
retval = 1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* if not given by argument (overide) use default link
|
/* if not given by argument (overide) use default link
|
||||||
and !Node has a config sub-statement and it is false */
|
and !Node has a config sub-statement and it is false */
|
||||||
if ((yt = xml_spec(xt)) != NULL && yang_config(yt) != 0){
|
if ((yt = xml_spec(xt)) != NULL && yang_config(yt) != 0){
|
||||||
|
|
@ -1215,6 +1225,13 @@ xml_yang_validate_all(clicon_handle h,
|
||||||
cvec *nsc = NULL;
|
cvec *nsc = NULL;
|
||||||
int hit = 0;
|
int hit = 0;
|
||||||
|
|
||||||
|
#ifdef YANG_SCHEMA_MOUNT
|
||||||
|
/* Do not validate beyond mountpoints */
|
||||||
|
if ((ret = xml_yang_mount_get(xt, NULL)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ret == 1)
|
||||||
|
goto ok;
|
||||||
|
#endif
|
||||||
/* if not given by argument (overide) use default link
|
/* if not given by argument (overide) use default link
|
||||||
and !Node has a config sub-statement and it is false */
|
and !Node has a config sub-statement and it is false */
|
||||||
if ((yt = xml_spec(xt)) == NULL){
|
if ((yt = xml_spec(xt)) == NULL){
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,11 @@
|
||||||
#include "clixon_xml_map.h"
|
#include "clixon_xml_map.h"
|
||||||
#include "clixon_yang_parse_lib.h"
|
#include "clixon_yang_parse_lib.h"
|
||||||
|
|
||||||
|
/*! Force add ietf-yang-library@2019-01-04 on all mount-points
|
||||||
|
* This is a limitation of othe current implementation
|
||||||
|
*/
|
||||||
|
#define YANG_SCHEMA_MOUNT_YANG_LIB_FORCE
|
||||||
|
|
||||||
/*! Create modstate structure
|
/*! Create modstate structure
|
||||||
*
|
*
|
||||||
* @retval md modstate struct
|
* @retval md modstate struct
|
||||||
|
|
@ -826,10 +831,10 @@ yang_metadata_init(clicon_handle h)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Given a yang-lib module-set XML tree, parse all modules into an yspec
|
/*! Given yang-lib module-set XML tree, parse all modules into an yspec
|
||||||
*
|
*
|
||||||
* This function is used where a yang-lib module-set is available to populate an
|
* This function is used where a yang-lib module-set is available to populate
|
||||||
* XML mount-point.
|
* an XML mount-point.
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] xylib yang-lib XML tree on the form <yang-lib>...
|
* @param[in] xylib yang-lib XML tree on the form <yang-lib>...
|
||||||
* @param[in] yspec Will be populated with YANGs, is consumed
|
* @param[in] yspec Will be populated with YANGs, is consumed
|
||||||
|
|
@ -860,14 +865,16 @@ yang_lib2yspec(clicon_handle h,
|
||||||
continue;
|
continue;
|
||||||
if ((revision = xml_find_body(xi, "revision")) == NULL)
|
if ((revision = xml_find_body(xi, "revision")) == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (yang_spec_parse_module(h, name, revision, yspec) < 0)
|
if (yang_parse_module(h, name, revision, yspec, NULL) == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
#ifdef YANG_SCHEMA_MOUNT_YANG_LIB_FORCE
|
#ifdef YANG_SCHEMA_MOUNT_YANG_LIB_FORCE
|
||||||
/* XXX: Ensure yang-lib is always there otherwise get state dont work for mountpoint */
|
/* XXX: Ensure yang-lib is always there otherwise get state dont work for mountpoint */
|
||||||
if (yang_spec_parse_module(h, "ietf-yang-library", "2019-01-04", yspec) < 0)
|
if (yang_parse_module(h, "ietf-yang-library", "2019-01-04", yspec, NULL) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
#endif
|
#endif
|
||||||
|
if (yang_parse_post(h, yspec, 0) < 0)
|
||||||
|
goto done;
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
if (vec)
|
if (vec)
|
||||||
|
|
|
||||||
|
|
@ -1059,7 +1059,7 @@ yang_parse_filename(const char *filename,
|
||||||
*
|
*
|
||||||
* See top of file for diagram of calling order
|
* See top of file for diagram of calling order
|
||||||
*/
|
*/
|
||||||
static yang_stmt *
|
yang_stmt *
|
||||||
yang_parse_module(clicon_handle h,
|
yang_parse_module(clicon_handle h,
|
||||||
const char *module,
|
const char *module,
|
||||||
const char *revision,
|
const char *revision,
|
||||||
|
|
|
||||||
|
|
@ -459,11 +459,6 @@ yang_schema_yanglib_parse_mount(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto anydata;
|
goto anydata;
|
||||||
#ifdef YANG_SCHEMA_MOUNT_YANG_LIB_FORCE
|
|
||||||
/* XXX: Ensure yang-lib is always there otherwise get state dont work for mountpoint */
|
|
||||||
if (yang_spec_parse_module(h, "ietf-yang-library", "2019-01-04", yspec) < 0)
|
|
||||||
goto done;
|
|
||||||
#endif
|
|
||||||
if (xml_yang_mount_set(xt, yspec) < 0)
|
if (xml_yang_mount_set(xt, yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 1;
|
retval = 1;
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,7 @@ main(int argc,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (commit){
|
if (commit){
|
||||||
if ((ret = candidate_commit(h, NULL, database, 0, cb)) < 0)
|
if ((ret = candidate_commit(h, NULL, database, 0, VL_FULL, cb)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue