BUG 8566 direct writes to ordered list fail 05/58105/1
authorTomas Cere <tcere@cisco.com>
Wed, 31 May 2017 12:53:57 +0000 (14:53 +0200)
committerTomas Cere <tcere@cisco.com>
Thu, 1 Jun 2017 10:32:11 +0000 (12:32 +0200)
Incorrect handling of direct writes into a mapEntry which tries
to merge an empty parent list instead of an exists check but doesnt
correctly handle the possibility of an OrderedMapNode as a parent.

Change-Id: Ia2c75cc50e6ff4c9c7c9be36846c08cc85cff491
Signed-off-by: Tomas Cere <tcere@cisco.com>
netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/netconf/mdsal/connector/ops/EditConfig.java
netconf/mdsal-netconf-connector/src/test/java/org/opendaylight/netconf/mdsal/connector/ops/NetconfMDSalMappingTest.java
netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_augmented_ordered_list_create.xml [new file with mode: 0644]
netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_augmented_ordered_list_replace.xml [new file with mode: 0644]
netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_ordered_list_create.xml [new file with mode: 0644]
netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_ordered_list_replace.xml [new file with mode: 0644]
netconf/mdsal-netconf-connector/src/test/resources/yang/mdsal-netconf-mapping-test.yang

index f55e299fc22c6e3cf571d8cc11ef5a033be62ac7..e3bb3cd1000c662ee57b42423f9e899a7584eb63 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.netconf.mdsal.connector.ops;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -16,6 +17,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
+import java.util.stream.Collectors;
 import org.opendaylight.controller.config.util.xml.DocumentedException;
 import org.opendaylight.controller.config.util.xml.DocumentedException.ErrorSeverity;
 import org.opendaylight.controller.config.util.xml.DocumentedException.ErrorTag;
@@ -44,6 +46,8 @@ import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -109,7 +113,7 @@ public class EditConfig extends AbstractSingletonNetconfOperation {
         }
     }
 
-    private static void executeChange(final DOMDataReadWriteTransaction rwtx, final DataTreeChange change)
+    private void executeChange(final DOMDataReadWriteTransaction rwtx, final DataTreeChange change)
             throws DocumentedException {
         final YangInstanceIdentifier path = YangInstanceIdentifier.create(change.getPath());
         final NormalizedNode<?, ?> changeData = change.getChangeRoot();
@@ -157,11 +161,31 @@ public class EditConfig extends AbstractSingletonNetconfOperation {
         }
     }
 
-    private static void mergeParentMap(final DOMDataReadWriteTransaction rwtx, final YangInstanceIdentifier path,
+    private void mergeParentMap(final DOMDataReadWriteTransaction rwtx, final YangInstanceIdentifier path,
                                 final NormalizedNode<?, ?> change) {
         if (change instanceof MapEntryNode) {
             final YangInstanceIdentifier mapNodeYid = path.getParent();
-            //merge empty map
+
+            final SchemaNode schemaNode = SchemaContextUtil.findNodeInSchemaContext(
+                    schemaContext.getCurrentContext(),
+                    mapNodeYid.getPathArguments().stream()
+                            // filter out identifiers not present in the schema tree
+                            .filter(arg -> !(arg instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates))
+                            .filter(arg -> !(arg instanceof YangInstanceIdentifier.AugmentationIdentifier))
+                            .map(YangInstanceIdentifier.PathArgument::getNodeType).collect(Collectors.toList()));
+
+            // we should have the schema node that points to the parent list now, enforce it
+            Preconditions.checkState(schemaNode instanceof ListSchemaNode, "Schema node is not pointing to a list.");
+
+            //merge empty ordered or unordered map
+            if (((ListSchemaNode) schemaNode).isUserOrdered()) {
+                final MapNode mixinNode = Builders.orderedMapBuilder()
+                        .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(mapNodeYid.getLastPathArgument().getNodeType()))
+                        .build();
+                rwtx.merge(LogicalDatastoreType.CONFIGURATION, mapNodeYid, mixinNode);
+                return;
+            }
+
             final MapNode mixinNode = Builders.mapBuilder()
                     .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(mapNodeYid.getLastPathArgument().getNodeType()))
                     .build();
index 009b3c64ca206901481d5a739772f2172c3c2845..2d5e971dc333595e60db3ff1b0c26f839c17729f 100644 (file)
@@ -299,6 +299,34 @@ public class NetconfMDSalMappingTest {
 
     }
 
+    @Test
+    public void testOrderedListEdits() throws Exception {
+
+        verifyResponse(edit("messages/mapping/editConfigs/editConfig_ordered_list_create.xml"), RPC_REPLY_OK);
+        verifyResponse(commit(), RPC_REPLY_OK);
+
+        verifyResponse(edit("messages/mapping/editConfigs/editConfig_ordered_list_replace.xml"), RPC_REPLY_OK);
+        verifyResponse(commit(), RPC_REPLY_OK);
+
+        deleteDatastore();
+
+    }
+
+    @Test
+    public void testAugmentedOrderedListEdits() throws Exception {
+
+        verifyResponse(edit("messages/mapping/editConfigs/editConfig_augmented_ordered_list_create.xml"),
+                RPC_REPLY_OK);
+        verifyResponse(commit(), RPC_REPLY_OK);
+
+        verifyResponse(edit("messages/mapping/editConfigs/editConfig_augmented_ordered_list_replace.xml"),
+                RPC_REPLY_OK);
+        verifyResponse(commit(), RPC_REPLY_OK);
+
+        deleteDatastore();
+
+    }
+
     @Test
     public void testLock() throws Exception {
 
diff --git a/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_augmented_ordered_list_create.xml b/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_augmented_ordered_list_create.xml
new file mode 100644 (file)
index 0000000..cc5395f
--- /dev/null
@@ -0,0 +1,32 @@
+<!--
+  ~ Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <test-option>
+            set
+        </test-option>
+        <default-operation>none</default-operation>
+        <config>
+            <mapping-nodes xmlns="urn:opendaylight:mdsal:mapping:test" xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="create">
+                <mapping-node>
+                    <id>id</id>
+                    <augmented-ordered-items>
+                        <augmented-ordered-item>
+                            <id>node1</id>
+                            <content>node1 original content</content>
+                        </augmented-ordered-item>
+                    </augmented-ordered-items>
+                </mapping-node>
+            </mapping-nodes>
+        </config>
+    </edit-config>
+</rpc>
\ No newline at end of file
diff --git a/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_augmented_ordered_list_replace.xml b/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_augmented_ordered_list_replace.xml
new file mode 100644 (file)
index 0000000..47c1ceb
--- /dev/null
@@ -0,0 +1,32 @@
+<!--
+  ~ Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <test-option>
+            set
+        </test-option>
+        <default-operation>none</default-operation>
+        <config>
+            <mapping-nodes xmlns="urn:opendaylight:mdsal:mapping:test" xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="none">
+                <mapping-node>
+                <id>id</id>
+                    <augmented-ordered-items>
+                        <augmented-ordered-item xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="replace">
+                            <id>node1</id>
+                            <content>node1 content</content>
+                        </augmented-ordered-item>
+                    </augmented-ordered-items>
+                </mapping-node>
+            </mapping-nodes>
+        </config>
+    </edit-config>
+</rpc>
\ No newline at end of file
diff --git a/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_ordered_list_create.xml b/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_ordered_list_create.xml
new file mode 100644 (file)
index 0000000..b4895e5
--- /dev/null
@@ -0,0 +1,32 @@
+<!--
+  ~ Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <test-option>
+            set
+        </test-option>
+        <default-operation>none</default-operation>
+        <config>
+            <mapping-nodes xmlns="urn:opendaylight:mdsal:mapping:test" xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="create">
+                <mapping-node>
+                <id>id</id>
+                    <ordered-items>
+                        <ordered-item>
+                            <id>node1</id>
+                            <content>node1 original content</content>
+                        </ordered-item>
+                    </ordered-items>
+                </mapping-node>
+            </mapping-nodes>
+        </config>
+    </edit-config>
+</rpc>
\ No newline at end of file
diff --git a/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_ordered_list_replace.xml b/netconf/mdsal-netconf-connector/src/test/resources/messages/mapping/editConfigs/editConfig_ordered_list_replace.xml
new file mode 100644 (file)
index 0000000..f3ee4f6
--- /dev/null
@@ -0,0 +1,32 @@
+<!--
+  ~ Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <test-option>
+            set
+        </test-option>
+        <default-operation>none</default-operation>
+        <config>
+            <mapping-nodes xmlns="urn:opendaylight:mdsal:mapping:test" xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="none">
+                <mapping-node>
+                <id>id</id>
+                    <ordered-items>
+                        <ordered-item xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="replace">
+                            <id>node1</id>
+                            <content>node1 content</content>
+                        </ordered-item>
+                    </ordered-items>
+                </mapping-node>
+            </mapping-nodes>
+        </config>
+    </edit-config>
+</rpc>
\ No newline at end of file
index d338ac3e07fa044bb09a9248e4fb5e123debced8..bf363b321b360cb82373dbdc5c57d893024d5c58 100644 (file)
@@ -34,7 +34,7 @@ module config {
             }
         }
         
-        list mapping-node{
+        list mapping-node {
             key "id";
             leaf id {
                 type string;
@@ -43,6 +43,43 @@ module config {
             leaf content {
                 type string;
             }
+
+            choice ordered-choice {
+                case a {
+                    container ordered-items {
+                        list ordered-item {
+                            key "id";
+                            ordered-by user;
+                            leaf id {
+                                type string;
+                            }
+
+                            leaf content {
+                                type string;
+                            }
+                        }
+                    }
+                }
+                case b {
+                    container augmented-ordered-items {
+
+                    }
+                }
+            }
+        }
+    }
+
+    augment "/map:mapping-nodes/map:mapping-node/map:ordered-choice/map:b/map:augmented-ordered-items" {
+        list augmented-ordered-item {
+            key "id";
+            ordered-by user;
+            leaf id {
+                type string;
+            }
+
+            leaf content {
+                type string;
+            }
         }
     }