The following article describes and exemplifies the REPLACE operation in edit-config requests.



Operation Replace

Elements in the <config> subtree MAY contain an "operation" attribute. The attribute identifies the point in the configuration to perform the operation. If the "operation" attribute is specified to be Replace:


The configuration data identified by the element containing this attribute replaces any related configuration in the configuration datastore identified by the <target> parameter. If no such configuration data exists in the configuration datastore, it is created. Unlike a <copy-config> operation, which replaces the entire target configuration, only the configuration actually present in the <config> parameter is affected.


Default-operation Replace

If the default-operation is set to "replace" and a top-level data node within the <config> subtree does not have an nc:operation attribute, then the operation will be "replace" for that data node.

Only data nodes present in the <config> subtree can be replaced.


The <copy-config> operation must be used to replace all top-level nodes, and delete any nodes not present in the <config> subtree.



Usage


SIL code and YANG module are attached to this article.

YANG Data model

module defcont {
  namespace "http://netconfcentral.org/ns/example";
  prefix "defcont";

  container deftest0 {
    container deftest1 {
      list deftest2 {
        key "profile-name";

        leaf profile-name {
          type string;
        }

        leaf defc3 {
          type boolean;
          default "false";
        }

        container deftest3 {
          leaf defc4 {
            type boolean;
            default "false";
          }

          leaf defc5 {
            type boolean;
          }
        }
      }
    }
  }
}

Example 1: Replace on container "deftest1"


Before we replace any nodes, we are going to create two lists in the container by using the following edit-config:

<edit-config>
    <target>
      <candidate/>
    </target>
    <default-operation>merge</default-operation>
    <test-option>set</test-option>
    <config>
        <deftest0 xmlns="http://netconfcentral.org/ns/example">
            <deftest1>
                <deftest2>
                    <profile-name>first-list-name</profile-name>
                    <defc3>true</defc3>
                    <deftest3>
                        <defc4>true</defc4>
                        <defc5>false</defc5>
                    </deftest3>
                </deftest2>
                <deftest2>
                    <profile-name>second-list-name</profile-name>
                    <defc3>true</defc3>
                    <deftest3>
                        <defc4>false</defc4>
                        <defc5>true</defc5>
                    </deftest3>
                </deftest2>
            </deftest1>
      </deftest0>
    </config>
</edit-config>
Assume we are running netconfd-pro server with --target=candidate. Thus, after the above edit we need to run <commit> operation in order to apply all the changes that were done in the edit-config.


After the edits the running datastore may look as follows:


{
        "defcont:deftest0": {
            "deftest1": {
                "deftest2": [
                    {
                        "profile-name": "first-list-name",
                        "defc3": true,
                        "deftest3": {
                            "defc4": true,
                            "defc5": false
                        }
                    },
                    {
                        "profile-name": "second-list-name",
                        "defc3": true,
                        "deftest3": {
                            "defc4": false,
                            "defc5": true
                        }
                    }
                ]
            }
        }
}

Now, in order to demonstrate Replace operation the following <edit-config> request is used:

<edit-config>
    <target>
      <candidate/>
    </target>
    <config>
        <deftest0 xmlns="http://netconfcentral.org/ns/example"
                  xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
            <deftest1 nc:operation="replace">
                <deftest2>
                    <profile-name>new-first-list-name</profile-name>
                    <defc3>true</defc3>
                    <deftest3>
                        <defc4>false</defc4>
                        <defc5>true</defc5>
                    </deftest3>
                </deftest2>
            </deftest1>
      </deftest0>
    </config>
</edit-config>

As a result of this request and after <commit> operation the server will produce the following output, from the netconfd-pro server log:


***** start commit phase on running for session 10, transaction 1472337 *****

Start full commit of transaction 1472337: 1 edit on running config
Start invoking commit SIL callback for replace on defcont:deftest1
 (deftest1) Enter EDIT-2 callback
 ------PHASE:commit;EDITOP:replace

    newval deftest1 P:[0x7f19e0004150] :
          deftest1 {
            deftest2  new-first-list-name {
              profile-name new-first-list-name
              defc3 true
              deftest3 {
                defc4 false
                defc5 true
              }
            }
          }
    curval deftest1 P:[0x7f19e00030f0] :
          deftest1 {
            deftest2  first-list-name {
              profile-name first-list-name
              defc3 true
              deftest3 {
                defc4 true
                defc5 false
              }
            }
            deftest2  second-list-name {
              profile-name second-list-name
              defc3 true
              deftest3 {
                defc4 false
                defc5 true
              }
            }
          }
Finished invoking user callback on defcont:deftest1
Start invoking commit SIL callback for create on defcont:deftest2
 (deftest2) Enter EDIT-2 callback
 ------PHASE:commit;EDITOP:create

    newval deftest2 P:[0x7f19e0004220] :
          deftest2  new-first-list-name {
            profile-name new-first-list-name
            defc3 true
            deftest3 {
              defc4 false
              defc5 true
            }
          }
child Q of simple childs:   profile-name='new-first-list-name'
child Q of simple childs:   defc3='true'
    curval null P:[(nil)] :
Finished invoking user callback on defcont:deftest2
Start invoking commit SIL callback for create on defcont:deftest3
 (deftest3) Enter EDIT-2 callback
 ------PHASE:commit;EDITOP:create

    newval deftest3 P:[0x7f19e0004480] :
          deftest3 {
            defc4 false
            defc5 true
          }
child Q of simple childs:   defc4='false'
child Q of simple childs:   defc5='true'
    curval null P:[(nil)] :
Finished invoking user callback on defcont:deftest3
Start invoking commit SIL callback for delete on defcont:deftest2
 (deftest2) Enter EDIT-2 callback
 ------PHASE:commit;EDITOP:delete

    newval null P:[(nil)] :
    curval deftest2 P:[0x7f19e00031a0] :
          deftest2  first-list-name {
            profile-name first-list-name
            defc3 true
            deftest3 {
              defc4 true
              defc5 false
            }
          }
child Q of simple childs:   profile-name='first-list-name'
child Q of simple childs:   defc3='true'
Finished invoking user callback on defcont:deftest2
Start invoking commit SIL callback for delete on defcont:deftest2
 (deftest2) Enter EDIT-2 callback
 ------PHASE:commit;EDITOP:delete

    newval null P:[(nil)] :
    curval deftest2 P:[0x7f19e0003860] :
          deftest2  second-list-name {
            profile-name second-list-name
            defc3 true
            deftest3 {
              defc4 false
              defc5 true
            }
          }
child Q of simple childs:   profile-name='second-list-name'
child Q of simple childs:   defc3='true'
Finished invoking user callback on defcont:deftest2
edit-transaction 1472337: on session 10 by restconf@::1
  time: 2021-09-14T17:15:51Z
  message-id: --
  trace-id: --
  datastore: running
  operation: replace
  target: /defcont:deftest0/defcont:deftest1
  comment: none

Complete commit OK of transaction 1472337 on running database


To summarize the above log and the <edit-config> results, the server invokes the following callbacks:

- SIL callback for Replace on deftest1
- SIL callback for Create on deftest2
- SIL callback for Create on deftest3
- SIL callback for Delete on deftest2
- SIL callback for Delete on deftest2


Note: that the server in order to Replace resources, it deletes the old one and creates a new to ensure that the Replace is fully done.


Example 2: Replace on list "deftest2" (a new list replace)


Assume there are existing lists in the running datastore configurations that looks as follows:


{
        "defcont:deftest0": {
            "deftest1": {
                "deftest2": [
                    {
                        "profile-name": "first-list-name",
                        "defc3": true,
                        "deftest3": {
                            "defc4": true,
                            "defc5": false
                        }
                    },
                    {
                        "profile-name": "second-list-name",
                        "defc3": true,
                        "deftest3": {
                            "defc4": false,
                            "defc5": true
                        }
                    }
                ]
            }
        }
}

And now we are ready to run a replace operation on a list node as follows:


<edit-config>
    <target>
      <candidate/>
    </target>
    <config>
        <deftest0 xmlns="http://netconfcentral.org/ns/example"
                  xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
            <deftest1>
                <deftest2 nc:operation="replace">
                    <profile-name>new-first-list-name</profile-name>
                    <defc3>true</defc3>
                    <deftest3>
                        <defc4>false</defc4>
                        <defc5>true</defc5>
                    </deftest3>
                </deftest2>
            </deftest1>
      </deftest0>
    </config>
</edit-config>
Note that the Replace operation if done on a list entry that does not exist. As a result of this operation the netconfd-pro server will create this new entry since there is no any entries to replace it with.

As a result of the above operation the server will produce the following output:


***** start commit phase on running for session 6, transaction 1472342 *****

Start full commit of transaction 1472342: 1 edit on running config
Start invoking commit SIL callback for create on defcont:deftest2
 (deftest2) Enter EDIT-2 callback
 ------PHASE:commit;EDITOP:create

    newval deftest2 P:[0x7faf88003a20] :
          deftest2  new-first-list-name {
            profile-name new-first-list-name
            defc3 true
            deftest3 {
              defc4 false
              defc5 true
            }
          }
child Q of simple childs:   profile-name='new-first-list-name'
child Q of simple childs:   defc3='true'
    curval null P:[(nil)] :
Finished invoking user callback on defcont:deftest2
Start invoking commit SIL callback for create on defcont:deftest3
 (deftest3) Enter EDIT-2 callback
 ------PHASE:commit;EDITOP:create

    newval deftest3 P:[0x7faf88009630] :
          deftest3 {
            defc4 false
            defc5 true
          }
child Q of simple childs:   defc4='false'
child Q of simple childs:   defc5='true'
    curval null P:[(nil)] :
Finished invoking user callback on defcont:deftest3
edit-transaction 1472342: on session 6 by restconf@::1
  time: 2021-09-14T18:00:40Z
  message-id: --
  trace-id: --
  datastore: running
  operation: replace
  target: /defcont:deftest0/defcont:deftest1/defcont:deftest2[defcont:profile-name="new-first-list-name"]
  comment: none

Complete commit OK of transaction 1472342 on running database
To summarize the above log and the <edit-config> results, the server invokes the following callbacks:

- SIL callback for Create on deftest2
- SIL callback for Create on deftest3


Example 3: Replace on list "deftest2" (an existing list replace)

Now lets replace a list entry that already exist, assume we have the same configurations in the datastore and run the following <edit-config>:


<edit-config>
    <target>
      <candidate/>
    </target>
    <config>
        <deftest0 xmlns="http://netconfcentral.org/ns/example"
                  xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
            <deftest1>
                <deftest2 nc:operation="replace">
                    <profile-name>first-list-name</profile-name>
                    <defc3>false</defc3>
                    <deftest3>
                        <defc4>true</defc4>
                        <defc5>false</defc5>
                    </deftest3>
                </deftest2>
            </deftest1>
      </deftest0>
    </config>
</edit-config>


As a result of the above operation the server will produce the following output:


***** start commit phase on running for session 9, transaction 1472344 *****

Start full commit of transaction 1472344: 1 edit on running config
Start invoking commit SIL callback for replace on defcont:deftest2
 (deftest2) Enter EDIT-2 callback
 ------PHASE:commit;EDITOP:replace

    newval deftest2 P:[0x7faf8800af30] :
          deftest2  first-list-name {
            profile-name first-list-name
            defc3 false
            deftest3 {
              defc4 true
              defc5 false
            }
          }
child Q of simple childs:   profile-name='first-list-name'
child Q of simple childs:   defc3='false'
    curval deftest2 P:[0x7faf88003e30] :
          deftest2  first-list-name {
            profile-name first-list-name
            defc3 true
            deftest3 {
              defc4 true
              defc5 false
            }
          }
child Q of simple childs:   profile-name='first-list-name'
child Q of simple childs:   defc3='true'
Finished invoking user callback on defcont:deftest2
Start invoking commit SIL callback for replace on defcont:deftest3
 (deftest3) Enter EDIT-2 callback
 ------PHASE:commit;EDITOP:replace

    newval deftest3 P:[0x7faf8800b220] :
          deftest3 {
            defc4 true
            defc5 false
          }
child Q of simple childs:   defc4='true'
child Q of simple childs:   defc5='false'
    curval deftest3 P:[0x7faf88004100] :
          deftest3 {
            defc4 true
            defc5 false
          }
child Q of simple childs:   defc4='true'
child Q of simple childs:   defc5='false'
Finished invoking user callback on defcont:deftest3
edit-transaction 1472344: on session 9 by restconf@::1
  time: 2021-09-14T18:06:53Z
  message-id: --
  trace-id: --
  datastore: running
  operation: replace
  target: /defcont:deftest0/defcont:deftest1/defcont:deftest2[defcont:profile-name="first-list-name"]
  comment: none

Complete commit OK of transaction 1472344 on running database
To summarize the above log and the <edit-config> results, the server invokes the following callbacks:

- SIL callback for Replace on deftest2
- SIL callback for Replace on deftest3




Example 4: Replace on leafs


Assume there are existing lists with a leafs in the running datastore configurations that looks as follows:


{
        "defcont:deftest0": {
            "deftest1": {
                "deftest2": [
                    {
                        "profile-name": "first-list-name",
                        "defc3": true,
                        "deftest3": {
                            "defc4": true,
                            "defc5": false
                        }
                    },
                    {
                        "profile-name": "second-list-name",
                        "defc3": true,
                        "deftest3": {
                            "defc4": false,
                            "defc5": true
                        }
                    }
                ]
            }
        }
}


Now lets replace a leaf node inside a list entry by using the following <edit-config>:

<edit-config>
    <target>
      <candidate/>
    </target>
    <config>
        <deftest0 xmlns="http://netconfcentral.org/ns/example"
                  xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
            <deftest1>
                <deftest2>
                    <profile-name>first-list-name</profile-name>
                    <defc3 nc:operation="replace">false</defc3>
                </deftest2>
            </deftest1>
      </deftest0>
    </config>
</edit-config>


As a result of the above operation the server will produce the following output:


***** start commit phase on running for session 7, transaction 1472349 *****

Start full commit of transaction 1472349: 1 edit on running config
Start invoking commit SIL callback for merge on defcont:deftest2
 (deftest2) Enter EDIT-2 callback
 ------PHASE:commit;EDITOP:merge

    newval deftest2 P:[0x7fba4800bd80] :
          deftest2  first-list-name {
            profile-name first-list-name
            defc3 false
            deftest3 {
              defc4 true
              defc5 false
            }
          }
child Q of simple childs:   profile-name='first-list-name'
child Q of simple childs:   defc3='false'
    curval deftest2 P:[0x7fba48003e30] :
          deftest2  first-list-name {
            profile-name first-list-name
            defc3 false
            deftest3 {
              defc4 true
              defc5 false
            }
          }
child Q of simple childs:   profile-name='first-list-name'
child Q of simple childs:   defc3='false'
    Merge list:
child_edit = 0x7fba48009630
child_edit->newnode = P:[0x7fba4800bef0]
child_edit->curnode = P:[0x7fba48003ff0]
        defc3: editop=merge newval=false curval=true
Finished invoking user callback on defcont:deftest2
edit-transaction 1472349: on session 7 by restconf@::1
  time: 2021-09-14T18:14:59Z
  message-id: --
  trace-id: --
  datastore: running
  operation: replace
  target: /defcont:deftest0/defcont:deftest1/defcont:deftest2[defcont:profile-name="first-list-name"]/defcont:defc3
  comment: none

Complete commit OK of transaction 1472349 on running database
To summarize the above log and the <edit-config> results, the server invokes the following callbacks:

- SIL callback for Merge on deftest2




Rollback with Replace operation


The Rollback procedure will be the same as for any other operation. If the server applies any edits during Apply Phase and for some reason one of the callbacks fails during Commit Phase the server will run Reverse Edits in order to Reverse all the edits that were done during the Apply Phase.

For more details refer to the YumaPro Dev Manual.



Also, refer to:


How do I replace the entire contents of the Datastore resource (PUT on datastore)?