[NETCONF-563] NetconfMessageTransformUtil.toFilterStructure() fails for leaf instance identifiers Created: 24/Aug/18 Updated: 08/Dec/21 Resolved: 04/Sep/18 |
|
| Status: | Resolved |
| Project: | netconf |
| Component/s: | netconf |
| Affects Version/s: | Oxygen, Fluorine |
| Fix Version/s: | Neon, Oxygen SR4, Fluorine SR1 |
| Type: | Bug | Priority: | High |
| Reporter: | Robert Varga | Assignee: | Robert Varga |
| Resolution: | Done | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||||||
| Description |
|
This utility method is used by NETCONF plugin to create a filter expression and write it out. Unfortunately this functionality relied leaf nodes having a null value, which would in turn be recognized and ignored by codecs. Null-valued leaves are no longer available, which breaks the ability to create filters for simple leaves, rendering sal-netconf-connector inoperable for requests to read individual leaves. |
| Comments |
| Comment by Robert Varga [ 24/Aug/18 ] |
|
Stack trace of evidence: java.lang.IllegalStateException: Value has not been set at com.google.common.base.Preconditions.checkState(Preconditions.java:504) [81:com.google.guava:23.6.1.jre] at org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.AbstractImmutableNormalizedNodeBuilder.getValue(AbstractImmutableNormalizedNodeBuilder.java:33) [323:org.opendaylight.yangtools.yang-data-impl:2.0.6.1] at org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder.build(ImmutableLeafNodeBuilder.java:27) [323:org.opendaylight.yangtools.yang-data-impl:2.0.6.1] at org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder.build(ImmutableLeafNodeBuilder.java:17) [323:org.opendaylight.yangtools.yang-data-impl:2.0.6.1] at org.opendaylight.yangtools.yang.data.impl.schema.InstanceIdToSimpleNodes.create(InstanceIdToSimpleNodes.java:50) [323:org.opendaylight.yangtools.yang-data-impl:2.0.6.1] at org.opendaylight.yangtools.yang.data.impl.schema.InstanceIdToCompositeNodes.create(InstanceIdToCompositeNodes.java:105) [323:org.opendaylight.yangtools.yang-data-impl:2.0.6.1] at org.opendaylight.yangtools.yang.data.impl.schema.InstanceIdToCompositeNodes.create(InstanceIdToCompositeNodes.java:105) [323:org.opendaylight.yangtools.yang-data-impl:2.0.6.1] at org.opendaylight.yangtools.yang.data.impl.schema.InstanceIdToCompositeNodes.create(InstanceIdToCompositeNodes.java:105) [323:org.opendaylight.yangtools.yang-data-impl:2.0.6.1] at org.opendaylight.yangtools.yang.data.impl.schema.InstanceIdToCompositeNodes.create(InstanceIdToCompositeNodes.java:105) [323:org.opendaylight.yangtools.yang-data-impl:2.0.6.1] at org.opendaylight.yangtools.yang.data.impl.schema.InstanceIdToCompositeNodes.create(InstanceIdToCompositeNodes.java:105) [323:org.opendaylight.yangtools.yang-data-impl:2.0.6.1] at org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.fromInstanceId(ImmutableNodes.java:147) [323:org.opendaylight.yangtools.yang-data-impl:2.0.6.1] at org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.fromInstanceId(ImmutableNodes.java:110) [323:org.opendaylight.yangtools.yang-data-impl:2.0.6.1] at org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toFilterStructure(NetconfMessageTransformUtil.java:187) [301:org.opendaylight.netconf.sal-netconf-connector:1.7.3] at org.opendaylight.netconf.sal.connect.netconf.util.NetconfRpcStructureTransformer.toFilterStructure(NetconfRpcStructureTransformer.java:46) [301:org.opendaylight.netconf.sal-netconf-connector:1.7.3] at org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps.getConfig(NetconfBaseOps.java:185) [301:org.opendaylight.netconf.sal-netconf-connector:1.7.3] at org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps.getConfigRunning(NetconfBaseOps.java:223) [301:org.opendaylight.netconf.sal-netconf-connector:1.7.3] at org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps.getConfigRunningData(NetconfBaseOps.java:199) [301:org.opendaylight.netconf.sal-netconf-connector:1.7.3] at org.opendaylight.netconf.sal.connect.netconf.sal.tx.ReadOnlyTx.readConfigurationData(ReadOnlyTx.java:43) [301:org.opendaylight.netconf.sal-netconf-connector:1.7.3] at org.opendaylight.netconf.sal.connect.netconf.sal.tx.ReadOnlyTx.read(ReadOnlyTx.java:67) [301:org.opendaylight.netconf.sal-netconf-connector:1.7.3] |
| Comment by Robert Varga [ 24/Aug/18 ] |
|
One way of fixing this would be to store Empty instance in the leaf, but that would only paper over the problem, leading to a failure to serialize the data, as both JSON and XML codecs rely on schema information to select the correct codec – leading to ClassCastException when the leaf's value is accessed for serialization. Another way would be to select an 'empty' value, which could work except numeric types do not have such a value – leading to a partially-working solution. |
| Comment by Robert Varga [ 24/Aug/18 ] |
|
This is an extreme edge case, which should be handled in NETCONF. toFilterStructure() is returning an anyxml node, for which it really needs only an Element with proper structure to use in DOMSource. Current code does this rather inefficiently by creating a NormalizedNode from YangInstanceIdentifier and then instantiating XML codec pipeline to encode that into the target Element. Skipping the NormalizedNode/codec steps will remove the edge case and also improve the performance of this method. |
| Comment by Robert Varga [ 24/Aug/18 ] |
|
The code looks like this, making it clear there is block we can replace: final Element element = XmlUtil.createElement(BLANK_DOCUMENT, NETCONF_FILTER_QNAME.getLocalName(), Optional.of(NETCONF_FILTER_QNAME.getNamespace().toString())); element.setAttributeNS(NETCONF_FILTER_QNAME.getNamespace().toString(), NETCONF_TYPE_QNAME.getLocalName(), "subtree"); try { NetconfUtil.writeNormalizedNode(ImmutableNodes.fromInstanceId(ctx, identifier), new DOMResult(element), SchemaPath.ROOT, ctx); } catch (IOException | XMLStreamException e) { throw new IllegalStateException("Unable to serialize filter element for path " + identifier, e); } anyXmlBuilder.withValue(new DOMSource(element)); |
| Comment by Robert Varga [ 26/Aug/18 ] |
|
So here we need the XML serializer to deal with leaf values (in case of NodeIdentifierWithPredicates), but for that we certainly do not need a NormalizedNode representation of the YangInstanceIdentifier. Hence NetconfUtil should grow a writeYangInstanceIdentifier(), which will instantiate the XML codec (to deal with values) and drive it using NormalizedNodeStreamWriter interface based on the content of YangInstanceIdentifier. |