creating a default subnet
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / ConfigTransactionControllerImpl.java
index 5038079c227b00ca487b035d9c2fec4bccf5d2f2..343d45a236e99bd9208ff4846d13c1e0a43bc571 100644 (file)
@@ -7,22 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl;
 
-import static java.lang.String.format;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.DynamicMBean;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.config.api.ValidationException;
@@ -34,14 +18,32 @@ import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtom
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HierarchicalConfigMBeanFactoriesHolder;
 import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistrator;
 import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator;
-import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator
-        .TransactionModuleJMXRegistration;
+import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
 import org.opendaylight.controller.config.manager.impl.util.LookupBeansUtil;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.DynamicMBean;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static java.lang.String.format;
+
 /**
  * This is a JMX bean representing current transaction. It contains
  * {@link #transactionIdentifier}, unique version and parent version for
@@ -49,9 +51,9 @@ import org.slf4j.LoggerFactory;
  */
 class ConfigTransactionControllerImpl implements
         ConfigTransactionControllerInternal,
-        ConfigTransactionControllerImplMXBean {
-    private static final Logger logger = LoggerFactory
-            .getLogger(ConfigTransactionControllerImpl.class);
+        ConfigTransactionControllerImplMXBean,
+        Identifiable<TransactionIdentifier>{
+    private static final Logger logger = LoggerFactory.getLogger(ConfigTransactionControllerImpl.class);
 
     private final TransactionIdentifier transactionIdentifier;
     private final ObjectName controllerON;
@@ -62,6 +64,7 @@ class ConfigTransactionControllerImpl implements
     private final DependencyResolverManager dependencyResolverManager;
     private final TransactionStatus transactionStatus;
     private final MBeanServer transactionsMBeanServer;
+    private final List<ModuleFactory> currentlyRegisteredFactories;
 
     /**
      * Disables ability of {@link DynamicWritableWrapper} to change attributes
@@ -74,11 +77,13 @@ class ConfigTransactionControllerImpl implements
             configBeanModificationDisabled);
     private final MBeanServer configMBeanServer;
 
+    private final BundleContext bundleContext;
+
     public ConfigTransactionControllerImpl(String transactionName,
-            TransactionJMXRegistrator transactionRegistrator,
-            long parentVersion, long currentVersion,
-            List<? extends ModuleFactory> currentlyRegisteredFactories,
-            MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer) {
+                                           TransactionJMXRegistrator transactionRegistrator,
+                                           long parentVersion, long currentVersion,
+                                           List<ModuleFactory> currentlyRegisteredFactories,
+                                           MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer, BundleContext bundleContext) {
 
         this.transactionIdentifier = new TransactionIdentifier(transactionName);
         this.controllerON = ObjectNameUtil
@@ -88,17 +93,70 @@ class ConfigTransactionControllerImpl implements
                 .createTransactionModuleJMXRegistrator();
         this.parentVersion = parentVersion;
         this.currentVersion = currentVersion;
-        this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(
-                currentlyRegisteredFactories);
+        this.currentlyRegisteredFactories = currentlyRegisteredFactories;
+        this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
         this.transactionStatus = new TransactionStatus();
-        this.dependencyResolverManager = new DependencyResolverManager(
-                transactionName, transactionStatus);
+        this.dependencyResolverManager = new DependencyResolverManager(transactionName, transactionStatus);
         this.transactionsMBeanServer = transactionsMBeanServer;
         this.configMBeanServer = configMBeanServer;
+        this.bundleContext = bundleContext;
     }
 
     @Override
-    public synchronized void copyExistingModule(
+    public void copyExistingModulesAndProcessFactoryDiff(Collection<ModuleInternalInfo> existingModules, List<ModuleFactory> lastListOfFactories) {
+        // copy old configuration to this server
+        for (ModuleInternalInfo oldConfigInfo : existingModules) {
+            try {
+                copyExistingModule(oldConfigInfo);
+            } catch (InstanceAlreadyExistsException e) {
+                throw new IllegalStateException("Error while copying " + oldConfigInfo, e);
+            }
+        }
+        processDefaultBeans(lastListOfFactories);
+    }
+
+    private synchronized void processDefaultBeans(List<ModuleFactory> lastListOfFactories) {
+        transactionStatus.checkNotCommitStarted();
+        transactionStatus.checkNotAborted();
+
+        Set<ModuleFactory> oldSet = new HashSet<>(lastListOfFactories);
+        Set<ModuleFactory> newSet = new HashSet<>(currentlyRegisteredFactories);
+
+        List<ModuleFactory> toBeAdded = new ArrayList<>();
+        List<ModuleFactory> toBeRemoved = new ArrayList<>();
+        for(ModuleFactory moduleFactory: currentlyRegisteredFactories) {
+            if (oldSet.contains(moduleFactory) == false){
+                toBeAdded.add(moduleFactory);
+            }
+        }
+        for(ModuleFactory moduleFactory: lastListOfFactories){
+            if (newSet.contains(moduleFactory) == false) {
+                toBeRemoved.add(moduleFactory);
+            }
+        }
+        // add default modules
+        for (ModuleFactory moduleFactory : toBeAdded) {
+            Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager, bundleContext);
+            for (Module module : defaultModules) {
+                try {
+                    putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null);
+                } catch (InstanceAlreadyExistsException e) {
+                    throw new IllegalStateException(e);
+                }
+            }
+        }
+
+        // remove modules belonging to removed factories
+        for(ModuleFactory removedFactory: toBeRemoved){
+            List<ModuleIdentifier> modulesOfRemovedFactory = dependencyResolverManager.findAllByFactory(removedFactory);
+            for (ModuleIdentifier name : modulesOfRemovedFactory) {
+                destroyModule(name);
+            }
+        }
+    }
+
+
+    private synchronized void copyExistingModule(
             ModuleInternalInfo oldConfigBeanInfo)
             throws InstanceAlreadyExistsException {
         transactionStatus.checkNotCommitStarted();
@@ -115,14 +173,13 @@ class ConfigTransactionControllerImpl implements
         try {
             module = moduleFactory.createModule(
                     moduleIdentifier.getInstanceName(), dependencyResolver,
-                    oldConfigBeanInfo.getReadableModule());
+                    oldConfigBeanInfo.getReadableModule(), bundleContext);
         } catch (Exception e) {
             throw new IllegalStateException(format(
                     "Error while copying old configuration from %s to %s",
                     oldConfigBeanInfo, moduleFactory), e);
         }
-        putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module,
-                moduleFactory, oldConfigBeanInfo);
+        putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo);
     }
 
     @Override
@@ -131,17 +188,13 @@ class ConfigTransactionControllerImpl implements
 
         transactionStatus.checkNotCommitStarted();
         transactionStatus.checkNotAborted();
-        ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName,
-                instanceName);
+        ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName);
         dependencyResolverManager.assertNotExists(moduleIdentifier);
 
         // find factory
-        ModuleFactory moduleFactory = factoriesHolder
-                .findByModuleName(factoryName);
-        DependencyResolver dependencyResolver = dependencyResolverManager
-                .getOrCreate(moduleIdentifier);
-        Module module = moduleFactory.createModule(instanceName,
-                dependencyResolver);
+        ModuleFactory moduleFactory = factoriesHolder.findByModuleName(factoryName);
+        DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
+        Module module = moduleFactory.createModule(instanceName, dependencyResolver, bundleContext);
         return putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module,
                 moduleFactory, null);
     }
@@ -151,7 +204,11 @@ class ConfigTransactionControllerImpl implements
             ModuleFactory moduleFactory,
             @Nullable ModuleInternalInfo maybeOldConfigBeanInfo)
             throws InstanceAlreadyExistsException {
-
+        logger.debug("Adding module {} to transaction {}", moduleIdentifier, this);
+        if (moduleIdentifier.equals(module.getIdentifier())==false) {
+            throw new IllegalStateException("Incorrect name reported by module. Expected "
+             + moduleIdentifier + ", got " + module.getIdentifier());
+        }
         DynamicMBean writableDynamicWrapper = new DynamicWritableWrapper(
                 module, moduleIdentifier, transactionIdentifier,
                 readOnlyAtomicBoolean, transactionsMBeanServer,
@@ -167,6 +224,8 @@ class ConfigTransactionControllerImpl implements
                 maybeOldConfigBeanInfo, transactionModuleJMXRegistration);
 
         dependencyResolverManager.put(moduleInternalTransactionalInfo);
+        // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
+        dependencyResolverManager.getOrCreate(moduleIdentifier);
         return writableON;
     }
 
@@ -180,11 +239,15 @@ class ConfigTransactionControllerImpl implements
                     + objectName);
         }
         ObjectNameUtil.checkDomain(objectName);
-        transactionStatus.checkNotAborted();
         ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(objectName,
                 ObjectNameUtil.TYPE_MODULE);
-        ModuleInternalTransactionalInfo removedTInfo = dependencyResolverManager
-                .destroyModule(moduleIdentifier);
+        destroyModule(moduleIdentifier);
+    }
+
+    private void destroyModule(ModuleIdentifier moduleIdentifier) {
+        logger.debug("Destroying module {} in transaction {}", moduleIdentifier, this);
+        transactionStatus.checkNotAborted();
+        ModuleInternalTransactionalInfo removedTInfo = dependencyResolverManager.destroyModule(moduleIdentifier);
         // remove from jmx
         removedTInfo.getTransactionModuleJMXRegistration().close();
     }
@@ -284,7 +347,7 @@ class ConfigTransactionControllerImpl implements
             ModuleIdentifier name = entry.getKey();
             try {
                 logger.debug("About to commit {} in transaction {}",
-                        transactionIdentifier, name);
+                        name, transactionIdentifier);
                 module.getInstance();
             } catch (Exception e) {
                 logger.error("Commit failed on {} in transaction {}", name,
@@ -395,4 +458,14 @@ class ConfigTransactionControllerImpl implements
     public TransactionIdentifier getName() {
         return transactionIdentifier;
     }
+
+    @Override
+    public List<ModuleFactory> getCurrentlyRegisteredFactories() {
+        return currentlyRegisteredFactories;
+    }
+
+    @Override
+    public TransactionIdentifier getIdentifier() {
+        return transactionIdentifier;
+    }
 }