Fix for container directory creation/deletion in startup without saving config
[controller.git] / opendaylight / containermanager / implementation / src / main / java / org / opendaylight / controller / containermanager / internal / ContainerManager.java
index d420bdd0a97a3033a923b02be374384de6b0ceb7..0fee183b67b8c1be06725b310c4111fbf3f9f8a8 100644 (file)
@@ -9,7 +9,6 @@
 
 package org.opendaylight.controller.containermanager.internal;
 
-import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -24,21 +23,28 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.eclipse.osgi.framework.console.CommandInterpreter;
 import org.eclipse.osgi.framework.console.CommandProvider;
+import org.opendaylight.controller.appauth.authorization.Authorization;
 import org.opendaylight.controller.clustering.services.CacheConfigException;
 import org.opendaylight.controller.clustering.services.CacheExistException;
 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
 import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
 import org.opendaylight.controller.configuration.IConfigurationAware;
 import org.opendaylight.controller.configuration.IConfigurationService;
+import org.opendaylight.controller.containermanager.ContainerChangeEvent;
+import org.opendaylight.controller.containermanager.ContainerConfig;
+import org.opendaylight.controller.containermanager.ContainerData;
+import org.opendaylight.controller.containermanager.ContainerFlowChangeEvent;
+import org.opendaylight.controller.containermanager.ContainerFlowConfig;
 import org.opendaylight.controller.containermanager.IContainerAuthorization;
 import org.opendaylight.controller.containermanager.IContainerManager;
+import org.opendaylight.controller.containermanager.NodeConnectorsChangeEvent;
 import org.opendaylight.controller.sal.authorization.AppRoleLevel;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.authorization.Resource;
@@ -56,8 +62,6 @@ import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.IObjectReader;
 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
 import org.opendaylight.controller.sal.utils.NodeCreator;
-import org.opendaylight.controller.sal.utils.ObjectReader;
-import org.opendaylight.controller.sal.utils.ObjectWriter;
 import org.opendaylight.controller.sal.utils.ServiceHelper;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
@@ -65,22 +69,14 @@ import org.opendaylight.controller.topologymanager.ITopologyManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.opendaylight.controller.appauth.authorization.Authorization;
-import org.opendaylight.controller.containermanager.ContainerFlowChangeEvent;
-import org.opendaylight.controller.containermanager.ContainerFlowConfig;
-import org.opendaylight.controller.containermanager.NodeConnectorsChangeEvent;
-import org.opendaylight.controller.containermanager.ContainerChangeEvent;
-import org.opendaylight.controller.containermanager.ContainerConfig;
-import org.opendaylight.controller.containermanager.ContainerData;
-
 public class ContainerManager extends Authorization<String> implements IContainerManager, IObjectReader,
         CommandProvider, ICacheUpdateAware<String, Object>, IContainerInternal, IContainerAuthorization,
         IConfigurationAware {
     private static final Logger logger = LoggerFactory.getLogger(ContainerManager.class);
-    private static String ROOT = GlobalConstants.STARTUPHOME.toString();
-    private static String containersFileName = ROOT + "containers.conf";
+    private static String CONTAINERS_FILE_NAME = "containers.conf";
     private static final String allContainersGroup = "allContainers";
     private IClusterGlobalServices clusterServices;
+    private IConfigurationService configurationService;
     /*
      * Collection containing the configuration objects. This is configuration
      * world: container names (also the map key) are maintained as they were
@@ -172,6 +168,16 @@ public class ContainerManager extends Authorization<String> implements IContaine
         }
     }
 
+    public void setConfigurationService(IConfigurationService service) {
+        logger.trace("Got configuration service set request {}", service);
+        this.configurationService = service;
+    }
+
+    public void unsetConfigurationService(IConfigurationService service) {
+        logger.trace("Got configuration service UNset request");
+        this.configurationService = null;
+    }
+
     private void allocateCaches() {
         logger.debug("Container Manager allocating caches");
 
@@ -232,7 +238,7 @@ public class ContainerManager extends Authorization<String> implements IContaine
 
         roles = (ConcurrentMap<String, AppRoleLevel>) clusterServices.getCache("containermgr.roles");
 
-        if (containerConfigs.size() > 0) {
+        if (inContainerMode()) {
             for (Map.Entry<String, ContainerConfig> entry : containerConfigs.entrySet()) {
                 // Notify global and local listeners about the mode change
                 notifyContainerChangeInternal(entry.getValue(), UpdateType.ADDED, true);
@@ -291,7 +297,7 @@ public class ContainerManager extends Authorization<String> implements IContaine
         createDefaultAuthorizationGroups();
 
         // Read startup configuration and create local database
-        loadConfigurations();
+        loadContainerConfig();
     }
 
     public void destroy() {
@@ -621,9 +627,9 @@ public class ContainerManager extends Authorization<String> implements IContaine
                     String msg = null;
                     ContainerData other = containerData.get(otherContainerName);
                     if (flowSpecList.isEmpty()) {
-                        msg = String.format("Port %s is shared and flow spec is emtpy for this container", port);
+                        msg = String.format("Port %s is shared and flow spec is empty for this container", port);
                     } else if (other.isFlowSpecEmpty()) {
-                        msg = String.format("Port %s is shared and flow spec is emtpy for the other container", port);
+                        msg = String.format("Port %s is shared and flow spec is empty for the other container", port);
                     } else if (!checkCommonContainerFlow(flowSpecList, other.getContainerFlowSpecs()).isSuccess()) {
                         msg = String.format("Port %s is shared and other container has common flow spec", port);
                     }
@@ -729,49 +735,19 @@ public class ContainerManager extends Authorization<String> implements IContaine
         return flowSpecConfig;
     }
 
-    private void loadConfigurations() {
-        /*
-         * Read containers, container flows and finally containers' entries from file
-         * and program the database accordingly
-         */
-        if (containerConfigs.isEmpty()) {
-            loadContainerConfig();
-        }
-    }
-
     private Status saveContainerConfig() {
         return saveContainerConfigLocal();
     }
 
     public Status saveContainerConfigLocal() {
-        ObjectWriter objWriter = new ObjectWriter();
+        Status status = configurationService.persistConfiguration(
+                new ArrayList<ConfigurationObject>(containerConfigs.values()), CONTAINERS_FILE_NAME);
 
-        Status status = objWriter.write(new ConcurrentHashMap<String, ContainerConfig>(containerConfigs), containersFileName);
         if (!status.isSuccess()) {
             return new Status(StatusCode.INTERNALERROR, "Failed to save container configurations: "
                     + status.getDescription());
         }
-        return new Status(StatusCode.SUCCESS);
-    }
-
-    private void removeComponentsStartUpfiles(String containerName) {
-        String startupLocation = String.format("./%s", GlobalConstants.STARTUPHOME.toString());
-        String containerPrint = String.format("_%s.", containerName.toLowerCase(Locale.ENGLISH));
-
-        File directory = new File(startupLocation);
-        String[] fileList = directory.list();
-
-        logger.trace("Deleteing startup configuration files for container {}", containerName);
-        if (fileList != null) {
-            for (String fileName : fileList) {
-                if (fileName.contains(containerPrint)) {
-                    String fullPath = String.format("%s/%s", startupLocation, fileName);
-                    File file = new File(fullPath);
-                    boolean done = file.delete();
-                    logger.trace("{} {}", (done ? "Deleted: " : "Failed to delete: "), fileName);
-                }
-            }
-        }
+        return status;
     }
 
     /**
@@ -826,15 +802,12 @@ public class ContainerManager extends Authorization<String> implements IContaine
      * @param containerName
      * @param delete
      */
-    private void updateResourceGroups(String containerName, boolean delete) {
-        String containerProfile = System.getProperty("container.profile");
-        if (containerProfile == null) {
-            containerProfile = "Container";
-        }
+    private void updateResourceGroups(ContainerConfig containerConf, boolean delete) {
         // Container Roles and Container Resource Group
-        String groupName = containerProfile+"-" + containerName;
-        String containerAdminRole = containerProfile+"-" + containerName + "-Admin";
-        String containerOperatorRole = containerProfile+"-" + containerName + "-Operator";
+        String containerName = containerConf.getContainer();
+        String groupName = containerConf.getContainerGroupName();
+        String containerAdminRole = containerConf.getContainerAdminRole();
+        String containerOperatorRole = containerConf.getContainerOperatorRole();
         Set<String> allContainerSet = resourceGroups.get(allResourcesGroupName);
         if (delete) {
             resourceGroups.remove(groupName);
@@ -900,7 +873,7 @@ public class ContainerManager extends Authorization<String> implements IContaine
      */
     private void notifyContainerModeChange(boolean lastActionDelete, boolean notifyLocal) {
         if (lastActionDelete == false && containerConfigs.size() == 1) {
-            logger.info("First container Creation. Inform listeners");
+            logger.trace("First container Creation. Inform listeners");
             synchronized (this.iContainerListener) {
                 for (IContainerListener i : this.iContainerListener) {
                     i.containerModeUpdated(UpdateType.ADDED);
@@ -914,7 +887,7 @@ public class ContainerManager extends Authorization<String> implements IContaine
                 }
             }
         } else if (lastActionDelete == true && containerConfigs.isEmpty()) {
-            logger.info("Last container Deletion. Inform listeners");
+            logger.trace("Last container Deletion. Inform listeners");
             synchronized (this.iContainerListener) {
                 for (IContainerListener i : this.iContainerListener) {
                     i.containerModeUpdated(UpdateType.REMOVED);
@@ -932,7 +905,7 @@ public class ContainerManager extends Authorization<String> implements IContaine
 
     private Status addRemoveContainerEntries(String containerName, List<String> nodeConnectorsString, boolean delete) {
         // Construct action message
-        String action = String.format("Node conenctor(s) %s container %s: %s", delete ? "removal from" : "addition to",
+        String action = String.format("Node connector(s) %s container %s: %s", delete ? "removal from" : "addition to",
                 containerName, nodeConnectorsString);
 
         // Validity Check
@@ -1194,19 +1167,6 @@ public class ContainerManager extends Authorization<String> implements IContaine
             return status;
         }
 
-        /*
-         * This is a quick fix until configuration service becomes the
-         * centralized configuration management place. Here container manager will
-         * remove the startup files for all the bundles that are present in the
-         * container being deleted. Do the cleanup here in Container manger as do not
-         * want to put this temporary code in Configuration manager yet which is
-         * ODL.
-         */
-        if (delete) {
-            // TODO: remove when Config Mgr takes over
-            removeComponentsStartUpfiles(containerName);
-        }
-
         /*
          * Update Configuration: This will trigger the notifications on cache
          * update callback locally and on the other cluster nodes
@@ -1218,7 +1178,7 @@ public class ContainerManager extends Authorization<String> implements IContaine
         }
 
         // Automatically create and populate user and resource groups
-        updateResourceGroups(containerName, delete);
+        updateResourceGroups(containerConf, delete);
 
         // Notify global and local listeners
         UpdateType update = (delete) ? UpdateType.REMOVED : UpdateType.ADDED;
@@ -1339,18 +1299,9 @@ public class ContainerManager extends Authorization<String> implements IContaine
         return ois.readObject();
     }
 
-    @SuppressWarnings("unchecked")
     private void loadContainerConfig() {
-        ObjectReader objReader = new ObjectReader();
-        ConcurrentMap<String, ContainerConfig> configMap = (ConcurrentMap<String, ContainerConfig>) objReader.read(this,
-                containersFileName);
-
-        if (configMap == null) {
-            return;
-        }
-
-        for (Map.Entry<String, ContainerConfig> configEntry : configMap.entrySet()) {
-            addContainer(configEntry.getValue());
+        for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, CONTAINERS_FILE_NAME)) {
+            addContainer((ContainerConfig) conf);
         }
     }
 
@@ -1402,10 +1353,6 @@ public class ContainerManager extends Authorization<String> implements IContaine
             return;
         }
         String staticVlan = ci.nextArgument();
-        if (staticVlan == null) {
-            ci.print("Static Vlan not specified");
-            return;
-        }
         ContainerConfig containerConfig = new ContainerConfig(containerName, staticVlan, null, null);
         ci.println(this.addRemoveContainer(containerConfig, false));
     }
@@ -1667,4 +1614,9 @@ public class ContainerManager extends Authorization<String> implements IContaine
     public boolean hasNonDefaultContainer() {
         return !containerConfigs.keySet().isEmpty();
     }
+
+    @Override
+    public boolean inContainerMode() {
+        return this.containerConfigs.size() > 0;
+    }
 }