mgmtd: validate candidate yang tree before creating a config diff

The candidate yang tree should be validated before `nb_config_diff` is
called. `nb_config_diff` ignores all prohibited operations and can
provide an empty change list because of this. For example, if a user
deletes a mandatory node from the candidate datastore and tries to make
a commit, they'll receive the "No changes found to be committed!" error,
because such a change is ignored by `nb_config_diff`. Instead, mgmtd
should tell the user that their candidate datastore is not valid and
can't be commited.

Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
This commit is contained in:
Igor Ryzhov 2023-11-14 20:17:24 +01:00
parent 4aff978cee
commit c81776c8e9

View File

@ -1034,6 +1034,23 @@ static int mgmt_txn_prepare_config(struct mgmt_txn_ctx *txn)
goto mgmt_txn_prepare_config_done;
}
/*
* Validate YANG contents of the source DS and get the diff
* between source and destination DS contents.
*/
char err_buf[BUFSIZ] = { 0 };
ret = nb_candidate_validate_yang(nb_config, true, err_buf,
sizeof(err_buf) - 1);
if (ret != NB_OK) {
if (strncmp(err_buf, " ", strlen(err_buf)) == 0)
strlcpy(err_buf, "Validation failed", sizeof(err_buf));
(void)mgmt_txn_send_commit_cfg_reply(txn, MGMTD_INVALID_PARAM,
err_buf);
ret = -1;
goto mgmt_txn_prepare_config_done;
}
nb_config_diff(mgmt_ds_get_nb_config(txn->commit_cfg_req->req.commit_cfg
.dst_ds_ctx),
nb_config, &changes);
@ -1056,29 +1073,13 @@ static int mgmt_txn_prepare_config(struct mgmt_txn_ctx *txn)
gettimeofday(&txn->commit_cfg_req->req.commit_cfg.cmt_stats
->validate_start,
NULL);
/*
* Validate YANG contents of the source DS and get the diff
* between source and destination DS contents.
*/
char err_buf[1024] = { 0 };
nb_ctx.client = NB_CLIENT_MGMTD_SERVER;
nb_ctx.user = (void *)txn;
ret = nb_candidate_validate_yang(nb_config, true, err_buf,
sizeof(err_buf) - 1);
if (ret != NB_OK) {
if (strncmp(err_buf, " ", strlen(err_buf)) == 0)
strlcpy(err_buf, "Validation failed", sizeof(err_buf));
(void)mgmt_txn_send_commit_cfg_reply(txn, MGMTD_INVALID_PARAM,
err_buf);
ret = -1;
goto mgmt_txn_prepare_config_done;
}
/*
* Perform application level validations locally on the MGMTD
* process by calling application specific validation routines
* loaded onto MGMTD process using libraries.
*/
nb_ctx.client = NB_CLIENT_MGMTD_SERVER;
nb_ctx.user = (void *)txn;
ret = nb_candidate_validate_code(&nb_ctx, nb_config, &changes, err_buf,
sizeof(err_buf) - 1);
if (ret != NB_OK) {