Edit Transaction Examples
Edit transactions are used to modify configuration datastores. The Database Operations section explains the callback functions that are used to implement an edit transaction. This section provides guidelines and examples for handling various editing procedures.
There are several operations that cause an edit transaction to be executed. The Database Deployment Variants section describes the different internal database deployment options. The Databases variant used on the server will determine which operations are available.
Database Edit APIs (DB-API)
Newval, Curval and Update Parameters
The newval
and curval
parameters that are passed to SIL and SIL-SA
callback functions can be used to implement YANG instrumentation for
configuration data nodes.
The properties and usage of these parameters are explained in this section.
newval
: edit callback input parameternon-NULL: the new value that will be set if the edit succeeds.
NULL: no new value if the edit is a delete operation
curval
: edit callback input parameternon-NULL: the current value that will be replaced if the edit succeeds.
NULL: there is no current value for the node.
The advent of the EDIT3 Callback marks a significant shift in YANG
instrumentation for configuration data nodes, pivoting primarily on the
utilization of the update
value.
The update
value streamlines the update process by providing a composite
Update value, that incorporates latest changes proposed by the user (newval)
along with relevant current values from the datastore (curval).
update
: a merged value of all new and current values from the datastore,streamlining the update process.
non-NULL: replace the existing data with this composite
update
valueNULL: operation is delete - Delete all data from the device
A data node can either be created by YANG default or created by a client edit operation. The edit transaction processing details for YANG defaults depend on the --default-style parameter value used on the server and the YANG data model being processed.
The following example use-cases will be examined:
Leaf with a Default
Leaf without a Default
Non-Presence Container with a Default
Non-Presence Container without a Default
Presence Container with a Default
Presence Container without a Default
The default processing is handled during an edit operation before the SIL or SIL-SA callbacks are invoked. This section contains the following examples:
the details for a first edit to a node by a client operation
the details for an edit to an existing node by a client operation
the details for a delete edit to an existing node by a client operation
The actual edit operations can change in different scenarios. For example, a 'delete' operation followed by a 'create' operation on the <candidate> datastore can be changed to a 'replace' operation on the <running> datastore.
Printing the Value Path String from a SIL Edit Callback
It is very common to print a debug trace when entering a SIL callback function. There is such a debug trace in the auto-generated code by yangdump-pro.
The 'val_gen_instance_id' function is used to get the string value for the path string of the object node for the callback.
-
status_t val_gen_instance_id(xml_msg_hdr_t *mhdr, const val_value_t *val, ncx_instfmt_t format, xmlChar **buff)
Malloc and Generate the instance ID string for this value node,.
- Parameters:
mhdr -- [inout] message hdr w/ prefix map or NULL to just use the internal prefix mappings
mhdr.pmap may have entries added if prefixes used in the instance identifier which are not already in the pmap
val -- node to generate the instance ID for
format -- desired output format (NCX or Xpath)
buff -- [out] pointer to address of buffer to use
*buff malloced buffer with the instance ID
- Returns:
status
The following example uses this small YANG module to show path strings for the 'test3' list node:
container test1 {
list test2 {
key "a b";
leaf a { type int32; }
leaf b { type string; }
list test3 {
key "c d";
leaf c { type string; }
leaf d { type string; }
}
}
}
The following code snippet shows how this function can be used.
if (LOGDEBUG) {
log_debug("\nEnter u_tlist_test3_edit callback for %s phase",
agt_cbtype_name(cbtyp));
/* print the edit operation */
log_debug_append(" op=%s", op_editop_name(editop));
/* print the path string */
val_value_t *useval = newval;
if (useval == NULL) {
useval = curval;
}
if (useval != NULL) {
ncx_instfmt_t format = NCX_IFMT_XPATH2;
xmlChar *buff = NULL;
res = val_gen_instance_id(RPC_MHDR(msg),
useval,
format,
&buff);
if ((res == NO_ERR) && (buff != NULL)) {
log_debug_append("\nPath: %s", buff);
}
m__free(buff);
}
}
The following log trace shows an example list entry being created:
Enter test3_edit callback for commit phase
Enter u_tlist_test3_edit callback for commit phase op=create
Path: /tlist:test1/tlist:test2[tlist:a="100"][tlist:b="test-b"]/tlist:test3[tlist:c="test-c"][tlist:d="test-d"]
Example YANG Module: testdef2
The YANG module modules/test/pass/testdef2.yang
is used as an example for default handling.
module testdef2 {
yang-version 1.1;
namespace "urn:yumaworks:params:xml:ns:yang:testdef2";
prefix "tdef2";
revision 2023-04-07;
leaf defleaf {
type uint32;
default 42;
}
leaf nodefleaf {
type uint32;
}
container npcon {
leaf defleaf2 {
type uint32;
default 142;
}
leaf nodefleaf2 {
type uint32;
}
}
container pcon {
presence "enabled";
leaf defleaf3 {
type uint32;
default 242;
}
leaf nodefleaf3 {
type uint32;
}
}
}
Each example shows the value and source of the newval
, curval
,
and update
parameters that are passed to the edit callback function.
Note
Update value is used only in EDIT3 Callback
A simple debug trace function was added to the edit functions:
static void dump_edit_vals (val_value_t *newval,
val_value_t *curval,
val_value_t *update)
{
if (!LOGDEBUG) {
return;
}
log_debug("\nEdit values:");
if (newval) {
log_debug_append("\nnewval set %s",
val_set_by_default(newval) ?
"by default" : "by client");
val_dump_value(newval, 2, DBG);
} else {
log_debug_append("\nnewval NULL");
}
if (curval) {
log_debug_append("\ncurval set %s",
val_set_by_default(curval) ?
"by default" : "by client");
val_dump_value(curval, 2, DBG);
} else {
log_debug_append("\ncurval NULL");
}
if (update) {
log_debug_append("\nupdate set %s",
val_set_by_default(update) ?
"by default" : "by client");
val_dump_value(update, 2, DBG);
} else {
log_debug_append("\nupdate NULL");
}
} /* dump_edit_vals */
Default Nodes Created During Load Config
The server will usually create default leafs and NP containers during the system <load-config> operation. The defaults are added to an empty datastore or to a datastore with the previous contents from non-volatile storage.
A val_value_t data structure is created for both default and non-default nodes leafs:
The
newval
,curval
, orupdate
parameters could be set by defaultUse function
val_set_by_default
to check if the value was added by the systemUse function
val_is_default
to check if the value is equal to the YANG default value
For this example it is assumed the initial datastore is empty. This is possible many ways, included by use of the --no-startup parameter.
The
curval
is NULL during a load since the datastore is initially empty.The
newval
is set by default.The
update
is the same asnewval
in EDIT3 callbacks.The editop will be
OP_EDITOP_LOAD
The --default-style parameter is ignored during processing.
The
newval
will be set-by-default in all 3 default stylesThe datastore will be <running>.
In this example, there will be SIL callbacks for the 2 nodes that are created by default.
Leaf /defleaf = 42
Start invoking validate SIL callback for load on testdef2:defleaf Enter defleaf_edit callback for validate phase Enter u_tdef2_defleaf_edit callback for validate phase Edit values: newval set by default tdef2:defleaf 42 curval NULL update NULL Finished invoking user callback on testdef2:defleaf
Container /npcon (contains defleaf2 = 142)
Enter npcon_edit callback for validate phase Enter u_tdef2_npcon_edit callback for validate phase Edit values: newval set by default tdef2:npcon { defleaf2 142 } curval NULL update set by default tdef2:npcon { defleaf2 142 } Finished invoking user callback on testdef2:defleaf
Edit Processing For Leafs
The callback details for a leaf are is the simplest of all YANG objects. There is only one instance possible of a leaf.
Note
Top level leafy nodes cannot have EDIT2 nor EDIT3 callbacks. In this case there will be an EDIT1 callback, thus no update value.
For non-delete operations:
The
newval
is non-NULL and is set by a client.The
curval
is non-NULL if there is an existing value for the leaf.The edit operation is a 'set' operation if the editop is one of:
OP_EDITOP_CREATE
OP_EDITOP_MERGE
OP_EDITOP_REPLACE
These operations mean the same thing for leafs and should be treated the same.
For delete operations:
The
newval
is NULLThe
curval
is set-by-default or NULLThe edit operation is a 'delete' operation if the editop is one of:
OP_EDITOP_DELETE
OP_EDITOP_REMOVE
For SIL or SIL-SA callback purposes the value of editop will always be
OP_EDITOP_DELETE
for any form of delete operation used by the client.
Leaf with a Default Value
create /defleaf value=100
Enter u_tdef2_defleaf_edit callback for validate phase Edit values: newval set by client tdef2:defleaf 100 curval set by default tdef2:defleaf 42 update NULL Finished invoking user callback on testdef2:defleaf
There is always a current value for a leaf with a YANG default, even if it is deleted.
replace /defleaf value=101
Enter defleaf_edit callback for validate phase Enter u_tdef2_defleaf_edit callback for validate phase Edit values: newval set by client tdef2:defleaf 101 curval set by client tdef2:defleaf 100 update NULL Finished invoking user callback on testdef2:defleaf
delete /defleaf
Enter u_tdef2_defleaf_edit callback for validate phase Edit values: newval set by default tdef2:defleaf 42 curval set by client tdef2:defleaf 101 update NULL Finished invoking user callback on testdef2:defleaf
Leaf Without a Default Value
create /nodefleaf value=200
Enter u_tdef2_nodefleaf_edit callback for validate phase Edit values: newval set by client tdef2:nodefleaf 200 curval NULL update NULL Finished invoking user callback on testdef2:nodefleaf
replace /nodefleaf value=201
Enter u_tdef2_nodefleaf_edit callback for validate phase Edit values: newval set by client tdef2:nodefleaf 201 curval set by client tdef2:nodefleaf 200 update NULL Finished invoking user callback on testdef2:nodefleaf
delete /nodefleaf
Enter u_tdef2_nodefleaf_edit callback for commit phase Edit values: newval NULL curval set by client tdef2:nodefleaf 201 update NULL Finished invoking user callback on testdef2:nodefleaf
Edit Processing For Containers and Lists
There are 2 types of YANG data nodes that can have child nodes:
non-presence container:
These nodes are created automatically.
The --create-empty-npcontainers parameter controls this behavior during edit operations.
The value can either be set-by-default or set-by-client
presence container or list:
These nodes are not created automatically.
The value is always set-by-client
For non-delete operations:
The
newval
is non-NULL and is set by a client.The
curval
is non-NULL if there is an existing value for the node.The
update
is non-NULL and is a merged value of new and current values.The edit operation is a 'set' operation if the editop is one of:
OP_EDITOP_CREATE
OP_EDITOP_MERGE
OP_EDITOP_REPLACE
These operations mean the same thing only if the current value is set-by-default or NULL.
For delete operations:
The
newval
is NULLThe
curval
is set-by-default or NULLThe
update
is NULLThe edit operation is a 'delete' operation if the editop is one of:
OP_EDITOP_DELETE
OP_EDITOP_REMOVE
For SIL or SIL-SA callback purposes the value of editop will always be
OP_EDITOP_DELETE
for any form of delete operation used by the client.If the --allow-list-delete-all parameter is 'true' then the following edit operations can be in the edit request. -
OP_EDITOP_DELETE_ALL
-OP_EDITOP_REMOVE_ALL
The server will set editop to
OP_EDITOP_DELETE
for each individual list instance.
Non Presence Container with a Default Value
create /npcon (defleaf2 = 242, nodefleaf2 = 243)
Enter u_tdef2_npcon_edit callback for validate phase Edit values: newval set by client tdef2:npcon { defleaf2 242 nodefleaf2 243 } curval set by default tdef2:npcon { defleaf2 142 } update set by client tdef2:npcon { defleaf2 242 nodefleaf2 243 } Finished invoking user callback on testdef2:npcon
Update value is the same as newval for CREATE operation.
replace /npcon (defleaf2 = 143, nodefleaf2 NOT SET)
Enter u_tdef2_npcon_edit callback for validate phase Edit values: newval set by client tdef2:npcon { defleaf2 143 } curval set by client tdef2:npcon { defleaf2 242 nodefleaf2 243 } update set by client tdef2:npcon { defleaf2 143 nodefleaf2 243 } Finished invoking user callback on testdef2:npcon
There is no instance of the 'nodefleaf2' node in 'newval'. The SIL callback for 'npcon' must remove any internal value held for this leaf if its configuration instance is removed.
Update value can be used to update internal values. The technique here is to replace the existing data with this composite Update value.
replace /npcon (defleaf2 NOT SET, nodefleaf2 = 256)
Enter u_tdef2_npcon_edit callback for validate phase Edit values: newval set by client tdef2:npcon { nodefleaf2 256 } curval set by client tdef2:npcon { defleaf2 143 nodefleaf2 243 } update set by client tdef2:npcon { defleaf2 143 nodefleaf2 256 } Finished invoking user callback on testdef2:npcon
Update value can be used to update internal values. The technique here is to replace the existing data with this composite Update value.
delete /npcon
Enter u_tdef2_npcon_edit callback for validate phase Edit values: newval set by default tdef2:npcon { defleaf2 142 } curval set by client tdef2:npcon { defleaf2 143 nodefleaf2 256 } update NULL Finished invoking user callback on testdef2:npcon
Update value is NULL during DELETE operation. Newval contains only defaults.
Presence Containers and Lists
An example for a presence container pcon
is shown.
The callbacks would be quite similar for lists, except
additional key leaf parameters are used.
create /pcon (defleaf3 = 300, nodefleaf3 = 400)
Enter u_tdef2_pcon_edit callback for validate phase Edit values: newval set by client tdef2:pcon { defleaf3 300 nodefleaf3 400 } curval NULL update set by client tdef2:pcon { defleaf3 300 nodefleaf3 400 } Finished invoking user callback on testdef2:pcon
Update value is the same as newval for CREATE operation.
replace /pcon (defleaf3 = 243, nodefleaf3 NOT SET)
Enter u_tdef2_pcon_edit callback for validate phase Edit values: newval set by client tdef2:pcon { defleaf3 243 } curval set by client tdef2:pcon { defleaf3 300 nodefleaf3 400 } update set by client tdef2:pcon { defleaf3 243 nodefleaf3 400 } Finished invoking user callback on testdef2:pcon
Update value can be used to update internal values. The technique here is to replace the existing data with this composite Update value.
replace /npcon (defleaf3 NOT SET, nodefleaf3 = 256)
Enter u_tdef2_pcon_edit callback for validate phase Edit values: newval set by client tdef2:pcon { nodefleaf3 256 } curval set by client tdef2:pcon { defleaf3 243 nodefleaf3 400 } update set by client tdef2:pcon { defleaf3 243 nodefleaf3 256 } Finished invoking user callback on testdef2:pcon
Update value can be used to update internal values. The technique here is to replace the existing data with this composite Update value.
delete /pcon
Enter u_tdef2_pcon_edit callback for validate phase Edit values: newval NULL curval set by client tdef2:pcon { defleaf3 242 nodefleaf3 256 } update NULL Finished invoking user callback on testdef2:pcon
Update value is NULL during DELETE operation. Newval does not contain any defaults and is also NULL.
Replace Operation Examples
The following section 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.
Replace Operation Usage
The following examples use the following YANG module:
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 2: Replace on container "deftest1"
Prior to replacing any nodes, two lists will be created within the container using the following edit-config command:
<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>
Assuming the netconfd-pro server is running with --target=candidate, a <commit> operation must be executed following the above edit to apply all changes made 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 callback invocations.
To summarize the <edit-config> result, 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 is done on a list entry that does not exist. As a result of this operation the netconfd-pro server creates this new entry since there is no any entries to replace it with.
As a result of this request and after <commit> operation the server will produce the following callback invocations.
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)
The following example demonstrates replacing an existing list entry. Assuming the same configurations are present in the datastore, execute 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 this request and after <commit> operation the server will produce the following callback invocations.
To summarize the <edit-config> result, 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
}
}
]
}
}
}
To replace a leaf node within a list entry, use 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 this request and after <commit> operation the server will produce the following callback invocations.
To summarize the <edit-config> result, the server invokes the following callbacks:
SIL callback for Merge on deftest2
Rollback with Replace operation
The rollback procedure is identical to that of any other operation. If the server applies edits during the Apply Phase and encounters a callback failure during the Commit Phase, it will initiate Reverse Edits to undo all changes made during the Apply Phase.
Replace Operation with Nested Operations Examples
Note
Nested operations within top replace operation are NOT allowed and must NOT be used in order to avoid unexpected errors.
This section provides examples of edit-config scenarios utilizing the Replace operation, covering top-level replacements, default-operation settings as "replace," and nested operations within a top Replace operation.
It illustrates the expected behavior of the server and the expected responses to specific edit-config requests containing Replace operations.
The four examples included in this section are:
Replace as a New Value
Replace Operation with Changes
Default-Operation Merge, Top-level Edit Operation Replace (No Changes)
Default-Operation Replace (No Changes)
The following examples use the following YANG module:
module onecont_onelist {
namespace "http://example.com/ns/yang/onecont_onelist";
prefix onecont_onelist;
revision "2024-06-27";
container CONT1 {
list LIST2 {
key "name";
leaf name {
type string;
}
leaf wait-to-restore {
type uint32 {
}
default 5;
}
leaf hold-str {
type string;
}
}
}
}
Replace as a New Value
Scenario: The configuration is initially empty, and the following is the first edit.
Note: If the Replace operation is applied to a node that does not exist, the netconfd-pro server will create a new entry, as there is nothing available to replace. Meaning the Replace is treated as Create in this scenario.
<edit-config>
<target>
<running/>
</target>
<default-operation>merge</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist" nc:operation="replace">
<LIST2>
<name nc:operation="merge">abc</name>
</LIST2>
</CONT1>
</config>
</edit-config>
Or the following XML request:
<edit-config>
<target>
<running/>
</target>
<default-operation>replace</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist">
<LIST2>
<name nc:operation="merge">abc</name>
</LIST2>
</CONT1>
</config>
</edit-config>
Expected Result: The server returns an error as nested edit operations within a Replace operation are not supported.
<errors xmlns:ncx="http://netconfcentral.org/ns/yuma-ncx"
xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf">
<error>
<error-type>rpc</error-type>
<error-tag>operation-not-supported</error-tag>
<error-app-tag>no-support</error-app-tag>
<error-path>/edit-config</error-path>
<error-message xml:lang="en">nested edit operation not supported</error-message>
<error-info>
<error-number>438</error-number>
</error-info>
</error>
</errors>
Replace Operation with Changes
Scenario: Initialize the configuration with the following data then replace it with NOT the same configurations but with nested operations.
<edit-config>
<target>
<running/>
</target>
<default-operation>merge</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist">
<LIST2>
<name>1</name>
<hold-str>abcd</hold-str>
</LIST2>
</CONT1>
</config>
</edit-config>
Request: Send a Replace operation to the server as follows:
<edit-config>
<target>
<running/>
</target>
<default-operation>replace</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist">
<LIST2>
<name nc:operation="merge">1</name>
</LIST2>
</CONT1>
</config>
</edit-config>
Or the following XML request:
<edit-config>
<target>
<running/>
</target>
<default-operation>merge</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist" nc:operation="replace">
<LIST2>
<name nc:operation="merge">1</name>
</LIST2>
</CONT1>
</config>
</edit-config>
Expected Result: The server attempts to apply the Replace edit but returns an error due to unsupported nested operations within a Replace operation.
The "hold-str" node is missing from the second edit-config thus the server must apply this replace edit and attempt deletion of this "hold-str" node. However, there is a nested operation within replace operation thus the error is reported.
<errors xmlns:ncx="http://netconfcentral.org/ns/yuma-ncx"
xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf">
<error>
<error-type>rpc</error-type>
<error-tag>operation-not-supported</error-tag>
<error-app-tag>no-support</error-app-tag>
<error-path>/edit-config</error-path>
<error-message xml:lang="en">nested edit operation not supported</error-message>
<error-info>
<error-number>438</error-number>
</error-info>
</error>
</errors>
Default-Operation Merge, Top-level Edit Operation Replace (No Changes)
Scenario: Initialize the configuration with the following data then replace it with the same configurations but with nested operations.
<edit-config>
<target>
<running/>
</target>
<default-operation>merge</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist">
<LIST2>
<name>1</name>
</LIST2>
</CONT1>
</config>
</edit-config>
Request: A Replace operation on the top node with a merge at a nested level.
<edit-config>
<target>
<running/>
</target>
<default-operation>merge</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist" nc:operation="replace">
<LIST2>
<name nc:operation="merge">1</name>
</LIST2>
</CONT1>
</config>
</edit-config>
Expected Result: The server detects the unsupported nested operation and returns an error.
When the default-operation is set to Replace, the server follows a distinct code path compared to Merge. In default-operation Replace mode, the server checks each node individually, allowing it to detect and flag any disallowed nested edit operations.
<errors xmlns:ncx="http://netconfcentral.org/ns/yuma-ncx"
xmlns="urn:ietf:params:xml:ns:yang:ietf-restconf">
<error>
<error-type>rpc</error-type>
<error-tag>operation-not-supported</error-tag>
<error-app-tag>no-support</error-app-tag>
<error-path>/edit-config</error-path>
<error-message xml:lang="en">nested edit operation not supported</error-message>
<error-info>
<error-number>438</error-number>
</error-info>
</error>
</errors>
The same result is expected if there are extra nodes within the list entry. Assume these extra nodes already created in the initial configurations:
<edit-config>
<target>
<running/>
</target>
<default-operation>merge</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist" nc:operation="replace">
<LIST2>
<name nc:operation="merge">1</name>
<wait-to-restore>5</wait-to-restore>
</LIST2>
</CONT1>
</config>
</edit-config>
OR
<edit-config>
<target>
<running/>
</target>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist" nc:operation="replace">
<LIST2>
<name nc:operation="merge">1</name>
<hold-str>abcd</hold-str>
</LIST2>
</CONT1>
</config>
</edit-config>
Expected Result: The server detects the unsupported nested operation and returns an error.
Default-Operation Replace (No Changes)
Scenario: Initialize the configuration with the following data then replace it with the same configurations but with nested operations.
<edit-config>
<target>
<running/>
</target>
<default-operation>merge</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist">
<LIST2>
<name>abc</name>
</LIST2>
</CONT1>
</config>
</edit-config>
Request: Send an edit with default-operation Replace with a nested merge operation within the config:
<edit-config>
<target>
<running/>
</target>
<default-operation>replace</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist">
<LIST2>
<name nc:operation="merge">abc</name>
</LIST2>
</CONT1>
</config>
</edit-config>
Expected Result: Since the incoming configuration matches the running configuration, the server skips the edit-config request, resulting in no error.
When the default-operation Replace the server just compares the two configurations: running and the incoming new configuration. As a result to make a decision it needs to start the transaction process.
As a new configuration in the edit-config is exactly the same as in running configuration, the server skips over this edit-config completely, resulting in no error.
The same result is expected if there are extra nodes within the list entry. Assume these extra nodes already created in the initial configurations:
<edit-config>
<target>
<running/>
</target>
<default-operation>replace</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist">
<LIST2>
<name nc:operation="merge">abc</name>
<wait-to-restore>5</wait-to-restore>
</LIST2>
</CONT1>
</config>
</edit-config>
OR
<edit-config>
<target>
<running/>
</target>
<default-operation>replace</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist">
<LIST2>
<name nc:operation="merge">abc</name>
<wait-to-restore>100</wait-to-restore>
</LIST2>
</CONT1>
</config>
</edit-config>
OR
<edit-config>
<target>
<running/>
</target>
<default-operation>replace</default-operation>
<test-option>test-then-set</test-option>
<config>
<CONT1 xmlns="http://example.com/ns/yang/onecont_onelist">
<LIST2>
<name nc:operation="merge">abc</name>
<hold-str>abcd</hold-str>
</LIST2>
</CONT1>
</config>
</edit-config>