BUG-3625 Allow replace nested composite nodes in cfg-subsystem 03/22803/2
authorMaros Marsalek <mmarsale@cisco.com>
Tue, 16 Jun 2015 11:36:30 +0000 (13:36 +0200)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 1 Jul 2015 14:41:34 +0000 (14:41 +0000)
Netconf-endpoint for config-subsystem now supports replace operation on nested
elements. Now it is possible to invoke PUT on nested composite attributes for
config-subsystem modules.

Change-Id: I5fde907c66c01a9c1bf58845daa868c7a141c998
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
(cherry picked from commit eb4b35e5e1ea9fa86ec5277a95c0dc882c563862)

opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ArrayAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/AttributeConfigElement.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/CompositeAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/NoneEditConfigStrategy.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_identities_inner_replace.xml [new file with mode: 0644]

index a25a0387ded31ec1e2114a7891dd59c5d0d0cbe2..80e549e719e4c33a242e11f2a02cd847301b8bfe 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attri
 import com.google.common.collect.Lists;
 import java.util.List;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 
 public class ArrayAttributeReadingStrategy extends AbstractAttributeReadingStrategy {
@@ -29,10 +30,17 @@ public class ArrayAttributeReadingStrategy extends AbstractAttributeReadingStrat
     @Override
     AttributeConfigElement readElementHook(List<XmlElement> configNodes) throws NetconfDocumentedException {
         List<Object> innerList = Lists.newArrayList();
+        EditStrategyType innerEditStrategy= null;
         for (XmlElement configNode : configNodes) {
-            innerList.add(innerStrategy.readElement(Lists.newArrayList(configNode)).getValue());
+            final AttributeConfigElement attributeConfigElement = innerStrategy.readElement(Lists.newArrayList(configNode));
+            if(attributeConfigElement.getEditStrategy().isPresent()) {
+                // TODO this sets the last operation for the entire array
+                innerEditStrategy = attributeConfigElement.getEditStrategy().get();
+            }
+            innerList.add(attributeConfigElement.getValue());
         }
-        return AttributeConfigElement.create(getNullableDefault(), innerList);
+        return innerEditStrategy == null ? AttributeConfigElement.create(getNullableDefault(), innerList) :
+                AttributeConfigElement.create(getNullableDefault(), innerList, innerEditStrategy);
     }
 
 }
index 2d5a72b0feefe800b1902b0bf0fd65c319228d55..fac1b358ce52365850bd05c861a8c751bc9c6503 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.base.Optional;
 import javax.management.openmbean.OpenType;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.AttributeResolvingStrategy;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
 
 /**
  * Parsed xml element containing configuration for one attribute of an instance
@@ -20,14 +21,16 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attrib
 public class AttributeConfigElement {
     private final Object defaultValue;
     private final Object value;
+    private final Optional<EditStrategyType> editStrategy;
 
     private Optional<?> resolvedValue;
     private Object resolvedDefaultValue;
     private String jmxName;
 
-    public AttributeConfigElement(Object defaultValue, Object value) {
+    public AttributeConfigElement(Object defaultValue, Object value, final EditStrategyType editStrategyType) {
         this.defaultValue = defaultValue;
         this.value = value;
+        this.editStrategy = Optional.fromNullable(editStrategyType);
     }
 
     public void setJmxName(String jmxName) {
@@ -45,12 +48,20 @@ public class AttributeConfigElement {
         resolvedDefaultValue = resolvedDefault.isPresent() ? resolvedDefault.get() : null;
     }
 
+    public Optional<EditStrategyType> getEditStrategy() {
+        return editStrategy;
+    }
+
     public static AttributeConfigElement create(Object nullableDefault, Object value) {
-        return new AttributeConfigElement(nullableDefault, value);
+        return new AttributeConfigElement(nullableDefault, value, null);
     }
 
     public static AttributeConfigElement createNullValue(Object nullableDefault) {
-        return new AttributeConfigElement(nullableDefault, null);
+        return new AttributeConfigElement(nullableDefault, null, null);
+    }
+
+    public static AttributeConfigElement create(final String nullableDefault, final Object value, final EditStrategyType editStrategyType) {
+        return new AttributeConfigElement(nullableDefault, value, editStrategyType);
     }
 
     public Object getValue() {
index 99c8ef5e99b561683ec20d28d16e3e681da57fa0..3e4957ba67f7a192d21a076eb7affcfad84c7124 100644 (file)
@@ -9,12 +9,15 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
 
 import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 
 public class CompositeAttributeReadingStrategy extends AbstractAttributeReadingStrategy {
@@ -54,7 +57,11 @@ public class CompositeAttributeReadingStrategy extends AbstractAttributeReadingS
 
         complexElement.checkUnrecognisedElements(recognisedChildren);
 
-        return AttributeConfigElement.create(getNullableDefault(), innerMap);
+        String perInstanceEditStrategy = complexElement.getAttribute(XmlNetconfConstants.OPERATION_ATTR_KEY,
+                XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+
+        return Strings.isNullOrEmpty(perInstanceEditStrategy) ? AttributeConfigElement.create(getNullableDefault(), innerMap) :
+                AttributeConfigElement.create(getNullableDefault(), innerMap, EditStrategyType.valueOf(perInstanceEditStrategy));
     }
 
 }
index 87e64c3e1f70b8d28a505deed372e2d8f7c92ffd..83afd708163e2068ddd287aac7058b4330c79480 100644 (file)
@@ -8,8 +8,10 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
 
+import java.util.Collections;
 import java.util.Map;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
 import org.slf4j.Logger;
@@ -21,8 +23,21 @@ public class NoneEditConfigStrategy implements EditConfigStrategy {
 
     @Override
     public void executeConfiguration(String module, String instance, Map<String, AttributeConfigElement> configuration,
-                                     ConfigTransactionClient ta, ServiceRegistryWrapper services) {
-        LOG.debug("Skipping configuration element for {}:{}", module, instance);
+                                     ConfigTransactionClient ta, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
+        if(configuration != null && !configuration.isEmpty()) {
+            for (Map.Entry<String, AttributeConfigElement> attrEntry : configuration.entrySet()) {
+                if(attrEntry.getValue().getEditStrategy().isPresent()) {
+                    final Map<String, AttributeConfigElement> partialConfig =
+                            Collections.singletonMap(attrEntry.getKey(), attrEntry.getValue());
+                    attrEntry.getValue().getEditStrategy().get().getFittingStrategy()
+                            .executeConfiguration(module, instance, partialConfig, ta, services);
+                } else {
+                    LOG.debug("Skipping configuration element for {}:{}:{}", module, instance, attrEntry.getKey());
+                }
+            }
+        } else {
+            LOG.debug("Skipping configuration element for {}:{}", module, instance);
+        }
     }
 
 }
index f95e13dd01180e3ce91c78d78eab14045c1d12b7..c78c80fe2bb849b97650061b87ab038f9d52321f 100644 (file)
@@ -9,6 +9,8 @@
 package org.opendaylight.controller.netconf.confignetconfconnector;
 
 import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
@@ -47,6 +49,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
@@ -57,7 +61,6 @@ import org.custommonkey.xmlunit.NodeTestException;
 import org.custommonkey.xmlunit.NodeTester;
 import org.custommonkey.xmlunit.XMLAssert;
 import org.custommonkey.xmlunit.XMLUnit;
-import org.hamcrest.CoreMatchers;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -215,7 +218,29 @@ public class NetconfMappingTest extends AbstractConfigTest {
         edit("netconfMessages/editConfig_identities.xml");
 
         commit();
-        getConfigRunning();
+        Document configRunning = getConfigRunning();
+        String asString = XmlUtil.toString(configRunning);
+        assertThat(asString, containsString("test-identity2"));
+        assertThat(asString, containsString("test-identity1"));
+        assertEquals(2, countSubstringOccurence(asString, "</identities>"));
+
+        edit("netconfMessages/editConfig_identities_inner_replace.xml");
+        commit();
+        configRunning = getConfigRunning();
+        asString = XmlUtil.toString(configRunning);
+        // test-identity1 was removed by replace
+        assertThat(asString, not(containsString("test-identity2")));
+        // now only 1 identities entry is present
+        assertEquals(1, countSubstringOccurence(asString, "</identities>"));
+    }
+
+    private int countSubstringOccurence(final String string, final String substring) {
+        final Matcher matches = Pattern.compile(substring).matcher(string);
+        int count = 0;
+        while (matches.find()) {
+            count++;
+        }
+        return count;
     }
 
     @Override
@@ -623,7 +648,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
     }
 
     private void assertContainsString(String string, String substring) {
-        assertThat(string, CoreMatchers.containsString(substring));
+        assertThat(string, containsString(substring));
     }
 
     private void checkEnum(final Document response) throws Exception {
diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_identities_inner_replace.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_identities_inner_replace.xml
new file mode 100644 (file)
index 0000000..3529018
--- /dev/null
@@ -0,0 +1,32 @@
+<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>
+            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <module xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+                    <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        test-impl:impl-identity-test
+                    </type>
+                    <name>id-test</name>
+                    <identities xc:operation="replace">
+                        <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity1</afi>
+                        <safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity1</safi>
+                    </identities>
+                    <identities-container xc:operation="replace">
+                        <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity1</afi>
+                    </identities-container>
+                </module>
+            </modules>
+
+            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+
+            </services>
+        </config>
+    </edit-config>
+</rpc>