[ONOS-7757] Support onos-local and embedded cluster configurations
- Refactor cluster.json to support internal/external nodes ('controller' and 'storage')
- Bootstrap embedded partitions when 'storage' nodes not present
- Update onos-gen-config script to generate cluster.json based on environment variables
- Update setup scenario to ignore missing $OCC# environment variables

Change-Id: Ia93b64e13d7a7c35ed712da4c681425e3ccf9fe9
diff --git a/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java b/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java
index 347c812..7dbf139 100644
--- a/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java
+++ b/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java
@@ -98,7 +98,8 @@
     public ControllerNode getLocalNode() {
         checkPermission(CLUSTER_READ);
         if (localNode == null) {
-            ControllerNode localNode = getProvider().getClusterMetadata().value().getLocalNode();
+            ClusterMetadata metadata = getProvider().getClusterMetadata().value();
+            ControllerNode localNode = metadata.getLocalNode();
             try {
                 if (localNode != null) {
                     this.localNode = new DefaultControllerNode(
@@ -107,7 +108,15 @@
                         localNode.tcpPort());
                 } else {
                     IpAddress ip = findLocalIp();
-                    this.localNode = new DefaultControllerNode(NodeId.nodeId(ip.toString()), ip);
+                    localNode = metadata.getControllerNodes().stream()
+                        .filter(node -> node.ip().equals(ip))
+                        .findFirst()
+                        .orElse(null);
+                    if (localNode != null) {
+                        this.localNode = localNode;
+                    } else {
+                        this.localNode = new DefaultControllerNode(NodeId.nodeId(ip.toString()), ip);
+                    }
                 }
             } catch (SocketException e) {
                 throw new IllegalStateException(e);
diff --git a/core/net/src/main/java/org/onosproject/cluster/impl/ConfigFileBasedClusterMetadataProvider.java b/core/net/src/main/java/org/onosproject/cluster/impl/ConfigFileBasedClusterMetadataProvider.java
index 8086206..e93ce33 100644
--- a/core/net/src/main/java/org/onosproject/cluster/impl/ConfigFileBasedClusterMetadataProvider.java
+++ b/core/net/src/main/java/org/onosproject/cluster/impl/ConfigFileBasedClusterMetadataProvider.java
@@ -28,6 +28,7 @@
 import java.util.stream.Collectors;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.Sets;
 import com.google.common.io.Files;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -111,10 +112,14 @@
     private ClusterMetadataPrototype toPrototype(ClusterMetadata metadata) {
         ClusterMetadataPrototype prototype = new ClusterMetadataPrototype();
         prototype.setName(metadata.getName());
-        prototype.setCluster(metadata.getNodes()
-            .stream()
-            .map(this::toPrototype)
-            .collect(Collectors.toSet()));
+        prototype.setController(metadata.getNodes()
+                .stream()
+                .map(this::toPrototype)
+                .collect(Collectors.toSet()));
+        prototype.setStorage(metadata.getStorageNodes()
+                .stream()
+                .map(this::toPrototype)
+                .collect(Collectors.toSet()));
         return prototype;
     }
 
@@ -241,13 +246,20 @@
                         metadata.getNode().getPort() != null
                             ? metadata.getNode().getPort()
                             : DefaultControllerNode.DEFAULT_PORT) : null,
-                metadata.getCluster()
-                    .stream()
-                    .map(node -> new DefaultControllerNode(
-                        NodeId.nodeId(node.getId()),
-                        IpAddress.valueOf(node.getIp()),
-                        node.getPort() != null ? node.getPort() : 5679))
-                    .collect(Collectors.toSet())),
+                    metadata.getController()
+                        .stream()
+                        .map(node -> new DefaultControllerNode(
+                            NodeId.nodeId(node.getId()),
+                            IpAddress.valueOf(node.getIp()),
+                            node.getPort() != null ? node.getPort() : 5679))
+                        .collect(Collectors.toSet()),
+                    metadata.getStorage()
+                        .stream()
+                        .map(node -> new DefaultControllerNode(
+                            NodeId.nodeId(node.getId()),
+                            IpAddress.valueOf(node.getIp()),
+                            node.getPort() != null ? node.getPort() : 5679))
+                        .collect(Collectors.toSet())),
                 version);
         } catch (IOException e) {
             throw new IllegalArgumentException(e);
@@ -278,7 +290,8 @@
     private static class ClusterMetadataPrototype {
         private String name;
         private NodePrototype node;
-        private Set<NodePrototype> cluster;
+        private Set<NodePrototype> controller = Sets.newHashSet();
+        private Set<NodePrototype> storage = Sets.newHashSet();
 
         public String getName() {
             return name;
@@ -296,12 +309,20 @@
             this.node = node;
         }
 
-        public Set<NodePrototype> getCluster() {
-            return cluster;
+        public Set<NodePrototype> getController() {
+            return controller;
         }
 
-        public void setCluster(Set<NodePrototype> cluster) {
-            this.cluster = cluster;
+        public void setController(Set<NodePrototype> controller) {
+            this.controller = controller;
+        }
+
+        public Set<NodePrototype> getStorage() {
+            return storage;
+        }
+
+        public void setStorage(Set<NodePrototype> storage) {
+            this.storage = storage;
         }
     }
 
diff --git a/core/net/src/main/java/org/onosproject/cluster/impl/DefaultClusterMetadataProvider.java b/core/net/src/main/java/org/onosproject/cluster/impl/DefaultClusterMetadataProvider.java
index aa32da2..a6f24ae 100644
--- a/core/net/src/main/java/org/onosproject/cluster/impl/DefaultClusterMetadataProvider.java
+++ b/core/net/src/main/java/org/onosproject/cluster/impl/DefaultClusterMetadataProvider.java
@@ -73,7 +73,7 @@
         ControllerNode localNode =
                 new DefaultControllerNode(new NodeId(localIp), IpAddress.valueOf(localIp), DEFAULT_ONOS_PORT);
         ClusterMetadata metadata = new ClusterMetadata(
-            PROVIDER_ID, "default", localNode, ImmutableSet.of());
+            PROVIDER_ID, "default", localNode, ImmutableSet.of(), ImmutableSet.of());
         long version = System.currentTimeMillis();
         cachedMetadata.set(new Versioned<>(metadata, version));
         providerRegistry.register(this);