[NETCONF-833] Leaf Node cannot be deleted inside NETCONF device via RESTCONF Created: 11/Nov/21  Updated: 20/Jan/22  Resolved: 20/Jan/22

Status: Resolved
Project: netconf
Component/s: netconf
Affects Version/s: 2.0.5
Fix Version/s: 2.0.12

Type: Bug Priority: Medium
Reporter: Peter Suna Assignee: Ivan Hrasko
Resolution: Done Votes: 0
Labels: pt
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: File delete-container.log     File delete-leaf.log     File fix.log     Text File karaf.log    
Issue Links:
Relates
relates to NETCONF-563 NetconfMessageTransformUtil.toFilterS... Resolved
relates to YANGTOOLS-1389 Deprecate overloaded ImmutableNodes.f... Resolved

 Description   

Populate leaf node data cannot be erased by RESTCONF DELETE request. Request will fail on

{
    "errors": {
        "error": [
            {
                "error-tag": "operation-failed",
                "error-info": "java.lang.IllegalStateException: Value has not been set",
                "error-message": "Transaction failed",
                "error-type": "application"
            }
        ]
    }
}

In attachment is provided karaf.log file.

Used YANG model:

module test-model {  
  namespace "test:model";
  prefix tm;  
  revision 2021-11-11 {
    description "Initial revision.";
  }
  
  container test-container {
    leaf test-data {
      type string;
    }
  }
}

Steps to reproduce:

  1. Add test-model.yang file to karaf schema `netconf/karaf/target/assembly/cache/schema`
  2. Start netconf-testtool with path to test-model.yang
java -Xmx1G -jar netconf-testtool-2.0.9-SNAPSHOT-executable.jar --schemas-dir SCHEMA_PATH --device-count 1 --debug false --starting-port 36001 --ssh true --md-sal false
  1. Start karaf and install features `odl-restconf-all` and `odl-netconf-topology`
  2. Connect netconf-testtol to Netconf:
curl --request PUT 'http://localhost:8181/rests/data/network-topology:network-topology/topology=topology-netconf/node=new-netconf-device' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--data-raw '{
    "node": [
        {
            "node-id": "new-netconf-device",
            "netconf-node-topology:port": 36001,
            "netconf-node-topology:reconnect-on-changed-schema": false,
            "netconf-node-topology:connection-timeout-millis": 20000,
            "netconf-node-topology:tcp-only": false,
            "netconf-node-topology:max-connection-attempts": 0,
            "netconf-node-topology:username": "admin",
            "netconf-node-topology:password": "admin",
            "netconf-node-topology:sleep-factor": 1.5,
            "netconf-node-topology:host": "127.0.0.1",
            "netconf-node-topology:between-attempts-timeout-millis": 2000,
            "netconf-node-topology:keepalive-delay": 120
        }
    ]
}'
  1. Verify that device is connected.
  2. Populate test-data inside netconf-testtool
curl --request PUT 'http://localhost:8181/rests/data/network-topology:network-topology/topology=topology-netconf/node=new-netconf-device/yang-ext:mount/test-model:test-container' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--data-raw '{
    "test-model:test-container": {
        "test-data": "data"
    }
}'
  1. Verify that data was written
  2. Try to delete test-data
curl --request DELETE 'http://localhost:8181/rests/data/network-topology:network-topology/topology=topology-netconf/node=new-netconf-device/yang-ext:mount/test-model:test-container/test-data' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--data-raw ''

 

 

The issue was reported on lighty.io:

https://github.com/PANTHEONtech/lighty/issues/843



 Comments   
Comment by Ivan Hrasko [ 18/Nov/21 ]

By debugging NetconfDeviceCommunicator class we can see that when deleting container we send to the device:

<rpc message-id="m-10" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <edit-config>
 <target>
 <candidate/>
 </target>
 <config>
 <test-container xmlns="test:model" xmlns:op="urn:ietf:params:xml:ns:netconf:base:1.0" op:operation="delete"/>
 </config>
 </edit-config>
</rpc>

But when we are deleting leaf we send:

<rpc message-id="m-25" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <discard-changes/>
</rpc>

Please see attached logs: delete-container.log and delete-leaf.log

Comment by Ivan Hrasko [ 19/Nov/21 ]

Yes, that's probably OK because there was an error during the transaction and we need to rollback changes.

But we can investigate the issue further and we see that the problem is in yangtools:

at com.google.common.base.Preconditions.checkState(Preconditions.java:510) ~[bundleFile:?]
 at org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.AbstractImmutableNormalizedNodeBuilder.getValue(AbstractImmutableNormalizedNodeBuilder.java:29) ~[bundleFile:?]
 at org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder.build(ImmutableLeafNodeBuilder.java:42) ~[bundleFile:?]
 at org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder.build(ImmutableLeafNodeBuilder.java:18) ~[bundleFile:?]
 at org.opendaylight.yangtools.yang.data.impl.schema.InstanceIdToSimpleNodes.create(InstanceIdToSimpleNodes.java:44) ~[bundleFile:?]
 at org.opendaylight.yangtools.yang.data.impl.schema.InstanceIdToCompositeNodes.create(InstanceIdToCompositeNodes.java:87) ~[bundleFile:?]
 at org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.fromInstanceId(ImmutableNodes.java:251) ~[bundleFile:?]

The root of the issue is that leaf nodes require non null (Empty) values since this patch.

 

Comment by Ivan Hrasko [ 19/Nov/21 ]

After applying this patch we observed a successful delete sequence send to the device as shown in fix.log

Comment by Robert Varga [ 19/Nov/21 ]

The part that you are ignoring is here:

	at org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.fromInstanceId(ImmutableNodes.java:251) ~[bundleFile:?]
	at org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.createEditConfigAnyxml(NetconfMessageTransformUtil.java:364) ~[?:?]
	at org.opendaylight.netconf.sal.connect.netconf.util.NetconfRpcStructureTransformer.createEditConfigStructure(NetconfRpcStructureTransformer.java:64) ~[?:?]
	at org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps.createEditConfigStrcture(NetconfBaseOps.java:431) ~[?:?]
	at org.opendaylight.netconf.sal.connect.netconf.sal.AbstractNetconfDataTreeService.delete(AbstractNetconfDataTreeService.java:314) ~[?:?]
	at org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfTransaction.lambda$delete$0(NetconfRestconfTransaction.java:75) ~[bundleFile:?]
	at org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfTransaction.lambda$enqueueOperation$7(NetconfRestconfTransaction.java:213) ~[bundleFile:?]

Yangtools is acting on argument provided by netconf hence it is netconf which needs to be fixed to pass a proper deepestElement.

Comment by Robert Varga [ 19/Nov/21 ]

This hack with Empty results in NormalizedNodes which are invalid – i.e. all leaf values will end up Empty, even if their actual type is Uint8, for example.
This only works for NETCONF because of its misuse of YangInstanceIdentifier to express a NETCONF filter and NormalizedNode to create the NETCONF filter tree.

So please examine first the NETCONF codepaths to understand how this can be resolved without further distorting what a NormalizedNode is.

At the end of the day what is being done here that YangInstanceIdentifier is indirectly used to populate a W3C structure into which the lastChildOverride is piped in. There is even a special override to not bother with that.

So NETCONF should very much be in a position to create the W3C DOM Elements from YangInstanceIdentifier and then use the last element to be the target of DOMResult.

This needs to happen even if we have to duplicate the ImmutableNodes code doing this in NETCONF – NETCONF is the only users of this 'deepestElement' thing.

Comment by Robert Varga [ 08/Dec/21 ]

So there actually is infrastructure to do this sort of thing in netconf-util introduced in NETCONF-563. That needs to be looked over and either plugged in or generalized (and then plugged in).

Generated at Wed Feb 07 20:16:01 UTC 2024 using Jira 8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d.