Provide single point for enforcing config naming convention
[controller.git] / opendaylight / containermanager / api / src / main / java / org / opendaylight / controller / containermanager / ContainerConfig.java
index 01715cc1bf1e98960266f1832460aec1b74942e2..3c086cbce0cd8934653e4f4cab512e87e7a21433 100644 (file)
@@ -20,6 +20,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
+import org.opendaylight.controller.configuration.ConfigurationObject;
 import org.opendaylight.controller.sal.core.ContainerFlow;
 import org.opendaylight.controller.sal.core.NodeConnector;
 import org.opendaylight.controller.sal.match.Match;
@@ -35,11 +36,15 @@ import org.opendaylight.controller.sal.utils.StatusCode;
  * files through java serialization API when saving to/reading from Container
  * Manager startup configuration file.
  */
-@XmlRootElement(name = "container-config")
+@XmlRootElement(name = "containerConfig")
 @XmlAccessorType(XmlAccessType.NONE)
-public class ContainerConfig implements Serializable {
+public class ContainerConfig extends ConfigurationObject implements Serializable {
     private static final long serialVersionUID = 2L;
     private static final String regexName = "^\\w+$";
+    private static final String containerProfile = System.getProperty("container.profile") == null ? "Container"
+            : System.getProperty("container.profile");
+    private static final String ADMIN_SUFFIX = "Admin";
+    private static final String OPERATOR_SUFFIX = "Operator";
 
     @XmlElement
     private String container;
@@ -223,7 +228,7 @@ public class ContainerConfig implements Serializable {
      */
     private Status validateName() {
         // No Container configuration allowed to container default
-        return (container.matches(regexName) && !container.equalsIgnoreCase(GlobalConstants.DEFAULT.toString())) ?
+        return (isValidResourceName(container) && !container.equalsIgnoreCase(GlobalConstants.DEFAULT.toString())) ?
                 new Status(StatusCode.SUCCESS) : new Status(StatusCode.BADREQUEST, "Invalid container name");
     }
 
@@ -311,17 +316,6 @@ public class ContainerConfig implements Serializable {
             return status;
         }
 
-        /* Allow adding ports which are already present
-        if (!ports.isEmpty()) {
-            List<String> intersection = new ArrayList<String>(ports);
-            intersection.retainAll(ncList);
-            if (!intersection.isEmpty()) {
-                return new Status(StatusCode.CONFLICT, "The following node connectors are already part of this container: "
-                        + intersection);
-            }
-        }
-        */
-
         // Add ports
         ports.addAll(ncList);
         return new Status(StatusCode.SUCCESS);
@@ -386,38 +380,35 @@ public class ContainerConfig implements Serializable {
                             config.getName()));
                 }
             }
-        }
-        /*
-         * Revisit the following flow-spec confict validation later based on more testing.
-         */
-         /*
-        if (!delete) {
-            // Check for overlapping container flows in the request
-            int size = cFlowConfigs.size();
-            for (int i = 0; i < size; i++) {
-                ContainerFlowConfig first = cFlowConfigs.get(i);
-                for (int j = i + 1; j < size; j++) {
-                    ContainerFlowConfig second = cFlowConfigs.get(j);
-                    if (first.overlap(second)) {
-                        return new Status(StatusCode.BADREQUEST, String.format(
-                                "Invalid Request: the proposed flow specs overlap: %s <-> %s", first.getName(),
-                                second.getName()));
-                    }
-                }
+        } else {
+            // Check for conflicting names with existing cFlows
+            List<String> conflicting = new ArrayList<String>(existingNames);
+            conflicting.retainAll(proposedNames);
+            if (!conflicting.isEmpty()) {
+                return new Status(StatusCode.CONFLICT,
+                        "Invalid Flow Spec configuration: flow spec name(s) conflict with existing flow specs: "
+                                + conflicting.toString());
             }
-            // Check if any of the proposed container flows overlap with the
-            // existing ones
-            for (ContainerFlowConfig current : cFlowConfigs) {
+
+            /*
+             * Check for conflicting flow spec match (we only check for strict
+             * equality). Remove this in case (*) is reintroduced
+             */
+            if (this.containerFlows != null && !this.containerFlows.isEmpty()) {
+                Set<Match> existingMatches = new HashSet<Match>();
                 for (ContainerFlowConfig existing : this.containerFlows) {
-                    if (current.overlap(existing)) {
-                        return new Status(StatusCode.BADREQUEST, String.format(
-                                "Invalid Request: the proposed flow specs overlap: %s <-> %s", current.getName(),
-                                existing.getName()));
+                    existingMatches.addAll(existing.getMatches());
+                }
+                for (ContainerFlowConfig proposed : cFlowConfigs) {
+                    if (existingMatches.removeAll(proposed.getMatches())) {
+                        return new Status(StatusCode.CONFLICT, String.format(
+                                "Invalid Flow Spec configuration: %s conflicts with existing flow spec",
+                                proposed.getName()));
                     }
                 }
             }
         }
-        */
+
 
         return new Status(StatusCode.SUCCESS);
     }
@@ -625,4 +616,30 @@ public class ContainerConfig implements Serializable {
         }
         return list;
     }
+
+    private String getContainerRole(boolean admin) {
+        return String.format("%s-%s-%s", containerProfile, container, (admin ? ADMIN_SUFFIX : OPERATOR_SUFFIX));
+    }
+
+    /**
+     * Return the well known administrator role for this container
+     *
+     * @return The administrator role for this container
+     */
+    public String getContainerAdminRole() {
+        return getContainerRole(true);
+    }
+
+    /**
+     * Return the well known operator role for this container
+     *
+     * @return The operator role for this container
+     */
+    public String getContainerOperatorRole() {
+        return getContainerRole(false);
+    }
+
+    public String getContainerGroupName() {
+        return String.format("%s-%s", containerProfile, container);
+    }
 }