[NETCONF-83] Mounted store edit-config operations fail when creating list entries Created: 09/Oct/15  Updated: 13/Aug/19

Status: Confirmed
Project: netconf
Component/s: netconf
Affects Version/s: None
Fix Version/s: None

Type: Bug
Reporter: Wojciech Dec Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Operating System: All
Platform: All


External issue ID: 4449

 Description   

Netconf mounted data store operations fail when creating list entries using the new API, with the "create missing parent" set to True.
The code attempts to create also the list entry key leaf name, which is used as the IID, but the create parent subroutine does not pass the mandatory data for the list entry. This gets rejected by Confd.
Following example is for the ietf interfaces module, where the type field is mandatory.

Data being put is:

Interface [_description=parent-interface, _key=InterfaceKey [_name=GigabitEthernet0/8/0], _name=GigabitEthernet0/8/0, _type=class org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd, augmentation=[Interface1 [_ipv4=Ipv4 [_enabled=true, _forwarding=true, augmentation=[]], _ipv6=Ipv6 [_enabled=true, _forwarding=true, augmentation=[]]]]]

Log:

2015-10-08 14:33:34,839 | TRACE | oupCloseable-7-2 | NetconfDeviceCommunicator | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | Finished sending request <rpc message-id="m-5" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<candidate/>
</target>
<error-option>rollback-on-error</error-option>
<config>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>
</config>
</edit-config>
</rpc>

2015-10-08 14:33:34,844 | DEBUG | oupCloseable-7-2 | NetconfDeviceCommunicator | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice

{vfn1}: Message received <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-5">
<ok/>
</rpc-reply>

2015-10-08 14:33:34,844 | TRACE | oupCloseable-7-2 | NetconfDeviceCommunicator | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice{vfn1}

: Matched request: <rpc message-id="m-5" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<candidate/>
</target>
<error-option>rollback-on-error</error-option>
<config>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>
</config>
</edit-config>
</rpc>
to response: <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-5">
<ok/>
</rpc-reply>

2015-10-08 14:33:34,844 | TRACE | oupCloseable-7-2 | KeepaliveSalFacade | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice

{vfn1}: Resetting netconf keepalive timer
2015-10-08 14:33:34,844 | TRACE | oupCloseable-7-2 | KeepaliveSalFacade | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice{vfn1}

: Scheduling next keepalive in 120 SECONDS
2015-10-08 14:33:34,844 | TRACE | oupCloseable-7-2 | NetconfRpcFutureCallback | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice

{vfn1}: Edit candidate invoked successfully
2015-10-08 14:33:34,853 | TRACE | lt-dispatcher-17 | NetconfDeviceCommunicator | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice{vfn1}

: Sending message <rpc message-id="m-6" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<candidate/>
</target>
<error-option>rollback-on-error</error-option>
<config>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>
</config>
</edit-config>
</rpc>

2015-10-08 14:33:34,854 | TRACE | oupCloseable-7-2 | NetconfDeviceCommunicator | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | Finished sending request <rpc message-id="m-6" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<candidate/>
</target>
<error-option>rollback-on-error</error-option>
<config>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>
</config>
</edit-config>
</rpc>

2015-10-08 14:33:34,859 | DEBUG | oupCloseable-7-2 | NetconfDeviceCommunicator | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice

{vfn1}: Message received <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-6">
<ok/>
</rpc-reply>

2015-10-08 14:33:34,859 | TRACE | oupCloseable-7-2 | NetconfDeviceCommunicator | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice{vfn1}

: Matched request: <rpc message-id="m-6" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<candidate/>
</target>
<error-option>rollback-on-error</error-option>
<config>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>
</config>
</edit-config>
</rpc>
to response: <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-6">
<ok/>
</rpc-reply>

2015-10-08 14:33:34,860 | TRACE | oupCloseable-7-2 | KeepaliveSalFacade | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice

{vfn1}: Resetting netconf keepalive timer
2015-10-08 14:33:34,860 | TRACE | oupCloseable-7-2 | KeepaliveSalFacade | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice{vfn1}

: Scheduling next keepalive in 120 SECONDS
2015-10-08 14:33:34,860 | TRACE | oupCloseable-7-2 | NetconfRpcFutureCallback | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice

{vfn1}: Edit candidate invoked successfully
2015-10-08 14:33:34,869 | TRACE | lt-dispatcher-17 | NetconfDeviceCommunicator | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice{vfn1}

: Sending message <rpc message-id="m-7" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<candidate/>
</target>
<error-option>rollback-on-error</error-option>
<config>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>GigabitEthernet0/8/0</name>
</interface>
</interfaces>
</config>
</edit-config>
</rpc>

2015-10-08 14:33:34,871 | TRACE | oupCloseable-7-2 | NetconfDeviceCommunicator | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | Finished sending request <rpc message-id="m-7" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<candidate/>
</target>
<error-option>rollback-on-error</error-option>
<config>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>GigabitEthernet0/8/0</name>
</interface>
</interfaces>
</config>
</edit-config>
</rpc>

2015-10-08 14:33:34,876 | DEBUG | oupCloseable-7-2 | NetconfDeviceCommunicator | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice

{vfn1}: Message received <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-7">
<rpc-error>
<error-type>application</error-type>
<error-tag>data-missing</error-tag>
<error-severity>error</error-severity>
<error-path xmlns:if="urn:ietf:params:xml:ns:yang:ietf-interfaces">
/rpc/edit-config/config/if:interfaces/if:interface[if:name='GigabitEthernet0/8/0']/if:type
</error-path>
<error-message xml:lang="en">/interfaces/interface[name='GigabitEthernet0/8/0']/type is not configured</error-message>
<error-info>
<bad-element>type</bad-element>
</error-info>
</rpc-error>
</rpc-reply>

2015-10-08 14:33:34,876 | TRACE | oupCloseable-7-2 | NetconfDeviceCommunicator | 253 - org.opendaylight.controller.sal-netconf-connector - 1.2.0.Lithium-00001-SNAPSHOT | RemoteDevice{vfn1}

: Matched request: <rpc message-id="m-7" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<candidate/>
</target>
<error-option>rollback-on-error</error-option>
<config>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>GigabitEthernet0/8/0</name>
</interface>
</interfaces>
</config>
</edit-config>
</rpc>
to response: <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-7">
<rpc-error>
<error-type>application</error-type>
<error-tag>data-missing</error-tag>
<error-severity>error</error-severity>
<error-path xmlns:if="urn:ietf:params:xml:ns:yang:ietf-interfaces">
/rpc/edit-config/config/if:interfaces/if:interface[if:name='GigabitEthernet0/8/0']/if:type
</error-path>
<error-message xml:lang="en">/interfaces/interface[name='GigabitEthernet0/8/0']/type is not configured</error-message>
<error-info>
<bad-element>type</bad-element>
</error-info>
</rpc-error>
</rpc-reply>



 Comments   
Comment by Maros Marsalek [ 10/Oct/15 ]

This is actually an MD-SAL Lithium issue, when binding aware transaction tries to create parent structure. The BindingDOMWriteTransactionAdapter.ensureParentsByMerge() is also trying to create parent data structure for the data itself (which should not be considered parents).

So the method should probably perform following action:

normalizedPath = normalizedPath.getParent();

Note: This has been fixed in Beryllium, where ensure parents is invoked at AbstractWriteTransaction.ensureParentsByMerge() and the method already contains the getParent() invocation.

Comment by Maros Marsalek [ 10/Oct/15 ]

One addition:

The "normalizedPath = normalizedPath.getParent();" action should be preceeded by a "if(normalizedPath.getParent() == null) return;" check. Because I think getParent may return a null.

Comment by Wojciech Dec [ 10/Oct/15 ]

It does not appear that Lithium code has the getParent() method. Suggestions?

Comment by Maros Marsalek [ 11/Oct/15 ]

Well, getParent() just creates new InstanceIdentifier instance with the same path without the last element:

YangInstanceIdentifier.create(this.path.subList(0, this.path.size() - 1));

So doing the the same thing in BindingDOMWriteTransactionAdapter.ensureParentsByMerge() should do the trick.

Its also possible to stop the loop before the last element is ensured as parent:

while (iterator.hasNext()) {
PathArgument currentArg = iterator.next();
// Skipping last element
if(!iterator.hasNext())

{ break; }

...

Comment by Tony Tkacik [ 03/Nov/15 ]

Create missingParent=true will never work with mandatory nodes,
since MD-SAL does not have any information how to fill out missing parents,
originally we objected for having this flag and planned to require community to create this parents manually, but community decided it is useful to have this flags, even with limitations, that it may fail on mandatory nodes.

Comment by Wojciech Dec [ 03/Nov/15 ]

It doesn't fail when writing against the same model in local MD-SAL storage. It only fails when writing to the netconf mounted data store (a ConfD server).
Note that it could be a ConfD Netconf protocol bug (which I asked your comment on in the associated mail). The Netconf server returns a "mandatory nodes missing" after the first edit config, even before the commit/validate.

Comment by Tony Tkacik [ 04/Nov/15 ]

Are we sure that puting of Interface [_description=parent-interface, _key=InterfaceKey [_name=GigabitEthernet0/8/0], _name=GigabitEthernet0/8/0, _type=class org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd, augmentation=[Interface1 [_ipv4=Ipv4 [_enabled=true, _forwarding=true, augmentation=[]], _ipv6=Ipv6 [_enabled=true, _forwarding=true, augmentation=[]]]]]

failed?

Or was there another nested write or put which was trying to first put something inside such interface and/or put interface with only key specified and later
write actual content?

Lithium MD-SAL datastore does not enforce mandatory statements (implementation behaviour, patch exists for Be)

As I mentioned createMissingParents = true is bit flawed, that it can safely works only for parents which does not contain any mandatory nodes.

So given that you are using concrete model - you have more knowledge about how that data should be filled out rather then MD-SAL (e.g. we can not infer values for mandatory nodes).

> The Netconf server returns a "mandatory nodes missing" after the first edit
> config, even before the commit/validate.

https://tools.ietf.org/html/rfc6020#section-8.2 section specifies which checks happens at which point - unfortunately it does not specify when mandatory checks are run. I would interpret this they should be done during validate or commit phase if target is candidate, but that is my interpretation and others may interpret it differently.

Comment by Wojciech Dec [ 04/Nov/15 ]

Yes, the putting of that data failed, in a single transaction. If you look at the netconf trace, the first edit-config carries only the list-entry name, which is rejected by the netconf server (likely because of that config validation ambiguity in the spec), which meant that the second part of the config carrying the mandatory data never got transmitted
Using the same data and code, but against the local store, the sequence of operations is the same, however the first operation is accepted, and then the second delivers the mandatory data.

Also note that in this case the mandatory leafs are not part of any of the node's parent nodes, i.e. they are only mandatory for the node being created.

Comment by Maros Marsalek [ 03/Dec/15 ]

Hi Wojciech,

Just a quick recap, there are 2 issues here:

1. Creating parent structure with mandatory nodes is not possible because ensure parents does not provide them and should be avoided. (This would work against MD-SAL because it does't enforce mandatory yet) - But this is not your problem because you are creating only a simple parent structure and mandatory nodes are in the actual data you are submitting.

2. Creating parent structure using BA (at least) in Lithium: BA tries to create the parent structure also for the data itself. - This is unnecessary since the data is already present in the request and in your case this causes issues due to mandatory nodes being present in that data.

In your case the fix should be modifying ensure parents in the BA layer to not create parent structure for the data itself and strip the last item from InstanceIdentifier. I think you've tried to use this workaround (suggested earlier), but I don't remember if you were successful. Could you provide the details here ?

Thanks

Comment by Wojciech Dec [ 16/Feb/16 ]

The issue also appears when attempting to add configuration via RESTCONF. It actually renders the API unusable for config changes.

API :
PUT /config/opendaylight-inventory:nodes/node/172.20.118.63/yang-ext:mount/ietf-interfaces:interfaces/interface/

{name}

Input :
{
"interface": [

{ "name": "et4", "type": "ietf-interfaces-mm:layer1-if", "ietf-interfaces-mm:source": "et5", "description": "", "enabled": false }

]
}

Netconf data doesn't carry the mandatory parameters and fails:

2016-02-13 04:03:24.861 GMT+00:00 [nettyThreadgroupModule$NioEventLoopGroupCloseable-7-3] TRACE o.o.c.s.c.n.u.NetconfRpcFutureCallback - RemoteDevice

{172.20.118.63}: Lock candidate invoked successfully
2016-02-13 04:03:24.861 GMT+00:00 [qtp11858990-41295] TRACE o.o.c.s.c.n.l.NetconfDeviceCommunicator - RemoteDevice{172.20.118.63}

: Sending message <rpc message-id="m-17" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<candidate/>
</target>
<error-option>rollback-on-error</error-option>
<config>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>
</config>
</edit-config>
</rpc>

2016-02-13 04:03:24.862 GMT+00:00 [nettyThreadgroupModule$NioEventLoopGroupCloseable-7-3] TRACE o.o.c.s.c.n.l.NetconfDeviceCommunicator - Finished sending request <rpc message-id="m-17" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<candidate/>
</target>
<error-option>rollback-on-error</error-option>
<config>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>
</config>
</edit-config>
</rpc>

2016-02-13 04:03:24.972 GMT+00:00 [nettyThreadgroupModule$NioEventLoopGroupCloseable-7-3] DEBUG o.o.c.s.c.n.l.NetconfDeviceCommunicator - RemoteDevice

{172.20.118.63}

: Message received <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-17">
<rpc-error>
<error-type>application</error-type>
<error-tag>operation-failed</error-tag>
<error-severity>error</error-severity>
<error-message>Datastore fails to validate (Element config failed to validate content)</error-message>
</rpc-error>
<default:rpc-error xmlns:default="urn:ietf:params:xml:ns:netconf:base:1.0">
<error-type>application</error-type>
<error-tag>operation-failed</error-tag>
<error-severity>error</error-severity>
<error-message>Datastore fails to validate (Extra element interfaces in interleave)</error-message>
</default:rpc-error>
</rpc-reply>

Comment by Tony Tkacik [ 16/Feb/16 ]

@Wojciech: This is separate issue, could you open bug for it?

(In reply to Wojciech Dec from comment #10)
> The issue also appears when attempting to add configuration via RESTCONF. It
> actually renders the API unusable for config changes.
>
> API :
> PUT
> /config/opendaylight-inventory:nodes/node/172.20.118.63/yang-ext:mount/ietf-
> interfaces:interfaces/interface/

{name}

>
> Input :
> {
> "interface": [
>

{ > "name": "et4", > "type": "ietf-interfaces-mm:layer1-if", > "ietf-interfaces-mm:source": "et5", > "description": "", > "enabled": false > }

> ]
> }
>
> Netconf data doesn't carry the mandatory parameters and fails:
>
> 2016-02-13 04:03:24.861 GMT+00:00
> [nettyThreadgroupModule$NioEventLoopGroupCloseable-7-3] TRACE
> o.o.c.s.c.n.u.NetconfRpcFutureCallback - RemoteDevice

{172.20.118.63}: Lock
> candidate invoked successfully
> 2016-02-13 04:03:24.861 GMT+00:00 [qtp11858990-41295] TRACE
> o.o.c.s.c.n.l.NetconfDeviceCommunicator - RemoteDevice{172.20.118.63}

:
> Sending message <rpc message-id="m-17"
> xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
> <edit-config>
> <target>
> <candidate/>
> </target>
> <error-option>rollback-on-error</error-option>
> <config>
> <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>
> </config>
> </edit-config>
> </rpc>
>
> 2016-02-13 04:03:24.862 GMT+00:00
> [nettyThreadgroupModule$NioEventLoopGroupCloseable-7-3] TRACE
> o.o.c.s.c.n.l.NetconfDeviceCommunicator - Finished sending request <rpc
> message-id="m-17" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
> <edit-config>
> <target>
> <candidate/>
> </target>
> <error-option>rollback-on-error</error-option>
> <config>
> <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>
> </config>
> </edit-config>
> </rpc>
>
> 2016-02-13 04:03:24.972 GMT+00:00
> [nettyThreadgroupModule$NioEventLoopGroupCloseable-7-3] DEBUG
> o.o.c.s.c.n.l.NetconfDeviceCommunicator - RemoteDevice

{172.20.118.63}

:
> Message received <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
> message-id="m-17">
> <rpc-error>
> <error-type>application</error-type>
> <error-tag>operation-failed</error-tag>
> <error-severity>error</error-severity>
> <error-message>Datastore fails to validate (Element config failed to
> validate content)</error-message>
> </rpc-error>
> <default:rpc-error xmlns:default="urn:ietf:params:xml:ns:netconf:base:1.0">
> <error-type>application</error-type>
> <error-tag>operation-failed</error-tag>
> <error-severity>error</error-severity>
> <error-message>Datastore fails to validate (Extra element interfaces in
> interleave)</error-message>
> </default:rpc-error>
> </rpc-reply>

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