Merge "Fix for Bug 3"
[controller.git] / opendaylight / netconf / config-netconf-connector / src / main / java / org / opendaylight / controller / netconf / confignetconfconnector / operations / editconfig / EditConfig.java
index be3b01db5debfa6897b30ded968627aede84eaa6..709573c2414c3249917aae4e03851e0f9ada4da8 100644 (file)
@@ -25,8 +25,11 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfigElementResolved;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementDefinition;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementResolved;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser.EditConfigExecution;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
@@ -35,6 +38,7 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
 import java.util.HashMap;
 import java.util.Map;
@@ -60,6 +64,7 @@ public class EditConfig extends AbstractConfigNetconfOperation {
     @VisibleForTesting
     Element getResponseInternal(final Document document,
             final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
+
         if (editConfigExecution.shouldTest()) {
             executeTests(configRegistryClient, editConfigExecution);
         }
@@ -88,9 +93,9 @@ public class EditConfig extends AbstractConfigNetconfOperation {
     }
 
     private void executeTests(ConfigRegistryClient configRegistryClient,
-            EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
+            EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
         try {
-            test(configRegistryClient, editConfigExecution.resolvedXmlElements);
+            test(configRegistryClient, editConfigExecution, editConfigExecution.getDefaultStrategy());
         } catch (IllegalStateException | JmxAttributeValidationException | ValidationException e) {
             logger.warn("Test phase for {} failed", EditConfigXmlParser.EDIT_CONFIG, e);
             final Map<String, String> errorInfo = new HashMap<>();
@@ -101,16 +106,21 @@ public class EditConfig extends AbstractConfigNetconfOperation {
         logger.debug("Test phase for {} operation successful", EditConfigXmlParser.EDIT_CONFIG);
     }
 
-    private void test(ConfigRegistryClient configRegistryClient,
-            Map<String, Multimap<String, ModuleElementResolved>> resolvedModules) {
+    private void test(ConfigRegistryClient configRegistryClient, EditConfigExecution execution,
+            EditStrategyType editStrategyType) {
         ObjectName taON = transactionProvider.getTestTransaction();
         try {
 
             // default strategy = replace wipes config
-            if (EditStrategyType.defaultStrategy() == EditStrategyType.replace) {
+            if (editStrategyType == EditStrategyType.replace) {
                 transactionProvider.wipeTestTransaction(taON);
             }
-            setOnTransaction(configRegistryClient, resolvedModules, taON);
+
+            ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(taON);
+
+            handleMisssingInstancesOnTransaction(ta, execution);
+            setServicesOnTransaction(ta, execution);
+            setOnTransaction(ta, execution);
             transactionProvider.validateTestTransaction(taON);
         } finally {
             transactionProvider.abortTestTransaction(taON);
@@ -122,17 +132,53 @@ public class EditConfig extends AbstractConfigNetconfOperation {
         ObjectName taON = transactionProvider.getOrCreateTransaction();
 
         // default strategy = replace wipes config
-        if (EditStrategyType.defaultStrategy() == EditStrategyType.replace) {
+        if (editConfigExecution.getDefaultStrategy() == EditStrategyType.replace) {
             transactionProvider.wipeTransaction();
         }
-        setOnTransaction(configRegistryClient, editConfigExecution.resolvedXmlElements, taON);
-    }
 
-    private void setOnTransaction(ConfigRegistryClient configRegistryClient,
-            Map<String, Multimap<String, ModuleElementResolved>> resolvedXmlElements, ObjectName taON) {
         ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(taON);
 
-        for (Multimap<String, ModuleElementResolved> modulesToResolved : resolvedXmlElements.values()) {
+        handleMisssingInstancesOnTransaction(ta, editConfigExecution);
+        setServicesOnTransaction(ta, editConfigExecution);
+        setOnTransaction(ta, editConfigExecution);
+    }
+
+    private void setServicesOnTransaction(ConfigTransactionClient ta, EditConfigExecution execution) {
+
+        Services services = execution.getServices();
+
+        Map<String, Map<String, Map<String, Services.ServiceInstance>>> namespaceToServiceNameToRefNameToInstance = services
+                .getNamespaceToServiceNameToRefNameToInstance();
+
+        for (String serviceNamespace : namespaceToServiceNameToRefNameToInstance.keySet()) {
+            for (String serviceName : namespaceToServiceNameToRefNameToInstance.get(serviceNamespace).keySet()) {
+
+                String qnameOfService = getQname(ta, serviceNamespace, serviceName);
+                Map<String, Services.ServiceInstance> refNameToInstance = namespaceToServiceNameToRefNameToInstance
+                        .get(serviceNamespace).get(serviceName);
+
+                for (String refName : refNameToInstance.keySet()) {
+                    ObjectName on = refNameToInstance.get(refName).getObjectName(ta.getTransactionName());
+                    try {
+                        ObjectName saved = ta.saveServiceReference(qnameOfService, refName, on);
+                        logger.debug("Saving service {} with on {} under name {} with service on {}", qnameOfService,
+                                on, refName, saved);
+                    } catch (InstanceNotFoundException e) {
+                        throw new IllegalStateException("Unable to save ref name " + refName + " for instance " + on, e);
+                    }
+                }
+            }
+        }
+    }
+
+    private String getQname(ConfigTransactionClient ta, String namespace, String serviceName) {
+        return ta.getServiceInterfaceName(namespace, serviceName);
+    }
+
+    private void setOnTransaction(ConfigTransactionClient ta, EditConfigExecution execution) {
+
+        for (Multimap<String, ModuleElementResolved> modulesToResolved : execution.getResolvedXmlElements(ta).values()) {
+
             for (Entry<String, ModuleElementResolved> moduleToResolved : modulesToResolved.entries()) {
                 String moduleName = moduleToResolved.getKey();
 
@@ -141,36 +187,61 @@ public class EditConfig extends AbstractConfigNetconfOperation {
 
                 InstanceConfigElementResolved ice = moduleElementResolved.getInstanceConfigElementResolved();
                 EditConfigStrategy strategy = ice.getEditStrategy();
-                strategy.executeConfiguration(moduleName, instanceName, ice.getConfiguration(), ta);
+                strategy.executeConfiguration(moduleName, instanceName, ice.getConfiguration(), ta, execution.getServiceRegistryWrapper(ta));
+            }
+        }
+    }
+
+    private void handleMisssingInstancesOnTransaction(ConfigTransactionClient ta,
+            EditConfigExecution execution) {
+
+        for (Multimap<String,ModuleElementDefinition> modulesToResolved : execution.getModulesDefinition(ta).values()) {
+            for (Entry<String, ModuleElementDefinition> moduleToResolved : modulesToResolved.entries()) {
+                String moduleName = moduleToResolved.getKey();
+
+                ModuleElementDefinition moduleElementDefinition = moduleToResolved.getValue();
+
+                EditConfigStrategy strategy = moduleElementDefinition.getEditStrategy();
+                strategy.executeConfiguration(moduleName, moduleElementDefinition.getInstanceName(), null, ta, execution.getServiceRegistryWrapper(ta));
             }
         }
     }
 
     public static Config getConfigMapping(ConfigRegistryClient configRegistryClient,
-            Map<String, Map<String, ModuleMXBeanEntry>> mBeanEntries) {
-        Map<String, Map<String, ModuleConfig>> factories = transform(configRegistryClient, mBeanEntries);
+            Map<String/* Namespace from yang file */,
+                    Map<String /* Name of module entry from yang file */, ModuleMXBeanEntry>> mBeanEntries) {
+        Map<String, Map<String, ModuleConfig>> factories = transformMbeToModuleConfigs(configRegistryClient, mBeanEntries);
+
         return new Config(factories);
     }
 
-    // TODO refactor
-    private static Map<String, Map<String, ModuleConfig>> transform(final ConfigRegistryClient configRegistryClient,
-            Map<String, Map<String, ModuleMXBeanEntry>> mBeanEntries) {
-        return Maps.transformEntries(mBeanEntries,
-                new Maps.EntryTransformer<String, Map<String, ModuleMXBeanEntry>, Map<String, ModuleConfig>>() {
-
-                    @Override
-                    public Map<String, ModuleConfig> transformEntry(String arg0, Map<String, ModuleMXBeanEntry> arg1) {
-                        return Maps.transformEntries(arg1,
-                                new Maps.EntryTransformer<String, ModuleMXBeanEntry, ModuleConfig>() {
-
-                                    @Override
-                                    public ModuleConfig transformEntry(String key, ModuleMXBeanEntry value) {
-                                        return new ModuleConfig(key, new InstanceConfig(configRegistryClient, value
-                                                .getAttributes()));
-                                    }
-                                });
-                    }
-                });
+    public static Map<String/* Namespace from yang file */,
+            Map<String /* Name of module entry from yang file */, ModuleConfig>> transformMbeToModuleConfigs
+            (final ConfigRegistryClient configRegistryClient, Map<String/* Namespace from yang file */,
+                    Map<String /* Name of module entry from yang file */, ModuleMXBeanEntry>> mBeanEntries) {
+
+        Map<String, Map<String, ModuleConfig>> namespaceToModuleNameToModuleConfig = Maps.newHashMap();
+
+        for (String namespace : mBeanEntries.keySet()) {
+            for (Entry<String, ModuleMXBeanEntry> moduleNameToMbe : mBeanEntries.get(namespace).entrySet()) {
+                String moduleName = moduleNameToMbe.getKey();
+                ModuleMXBeanEntry moduleMXBeanEntry = moduleNameToMbe.getValue();
+
+                ModuleConfig moduleConfig = new ModuleConfig(moduleName, new InstanceConfig(configRegistryClient,
+                        moduleMXBeanEntry.getAttributes()), moduleMXBeanEntry
+                        .getProvidedServices().values());
+
+                Map<String, ModuleConfig> moduleNameToModuleConfig = namespaceToModuleNameToModuleConfig.get(namespace);
+                if(moduleNameToModuleConfig == null) {
+                    moduleNameToModuleConfig = Maps.newHashMap();
+                    namespaceToModuleNameToModuleConfig.put(namespace, moduleNameToModuleConfig);
+                }
+
+                moduleNameToModuleConfig.put(moduleName, moduleConfig);
+            }
+        }
+
+        return namespaceToModuleNameToModuleConfig;
     }
 
     @Override
@@ -184,11 +255,11 @@ public class EditConfig extends AbstractConfigNetconfOperation {
         EditConfigXmlParser.EditConfigExecution editConfigExecution;
         Config cfg = getConfigMapping(configRegistryClient, yangStoreSnapshot.getModuleMXBeanEntryMap());
         try {
-            editConfigExecution = editConfigXmlParser.fromXml(xml, cfg);
+            editConfigExecution = editConfigXmlParser.fromXml(xml, cfg, transactionProvider, configRegistryClient);
         } catch (IllegalStateException e) {
             logger.warn("Error parsing xml", e);
             final Map<String, String> errorInfo = new HashMap<>();
-            errorInfo.put(ErrorTag.missing_attribute.name(), "Missing value for 'target' attribute");
+            errorInfo.put(ErrorTag.missing_attribute.name(), "Error parsing xml: " + e.getMessage());
             throw new NetconfDocumentedException(e.getMessage(), ErrorType.rpc, ErrorTag.missing_attribute,
                     ErrorSeverity.error, errorInfo);
         } catch (final IllegalArgumentException e) {