In preparation for dynamic clustering support:
- Added Cluster metadata service and metadata store interfaces
- Added a static cluster metadata store implementation that is backed by a local file.
- Consolidated the existing cluster.json and tablets.json metadata files into a single cluster.json file that has all the cluster related metadata.
- Removed dependency on ONOS_NIC env variable.

Change-Id: Ia0a8bb69740caecdcdde71a9408be37c56ae2504
diff --git a/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java b/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java
index 5f2b5ff..4794487 100644
--- a/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java
+++ b/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java
@@ -30,9 +30,8 @@
      * instance.
      *
      * @param nodes    set of nodes that form the cluster
-     * @param ipPrefix IP address prefix, e.g. 10.0.1.*
      */
-    void formCluster(Set<ControllerNode> nodes, String ipPrefix);
+    void formCluster(Set<ControllerNode> nodes);
 
     /**
      * Adds a new controller node to the cluster.
diff --git a/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java b/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java
deleted file mode 100644
index 1ee78b1..0000000
--- a/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.cluster;
-
-import java.util.Set;
-
-/**
- * Service for obtaining the static definition of a controller cluster.
- */
-public interface ClusterDefinitionService {
-
-    /**
-     * Returns the local controller node.
-     * @return local controller node
-     */
-    ControllerNode localNode();
-
-    /**
-     * Returns the set of seed nodes that should be used for discovering other members
-     * of the cluster.
-     * @return set of seed controller nodes
-     */
-    Set<ControllerNode> seedNodes();
-
-    /**
-     * Forms cluster configuration based on the specified set of node
-     * information. Assumes subsequent restart for the new configuration to
-     * take hold.
-     *
-     * @param nodes    set of nodes that form the cluster
-     * @param ipPrefix IP address prefix, e.g. 10.0.1.*
-     */
-    void formCluster(Set<ControllerNode> nodes, String ipPrefix);
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java
new file mode 100644
index 0000000..008886d
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Verify.verifyNotNull;
+import static com.google.common.base.Verify.verify;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Cluster metadata.
+ * <p>
+ * Metadata specifies the attributes that define a ONOS cluster and comprises the collection
+ * of {@link org.onosproject.cluster.ControllerNode nodes} and the collection of data
+ * {@link org.onosproject.cluster.Partition partitions}.
+ */
+public final class ClusterMetadata {
+
+    private String name;
+    private Set<ControllerNode> nodes;
+    private Set<Partition> partitions;
+
+    /**
+     * Returns a new cluster metadata builder.
+     * @return The cluster metadata builder.
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Returns the name of the cluster.
+     *
+     * @return cluster name
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * Returns the collection of {@link org.onosproject.cluster.ControllerNode nodes} that make up the cluster.
+     * @return cluster nodes
+     */
+    public Collection<ControllerNode> getNodes() {
+        return this.nodes;
+    }
+
+    /**
+     * Returns the collection of data {@link org.onosproject.cluster.Partition partitions} that make up the cluster.
+     * @return collection of partitions.
+     */
+    public Collection<Partition> getPartitions() {
+        return this.partitions;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(ClusterMetadata.class)
+                .add("name", name)
+                .add("nodes", nodes)
+                .add("partitions", partitions)
+                .toString();
+    }
+
+    /**
+     * Builder for a {@link ClusterMetadata} instance.
+     */
+    public static class Builder {
+
+        private final ClusterMetadata metadata;
+
+        public Builder() {
+            metadata = new ClusterMetadata();
+        }
+
+        /**
+         * Sets the cluster name, returning the cluster metadata builder for method chaining.
+         * @param name cluster name
+         * @return this cluster metadata builder
+         */
+        public Builder withName(String name) {
+            metadata.name = checkNotNull(name);
+            return this;
+        }
+
+        /**
+         * Sets the collection of cluster nodes, returning the cluster metadata builder for method chaining.
+         * @param controllerNodes collection of cluster nodes
+         * @return this cluster metadata builder
+         */
+        public Builder withControllerNodes(Collection<ControllerNode> controllerNodes) {
+            metadata.nodes = ImmutableSet.copyOf(checkNotNull(controllerNodes));
+            return this;
+        }
+
+        /**
+         * Sets the collection of data partitions, returning the cluster metadata builder for method chaining.
+         * @param partitions collection of partitions
+         * @return this cluster metadata builder
+         */
+        public Builder withPartitions(Collection<Partition> partitions) {
+            metadata.partitions = ImmutableSet.copyOf(checkNotNull(partitions));
+            return this;
+        }
+
+        /**
+         * Builds the cluster metadata.
+         * @return cluster metadata
+         * @throws com.google.common.base.VerifyException VerifyException if the metadata is misconfigured
+         */
+        public ClusterMetadata build() {
+            verifyMetadata();
+            return metadata;
+        }
+
+        /**
+         * Validates the constructed metadata for semantic correctness.
+         * @throws VerifyException if the metadata is misconfigured.
+         */
+        private void verifyMetadata() {
+            verifyNotNull(metadata.getName(), "Cluster name must be specified");
+            verifyNotNull(metadata.getNodes(), "Cluster nodes must be specified");
+            verifyNotNull(metadata.getPartitions(), "Cluster partitions must be specified");
+            verify(!metadata.getNodes().isEmpty(), "Cluster nodes must not be empty");
+            verify(!metadata.getPartitions().isEmpty(), "Cluster nodes must not be empty");
+
+            // verify that partitions are constituted from valid cluster nodes.
+            boolean validPartitions = Collections2.transform(metadata.getNodes(), ControllerNode::id)
+                                                  .containsAll(metadata.getPartitions()
+                                                                       .stream()
+                                                                       .flatMap(r -> r.getMembers().stream())
+                                                                       .collect(Collectors.toSet()));
+            verify(validPartitions, "Partition locations must be valid cluster nodes");
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java
new file mode 100644
index 0000000..a0f461c
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes a cluster metadata event.
+ */
+public class ClusterMetadataEvent extends AbstractEvent<ClusterMetadataEvent.Type, ClusterMetadata> {
+
+    /**
+     * Type of cluster metadata events.
+     */
+    public enum Type {
+        /**
+         * Signifies that the cluster metadata has changed.
+         */
+        METADATA_CHANGED,
+    }
+
+    /**
+     * Creates an event of a given type and for the specified metadata and the
+     * current time.
+     *
+     * @param type     cluster metadata event type
+     * @param metadata cluster metadata subject
+     */
+    public ClusterMetadataEvent(Type type, ClusterMetadata metadata) {
+        super(type, metadata);
+    }
+
+    /**
+     * Creates an event of a given type and for the specified metadata and time.
+     *
+     * @param type     cluster metadata event type
+     * @param metadata cluster metadata subject
+     * @param time     occurrence time
+     */
+    public ClusterMetadataEvent(Type type, ClusterMetadata metadata, long time) {
+        super(type, metadata, time);
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java
new file mode 100644
index 0000000..fdfaeed
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving cluster metadata related events.
+ */
+public interface ClusterMetadataEventListener  extends EventListener<ClusterMetadataEvent> {
+}
diff --git a/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java
new file mode 100644
index 0000000..25a6df6
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+/**
+ * Service for obtaining metadata information about the cluster.
+ */
+public interface ClusterMetadataService {
+
+    /**
+     * Returns the current cluster metadata.
+     * @return cluster metadata
+     */
+    ClusterMetadata getClusterMetadata();
+
+    /**
+     * Updates the cluster metadata.
+     * @param metadata new metadata
+     */
+    void setClusterMetadata(ClusterMetadata metadata);
+
+    /**
+     * Returns the local controller node representing this instance.
+     * @return local controller node
+     */
+    ControllerNode getLocalNode();
+}
diff --git a/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java
new file mode 100644
index 0000000..7e83b5b
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import java.util.Collection;
+
+import org.onosproject.store.Store;
+import org.onosproject.store.service.Versioned;
+
+/**
+ * Manages persistence of cluster metadata; not intended for direct use.
+ */
+public interface ClusterMetadataStore extends Store<ClusterMetadataEvent, ClusterMetadataStoreDelegate> {
+
+    /**
+     * Returns the cluster metadata.
+     * <p>
+     * The returned metadata is versioned to aid determining if a metadata instance is more recent than another.
+     * @return cluster metadata
+     */
+    Versioned<ClusterMetadata> getClusterMetadata();
+
+    /**
+     * Updates the cluster metadata.
+     * @param metadata new metadata value
+     */
+    void setClusterMetadata(ClusterMetadata metadata);
+
+    // TODO: The below methods should move to a separate store interface that is responsible for
+    // tracking cluster partition operational state.
+
+    /**
+     * Sets a controller node as an active member of a partition.
+     * <p>
+     * Active members are those replicas that are up to speed with the rest of the system and are
+     * usually capable of participating in the replica state management activities in accordance with
+     * the data consistency and replication protocol in use.
+     * @param partitionId partition identifier
+     * @param nodeId id of controller node
+     */
+    void setActiveReplica(String partitionId, NodeId nodeId);
+
+    /**
+     * Removes a controller node as an active member for a partition.
+     * <p>
+     * Active members are those replicas that are up to speed with the rest of the system and are
+     * usually capable of participating in the replica state management activities in accordance with
+     * the data consistency and replication protocol in use.
+     * @param partitionId partition identifier
+     * @param nodeId id of controller node
+     */
+    void unsetActiveReplica(String partitionId, NodeId nodeId);
+
+    /**
+     * Returns the collection of controller nodes that are the active replicas for a partition.
+     * <p>
+     * Active members are those replicas that are up to speed with the rest of the system and are
+     * usually capable of participating in the replica state management activities in accordance with
+     * the data consistency and replication protocol in use.
+     * @param partitionId partition identifier
+     * @return identifiers of controller nodes that are the active replicas
+     */
+    Collection<NodeId> getActiveReplicas(String partitionId);
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java
new file mode 100644
index 0000000..b56b7a2
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Cluster metadata store delegate abstraction.
+ */
+public interface ClusterMetadataStoreDelegate extends StoreDelegate<ClusterMetadataEvent> {
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/cluster/Partition.java b/core/api/src/main/java/org/onosproject/cluster/Partition.java
new file mode 100644
index 0000000..7590275
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cluster/Partition.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cluster;
+
+import java.util.Collection;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A data partition.
+ * <p>
+ * Partition represents a slice of the data space and is made up of a collection
+ * of {@link org.onosproject.cluster.ControllerNode nodes}
+ * that all maintain copies of this data.
+ */
+public class Partition {
+
+    private final String name;
+    private final Set<NodeId> members;
+
+    private Partition() {
+        name = null;
+        members = null;
+    }
+
+    public Partition(String name, Collection<NodeId> members) {
+        this.name = checkNotNull(name);
+        this.members = ImmutableSet.copyOf(checkNotNull(members));
+    }
+
+    /**
+     * Returns the partition name.
+     * <p>
+     * Each partition is identified by a unique name.
+     * @return partition name
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * Returns the collection of controller node identifiers that make up this partition.
+     * @return collection of controller node identifiers
+     */
+    public Collection<NodeId> getMembers() {
+        return this.members;
+    }
+}
\ No newline at end of file