Currently, there's no difference between CREATE and MODIFY operations.
To be compatible with NETCONF/RESTCONF, add new CREATE_EXCL operation
that throws an error if the configuration data already exists.
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
REQ_TYPE_NONE = 0;
SET_DATA = 1;
DELETE_DATA = 2;
+ CREATE_DATA = 3;
}
message YangCfgDataReq {
== MGMTD__CFG_DATA_REQ_TYPE__DELETE_DATA)
cfg_chg->operation = NB_OP_DESTROY;
else
- cfg_chg->operation = NB_OP_CREATE;
+ cfg_chg->operation = NB_OP_MODIFY;
strlcpy(cfg_chg->xpath, cfg_req[index]->data->xpath,
sizeof(cfg_chg->xpath));
struct lyd_node *dnode, *dep_dnode;
char xpath_edit[XPATH_MAXLEN];
char dep_xpath[XPATH_MAXLEN];
+ uint32_t options = 0;
LY_ERR err;
/* Use special notation for leaf-lists (RFC 6020, section 9.13.5). */
switch (operation) {
case NB_OP_CREATE:
case NB_OP_MODIFY:
+ options = LYD_NEW_PATH_UPDATE;
+ fallthrough;
+ case NB_OP_CREATE_EXCL:
err = lyd_new_path(candidate->dnode, ly_native_ctx, xpath_edit,
- (void *)data->value, LYD_NEW_PATH_UPDATE,
- &dnode);
+ (void *)data->value, options, &dnode);
if (err) {
flog_warn(EC_LIB_LIBYANG,
"%s: lyd_new_path(%s) failed: %d", __func__,
const char *nb_operation_name(enum nb_operation operation)
{
switch (operation) {
+ case NB_OP_CREATE_EXCL:
+ return "create exclusive";
case NB_OP_CREATE:
return "create";
case NB_OP_MODIFY:
/* Northbound operations */
enum nb_operation {
+ NB_OP_CREATE_EXCL,
NB_OP_CREATE,
NB_OP_MODIFY,
NB_OP_DESTROY,
MGMTD__CFG_DATA_REQ_TYPE__DELETE_DATA;
break;
+ case NB_OP_CREATE_EXCL:
+ cfg_req[indx].req_type =
+ MGMTD__CFG_DATA_REQ_TYPE__CREATE_DATA;
+ break;
+
case NB_OP_CREATE:
case NB_OP_MODIFY:
case NB_OP_MOVE:
batch->cfg_datap[batch->num_cfg_data] =
&batch->cfg_data[batch->num_cfg_data];
+ /*
+ * On the backend, we don't really care if it's CREATE
+ * or MODIFY, because the existence was already checked
+ * on the frontend. Therefore we use SET for both.
+ */
if (chg->cb.operation == NB_CB_DESTROY)
batch->cfg_data[batch->num_cfg_data].req_type =
MGMTD__CFG_DATA_REQ_TYPE__DELETE_DATA;
size_t indx;
uint16_t *num_chgs;
struct nb_cfg_change *cfg_chg;
+ struct nb_node *node;
txn = mgmt_txn_id2ctx(txn_id);
if (!txn)
for (indx = 0; indx < num_req; indx++) {
cfg_chg = &txn_req->req.set_cfg->cfg_changes[*num_chgs];
- if (cfg_req[indx]->req_type ==
- MGMTD__CFG_DATA_REQ_TYPE__DELETE_DATA)
+ switch (cfg_req[indx]->req_type) {
+ case MGMTD__CFG_DATA_REQ_TYPE__DELETE_DATA:
cfg_chg->operation = NB_OP_DESTROY;
- else if (cfg_req[indx]->req_type ==
- MGMTD__CFG_DATA_REQ_TYPE__SET_DATA)
- cfg_chg->operation =
- mgmt_ds_find_data_node_by_xpath(ds_ctx,
- cfg_req[indx]
- ->data
- ->xpath)
- ? NB_OP_MODIFY
- : NB_OP_CREATE;
- else
+ break;
+ case MGMTD__CFG_DATA_REQ_TYPE__SET_DATA:
+ /*
+ * For backward compatibility, we need to allow creating
+ * *new* list keys with SET_DATA operation. NB_OP_MODIFY
+ * is not allowed for keys, so use NB_OP_CREATE_EXCL.
+ */
+ node = nb_node_find(cfg_req[indx]->data->xpath);
+ if (node && lysc_is_key(node->snode))
+ cfg_chg->operation = NB_OP_CREATE_EXCL;
+ else
+ cfg_chg->operation = NB_OP_MODIFY;
+ break;
+ case MGMTD__CFG_DATA_REQ_TYPE__CREATE_DATA:
+ cfg_chg->operation = NB_OP_CREATE_EXCL;
+ break;
+ case MGMTD__CFG_DATA_REQ_TYPE__REQ_TYPE_NONE:
+ case _MGMTD__CFG_DATA_REQ_TYPE_IS_INT_SIZE:
+ default:
continue;
+ }
MGMTD_TXN_DBG("XPath: '%s', Value: '%s'",
cfg_req[indx]->data->xpath,
return CMD_SUCCESS;
}
+DEFPY(mgmt_create_config_data, mgmt_create_config_data_cmd,
+ "mgmt create-config WORD$path VALUE",
+ MGMTD_STR
+ "Create configuration data\n"
+ "XPath expression specifying the YANG data path\n"
+ "Value of the data to create\n")
+{
+ strlcpy(vty->cfg_changes[0].xpath, path,
+ sizeof(vty->cfg_changes[0].xpath));
+ vty->cfg_changes[0].value = value;
+ vty->cfg_changes[0].operation = NB_OP_CREATE_EXCL;
+ vty->num_cfg_changes = 1;
+
+ vty_mgmt_send_config_data(vty, NULL, false);
+ return CMD_SUCCESS;
+}
+
DEFPY(mgmt_set_config_data, mgmt_set_config_data_cmd,
"mgmt set-config WORD$path VALUE",
MGMTD_STR
strlcpy(vty->cfg_changes[0].xpath, path,
sizeof(vty->cfg_changes[0].xpath));
vty->cfg_changes[0].value = value;
- vty->cfg_changes[0].operation = NB_OP_CREATE;
+ vty->cfg_changes[0].operation = NB_OP_MODIFY;
vty->num_cfg_changes = 1;
vty_mgmt_send_config_data(vty, NULL, false);
install_element(VIEW_NODE, &show_mgmt_cmt_hist_cmd);
install_element(CONFIG_NODE, &mgmt_commit_cmd);
+ install_element(CONFIG_NODE, &mgmt_create_config_data_cmd);
install_element(CONFIG_NODE, &mgmt_set_config_data_cmd);
install_element(CONFIG_NODE, &mgmt_delete_config_data_cmd);
install_element(CONFIG_NODE, &mgmt_load_config_cmd);