]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: mgmtd: add `changed` and `created` to edit-reply msg
authorChristian Hopps <chopps@labn.net>
Tue, 17 Sep 2024 06:27:31 +0000 (02:27 -0400)
committerChristian Hopps <chopps@labn.net>
Tue, 17 Sep 2024 09:31:00 +0000 (05:31 -0400)
- This is used for various return values in RESTCONF

Signed-off-by: Christian Hopps <chopps@labn.net>
lib/mgmt_msg_native.h
lib/northbound.c
lib/northbound.h
mgmtd/mgmt_fe_adapter.c
mgmtd/mgmt_fe_adapter.h
mgmtd/mgmt_txn.c

index 76a52658cdee751859e0b29237a977ee99853b70..ef03b66edc06285a94ac730f266b4d19b4564b4b 100644 (file)
@@ -383,11 +383,18 @@ _Static_assert(sizeof(struct mgmt_msg_edit) ==
 /**
  * struct mgmt_msg_edit_reply - frontend edit reply.
  *
- * @data: the xpath of the data node that was created.
+ * @changed: If true then changes in datastore resulted.
+ * @created: If true then object was newly created (non-existing before)
+ * @data: @vsplit values, second value may be zero len.
+ * @data: [0] the xpath of the data node that was created.
+ * @data: [1] Possible structured data to pass back to client (e.g., non-"error"
+ *        yang modeled error data).
  */
 struct mgmt_msg_edit_reply {
        struct mgmt_msg_header;
-       uint8_t resv2[8];
+       uint8_t changed;
+       uint8_t created;
+       uint8_t resv2[6];
 
        alignas(8) char data[];
 };
index 35d0596ed4e309488e0060656099a3d9dd981831..2dae21341e59780a3a7b0b8ae556475e37c24a87 100644 (file)
@@ -816,8 +816,9 @@ int nb_candidate_edit(struct nb_config *candidate, const struct nb_node *nb_node
 static int nb_candidate_edit_tree_add(struct nb_config *candidate,
                                      enum nb_operation operation,
                                      LYD_FORMAT format, const char *xpath,
-                                     const char *data, char *xpath_created,
-                                     char *errmsg, size_t errmsg_len)
+                                     const char *data, bool *created,
+                                     char *xpath_created, char *errmsg,
+                                     size_t errmsg_len)
 {
        struct lyd_node *tree = NULL;
        struct lyd_node *parent = NULL;
@@ -897,10 +898,18 @@ static int nb_candidate_edit_tree_add(struct nb_config *candidate,
        }
 
        /* check if the node already exists in candidate */
-       if (operation == NB_OP_CREATE_EXCL || operation == NB_OP_REPLACE) {
+       if (operation == NB_OP_CREATE || operation == NB_OP_MODIFY)
+               existing = yang_dnode_get(candidate->dnode, xpath_created);
+       else if (operation == NB_OP_CREATE_EXCL || operation == NB_OP_REPLACE) {
                existing = yang_dnode_get(candidate->dnode, xpath_created);
 
                /* if the existing node is implicit default, ignore */
+               /* Q: Is this correct for CREATE_EXCL which is supposed to error
+                * if the resouurce already exists? This is used by RESTCONF
+                * when processing the POST command, for example. RFC8040
+                * doesn't say POST fails if resource exists "unless it was a
+                * default".
+                */
                if (existing && (existing->flags & LYD_DEFAULT))
                        existing = NULL;
 
@@ -930,7 +939,7 @@ static int nb_candidate_edit_tree_add(struct nb_config *candidate,
                                 LYD_MERGE_DESTRUCT | LYD_MERGE_WITH_FLAGS);
        if (err) {
                /* if replace failed, restore the original node */
-               if (existing) {
+               if (existing && operation == NB_OP_REPLACE) {
                        if (root) {
                                /* Restoring the whole config. */
                                candidate->dnode = existing;
@@ -954,6 +963,8 @@ static int nb_candidate_edit_tree_add(struct nb_config *candidate,
                ret = NB_ERR;
                goto done;
        } else {
+               if (!existing)
+                       *created = true;
                /*
                 * Free existing node after replace.
                 * We're using `lyd_free_siblings` here to free the whole
@@ -961,7 +972,7 @@ static int nb_candidate_edit_tree_add(struct nb_config *candidate,
                 * siblings if it wasn't root, because the existing node
                 * was unlinked from the tree.
                 */
-               if (existing)
+               if (existing && operation == NB_OP_REPLACE)
                        lyd_free_siblings(existing);
 
                tree = NULL; /* LYD_MERGE_DESTRUCT deleted the tree */
@@ -1011,7 +1022,7 @@ static int nb_candidate_edit_tree_del(struct nb_config *candidate,
 
 int nb_candidate_edit_tree(struct nb_config *candidate,
                           enum nb_operation operation, LYD_FORMAT format,
-                          const char *xpath, const char *data,
+                          const char *xpath, const char *data, bool *created,
                           char *xpath_created, char *errmsg, size_t errmsg_len)
 {
        int ret = NB_ERR;
@@ -1022,8 +1033,9 @@ int nb_candidate_edit_tree(struct nb_config *candidate,
        case NB_OP_MODIFY:
        case NB_OP_REPLACE:
                ret = nb_candidate_edit_tree_add(candidate, operation, format,
-                                                xpath, data, xpath_created,
-                                                errmsg, errmsg_len);
+                                                xpath, data, created,
+                                                xpath_created, errmsg,
+                                                errmsg_len);
                break;
        case NB_OP_DESTROY:
        case NB_OP_DELETE:
index b311affa31f8700b3b7601efeebd9550ca5e6219..b2cccb67163e8ab55ef99cfe9d90b6663fea93ff 100644 (file)
@@ -1016,6 +1016,9 @@ extern int nb_candidate_edit(struct nb_config *candidate,
  * data
  *    New data tree for the node.
  *
+ * created
+ *    OUT param set accordingly if a node was created or just updated
+ *
  * xpath_created
  *    XPath of the created node if operation is "create".
  *
@@ -1030,9 +1033,9 @@ extern int nb_candidate_edit(struct nb_config *candidate,
  *    - NB_ERR for other errors.
  */
 extern int nb_candidate_edit_tree(struct nb_config *candidate,
-                                 enum nb_operation operation,
-                                 LYD_FORMAT format, const char *xpath,
-                                 const char *data, char *xpath_created,
+                                 enum nb_operation operation, LYD_FORMAT format,
+                                 const char *xpath, const char *data,
+                                 bool *created, char *xpath_created,
                                  char *errmsg, size_t errmsg_len);
 
 /*
index 8ab66de6875dfd2e46394b4d61d4edf8302a2e95..8d305ed52fd22bace5824d818e1bda2c68d99a46 100644 (file)
@@ -1164,7 +1164,9 @@ done:
 }
 
 static int fe_adapter_send_edit_reply(struct mgmt_fe_session_ctx *session,
-                                     uint64_t req_id, const char *xpath)
+                                     uint64_t req_id, bool changed,
+                                     bool created, const char *xpath,
+                                     const char *data)
 {
        struct mgmt_msg_edit_reply *msg;
        int ret;
@@ -1173,14 +1175,19 @@ static int fe_adapter_send_edit_reply(struct mgmt_fe_session_ctx *session,
                                        MTYPE_MSG_NATIVE_EDIT_REPLY);
        msg->refer_id = session->session_id;
        msg->req_id = req_id;
+       msg->changed = changed;
+       msg->created = created;
        msg->code = MGMT_MSG_CODE_EDIT_REPLY;
 
        mgmt_msg_native_xpath_encode(msg, xpath);
 
+       if (data)
+               mgmt_msg_native_append(msg, data, strlen(data) + 1);
+
        __dbg("Sending edit-reply from adapter %s to session-id %" PRIu64
-             " req-id %" PRIu64 " len %u",
-             session->adapter->name, session->session_id, req_id,
-             mgmt_msg_native_get_msg_len(msg));
+             " req-id %" PRIu64 " changed %u created %u len %u",
+             session->adapter->name, session->session_id, req_id, changed,
+             created, mgmt_msg_native_get_msg_len(msg));
 
        ret = fe_adapter_send_native_msg(session->adapter, msg,
                                         mgmt_msg_native_get_msg_len(msg),
@@ -1977,8 +1984,8 @@ int mgmt_fe_adapter_send_rpc_reply(uint64_t session_id, uint64_t txn_id,
 
 int mgmt_fe_adapter_send_edit_reply(uint64_t session_id, uint64_t txn_id,
                                    uint64_t req_id, bool unlock, bool commit,
-                                   const char *xpath, int16_t error,
-                                   const char *errstr)
+                                   bool created, const char *xpath,
+                                   int16_t error, const char *errstr)
 {
        struct mgmt_fe_session_ctx *session;
        Mgmtd__DatastoreId ds_id, rds_id;
@@ -2009,11 +2016,12 @@ int mgmt_fe_adapter_send_edit_reply(uint64_t session_id, uint64_t txn_id,
                }
        }
 
-       if (error)
+       if (error != 0 && error != -EALREADY)
                ret = fe_adapter_send_error(session, req_id, false, error, "%s",
                                            errstr);
        else
-               ret = fe_adapter_send_edit_reply(session, req_id, xpath);
+               ret = fe_adapter_send_edit_reply(session, req_id, created,
+                                                !error, xpath, errstr);
 
        if (session->cfg_txn_id != MGMTD_TXN_ID_NONE && !commit)
                mgmt_destroy_txn(&session->cfg_txn_id);
index 5a7dec3e6ff765bf8b995dc3a9c1e0dffa4b5c8d..4d94e7604f6e93e393622200aa6517f754e4628b 100644 (file)
@@ -193,14 +193,16 @@ extern int mgmt_fe_adapter_send_rpc_reply(uint64_t session_id, uint64_t txn_id,
  *     req_id: the req id for the edit message
  *     unlock: implicit-lock flag was set in the request
  *     commit: implicit-commit flag was set in the request
- *     xpath: the xpath of the data node that was created
+ *     created: true if the node was just created
+ *     xpath: the xpath of the data node that was created/updated
  *     error: >0 LY_ERR, < 0 -errno
  *     errstr: the error string, if error is non-zero
  */
 extern int mgmt_fe_adapter_send_edit_reply(uint64_t session_id, uint64_t txn_id,
                                           uint64_t req_id, bool unlock,
-                                          bool commit, const char *xpath,
-                                          int16_t error, const char *errstr);
+                                          bool commit, bool created,
+                                          const char *xpath, int16_t error,
+                                          const char *errstr);
 
 /**
  * Send an error back to the FE client using native messaging.
index 53d9f5c3fabf38cb90d76f0942ed4acb0672cb57..ccfdd7539f8113bbdbdd5fca098198ce7a8745c2 100644 (file)
@@ -94,6 +94,7 @@ DECLARE_LIST(mgmt_txn_batches, struct mgmt_txn_be_cfg_batch, list_linkage);
 
 struct mgmt_edit_req {
        char xpath_created[XPATH_MAXLEN];
+       bool created;
        bool unlock;
 };
 
@@ -741,6 +742,8 @@ static int mgmt_txn_send_commit_cfg_reply(struct mgmt_txn_ctx *txn,
                                            txn->commit_cfg_req->req.commit_cfg
                                                    .edit->unlock,
                                            true,
+                                           txn->commit_cfg_req->req.commit_cfg
+                                                   .edit->created,
                                            txn->commit_cfg_req->req.commit_cfg
                                                    .edit->xpath_created,
                                            success ? 0 : -1,
@@ -2566,8 +2569,8 @@ int mgmt_txn_send_edit(uint64_t txn_id, uint64_t req_id,
        assert(nb_config);
 
        ret = nb_candidate_edit_tree(nb_config, operation, request_type, xpath,
-                                    data, edit->xpath_created, errstr,
-                                    sizeof(errstr));
+                                    data, &edit->created, edit->xpath_created,
+                                    errstr, sizeof(errstr));
        if (ret)
                goto reply;
 
@@ -2581,7 +2584,8 @@ int mgmt_txn_send_edit(uint64_t txn_id, uint64_t req_id,
        }
 reply:
        mgmt_fe_adapter_send_edit_reply(txn->session_id, txn->txn_id, req_id,
-                                       unlock, commit, edit->xpath_created,
+                                       unlock, commit, edit->created,
+                                       edit->xpath_created,
                                        errno_from_nb_error(ret), errstr);
 
        XFREE(MTYPE_MGMTD_TXN_REQ, edit);