Confirm-commit RESTCONF support
This commit is contained in:
parent
1eb78a78f8
commit
6f0bd01a6a
6 changed files with 108 additions and 47 deletions
|
|
@ -455,19 +455,34 @@ from_client_edit_config(clicon_handle h,
|
|||
autocommit = 1;
|
||||
/* If autocommit option is set or requested by client */
|
||||
if (clicon_autocommit(h) || autocommit) {
|
||||
// TODO: if this is from a restconf client ...
|
||||
// and, if there is an existing ephemeral commit, set is_valid_confirming_commit=1 such that
|
||||
// candidate_commit will apply the configuration per RFC 8040 1.4:
|
||||
// If a confirmed commit procedure is
|
||||
// in progress by any NETCONF client, then any new commit will act as
|
||||
// the confirming commit.
|
||||
// and, if there is an existing persistent commit, netconf_operation_failed with "in-use", so
|
||||
// that the restconf server will return "409 Conflict" per RFC 8040 1.4:
|
||||
// If the NETCONF server is expecting a
|
||||
// "persist-id" parameter to complete the confirmed commit procedure,
|
||||
// then the RESTCONF edit operation MUST fail with a "409 Conflict"
|
||||
// status-line. The error-tag "in-use" is used in this case.
|
||||
|
||||
/* if this is from a restconf client ...
|
||||
* and, if there is an existing ephemeral commit, set is_valid_confirming_commit=1 such that
|
||||
* candidate_commit will apply the configuration per RFC 8040 1.4:
|
||||
* If a confirmed commit procedure is
|
||||
* in progress by any NETCONF client, then any new commit will act as
|
||||
* the confirming commit.
|
||||
* and, if there is an existing persistent commit, netconf_operation_failed with "in-use", so
|
||||
* that the restconf server will return "409 Conflict" per RFC 8040 1.4:
|
||||
* If the NETCONF server is expecting a
|
||||
* "persist-id" parameter to complete the confirmed commit procedure,
|
||||
* then the RESTCONF edit operation MUST fail with a "409 Conflict"
|
||||
* status-line. The error-tag "in-use" is used in this case.
|
||||
*/
|
||||
if (if_feature(yspec, "ietf-netconf", "confirmed-commit")) {
|
||||
switch (confirmed_commit.state){
|
||||
case INACTIVE:
|
||||
break;
|
||||
case PERSISTENT:
|
||||
if (netconf_in_use(cbret, "application", "Persistent commit is ongoing")< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
break;
|
||||
case EPHEMERAL:
|
||||
case ROLLBACK:
|
||||
cancel_confirmed_commit(h);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((ret = candidate_commit(h, "candidate", cbret)) < 0){ /* Assume validation fail, nofatal */
|
||||
if (netconf_operation_failed(cbret, "application", clicon_err_reason)< 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -648,7 +648,7 @@ candidate_validate(clicon_handle h,
|
|||
* @retval -1 No Rollback event was found
|
||||
*/
|
||||
int
|
||||
cancel_rollback_event()
|
||||
cancel_rollback_event(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
|
|
@ -723,6 +723,28 @@ schedule_rollback_event(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Cancel a confirming commit by removing rollback, and free state
|
||||
* @param[in] h
|
||||
* @param[out] cbret
|
||||
* @retval 0 OK
|
||||
*/
|
||||
int
|
||||
cancel_confirmed_commit(clicon_handle h)
|
||||
{
|
||||
cancel_rollback_event();
|
||||
|
||||
if (confirmed_commit.state == PERSISTENT && confirmed_commit.persist_id != NULL) {
|
||||
free(confirmed_commit.persist_id);
|
||||
confirmed_commit.persist_id = NULL;
|
||||
}
|
||||
|
||||
confirmed_commit.state = INACTIVE;
|
||||
|
||||
if (xmldb_delete(h, "rollback") < 0)
|
||||
clicon_err(OE_DB, 0, "Error deleting the rollback configuration");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Handle the second phase of confirmed-commit processing.
|
||||
*
|
||||
* In the first phase, the proper action was taken in the case of a valid confirming-commit, but no subsequent
|
||||
|
|
@ -1211,20 +1233,8 @@ from_client_commit(clicon_handle h,
|
|||
/* If <confirmed/> is *not* present, this will conclude the confirmed-commit, so cancel the rollback. */
|
||||
if (xml_find_type(confirmed_commit.xe, NULL, "confirmed", CX_ELMNT) == NULL
|
||||
&& is_valid_confirming_commit) {
|
||||
cancel_rollback_event();
|
||||
|
||||
if (confirmed_commit.state == PERSISTENT && confirmed_commit.persist_id != NULL) {
|
||||
free(confirmed_commit.persist_id);
|
||||
confirmed_commit.persist_id = NULL;
|
||||
}
|
||||
|
||||
confirmed_commit.state = INACTIVE;
|
||||
|
||||
if (xmldb_delete(h, "rollback") < 0)
|
||||
clicon_err(OE_DB, 0, "Error deleting the rollback configuration");
|
||||
|
||||
cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", NETCONF_BASE_NAMESPACE);
|
||||
|
||||
cancel_confirmed_commit(h);
|
||||
cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", NETCONF_BASE_NAMESPACE);
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,13 +65,14 @@ struct confirmed_commit {
|
|||
void *arg; // the clicon_handle that will be passed to rollback_fn()
|
||||
};
|
||||
|
||||
extern struct confirmed_commit confirmed_commit;
|
||||
extern struct confirmed_commit confirmed_commit; // XXX global
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
int do_rollback(clicon_handle h, uint8_t *errs);
|
||||
int cancel_rollback_event();
|
||||
int cancel_rollback_event(void);
|
||||
int cancel_confirmed_commit(clicon_handle h);
|
||||
|
||||
int startup_validate(clicon_handle h, char *db, cxobj **xtr, cbuf *cbret);
|
||||
int startup_commit(clicon_handle h, char *db, cbuf *cbret);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue