[ONOS-7088] Distribute storage partitions evenly during upgrades

Change-Id: Id82f86ddedbe6c7de2322717338c5c341177bc9e
diff --git a/core/api/src/main/java/org/onosproject/cluster/DefaultPartition.java b/core/api/src/main/java/org/onosproject/cluster/DefaultPartition.java
index 83ab5b9..d0f2f3d 100644
--- a/core/api/src/main/java/org/onosproject/cluster/DefaultPartition.java
+++ b/core/api/src/main/java/org/onosproject/cluster/DefaultPartition.java
@@ -23,6 +23,7 @@
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
+import org.onosproject.core.Version;
 
 /**
  * Default {@link Partition} implementation.
@@ -30,6 +31,7 @@
 public class DefaultPartition implements Partition {
 
     private final PartitionId id;
+    private final Version version;
     private final Collection<NodeId> members;
 
     /**
@@ -37,6 +39,7 @@
      */
     protected DefaultPartition() {
         id = null;
+        version = null;
         members = null;
     }
 
@@ -44,10 +47,12 @@
      * Constructs a partition.
      *
      * @param id partition identifier
+     * @param version partition version
      * @param members partition member nodes
      */
-    public DefaultPartition(PartitionId id, Collection<NodeId> members) {
+    public DefaultPartition(PartitionId id, Version version, Collection<NodeId> members) {
         this.id = checkNotNull(id);
+        this.version = version;
         this.members = ImmutableSet.copyOf(members);
     }
 
@@ -58,23 +63,30 @@
      */
     public DefaultPartition(Partition other) {
         this.id = checkNotNull(other.getId());
+        this.version = checkNotNull(other.getVersion());
         this.members = ImmutableSet.copyOf(other.getMembers());
     }
 
     @Override
     public PartitionId getId() {
-        return this.id;
+        return id;
+    }
+
+    @Override
+    public Version getVersion() {
+        return version;
     }
 
     @Override
     public Collection<NodeId> getMembers() {
-        return this.members;
+        return members;
     }
 
     @Override
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .add("id", id)
+                .add("version", version)
                 .add("members", members)
                 .toString();
     }
diff --git a/core/api/src/main/java/org/onosproject/cluster/Partition.java b/core/api/src/main/java/org/onosproject/cluster/Partition.java
index c73357d..ebff406 100644
--- a/core/api/src/main/java/org/onosproject/cluster/Partition.java
+++ b/core/api/src/main/java/org/onosproject/cluster/Partition.java
@@ -17,6 +17,8 @@
 
 import java.util.Collection;
 
+import org.onosproject.core.Version;
+
 /**
  * A partition or shard is a group of controller nodes that are work together to maintain state.
  * A ONOS cluster is typically made of of one or partitions over which the the data is partitioned.
@@ -30,6 +32,13 @@
     PartitionId getId();
 
     /**
+     * Returns the partition version.
+     *
+     * @return the partition version
+     */
+    Version getVersion();
+
+    /**
      * Returns the controller nodes that are members of this partition.
      * @return collection of controller node identifiers
      */
diff --git a/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataDiffTest.java b/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataDiffTest.java
index a8ae78f..f97bd6a 100644
--- a/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataDiffTest.java
+++ b/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataDiffTest.java
@@ -24,6 +24,7 @@
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
+import org.onosproject.core.Version;
 
 /**
  * Unit tests for ClusterMetadataDiff.
@@ -35,7 +36,7 @@
         PartitionId pid1 = PartitionId.from(1);
         NodeId nid1 = NodeId.nodeId("10.0.0.1");
         ControllerNode n1 = new DefaultControllerNode(nid1, IpAddress.valueOf("10.0.0.1"), 9876);
-        Partition p1 = new DefaultPartition(pid1, ImmutableSet.of(nid1));
+        Partition p1 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1));
         ClusterMetadata md1 = new ClusterMetadata("foo", ImmutableSet.of(n1), ImmutableSet.of(p1));
         ClusterMetadataDiff diff = new ClusterMetadataDiff(md1, md1);
         assertTrue(diff.nodesAdded().isEmpty());
@@ -53,8 +54,8 @@
         NodeId nid2 = NodeId.nodeId("10.0.0.2");
         ControllerNode n1 = new DefaultControllerNode(nid1, IpAddress.valueOf("10.0.0.1"), 9876);
         ControllerNode n2 = new DefaultControllerNode(nid2, IpAddress.valueOf("10.0.0.2"), 9876);
-        Partition p1 = new DefaultPartition(pid1, ImmutableSet.of(nid1));
-        Partition p12 = new DefaultPartition(pid1, ImmutableSet.of(nid1, nid2));
+        Partition p1 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1));
+        Partition p12 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1, nid2));
         ClusterMetadata md1 = new ClusterMetadata("foo", ImmutableSet.of(n1), ImmutableSet.of(p1));
         ClusterMetadata md12 = new ClusterMetadata("foo", ImmutableSet.of(n1, n2), ImmutableSet.of(p12));
         ClusterMetadataDiff diff = new ClusterMetadataDiff(md1, md12);
@@ -77,8 +78,8 @@
         NodeId nid2 = NodeId.nodeId("10.0.0.2");
         ControllerNode n1 = new DefaultControllerNode(nid1, IpAddress.valueOf("10.0.0.1"), 9876);
         ControllerNode n2 = new DefaultControllerNode(nid2, IpAddress.valueOf("10.0.0.2"), 9876);
-        Partition p1 = new DefaultPartition(pid1, ImmutableSet.of(nid1));
-        Partition p12 = new DefaultPartition(pid1, ImmutableSet.of(nid1, nid2));
+        Partition p1 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1));
+        Partition p12 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1, nid2));
         ClusterMetadata md1 = new ClusterMetadata("foo", ImmutableSet.of(n1), ImmutableSet.of(p1));
         ClusterMetadata md12 = new ClusterMetadata("foo", ImmutableSet.of(n1, n2), ImmutableSet.of(p12));
         ClusterMetadataDiff diff = new ClusterMetadataDiff(md12, md1);
diff --git a/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataEventTest.java b/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataEventTest.java
index 2648d36..036839a 100644
--- a/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataEventTest.java
+++ b/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataEventTest.java
@@ -19,6 +19,7 @@
 import com.google.common.testing.EqualsTester;
 import org.junit.Test;
 import org.onlab.packet.IpAddress;
+import org.onosproject.core.Version;
 
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertThat;
@@ -37,9 +38,9 @@
             new DefaultControllerNode(nid1, IpAddress.valueOf("10.0.0.1"), 9876);
     private final ControllerNode n2 =
             new DefaultControllerNode(nid2, IpAddress.valueOf("10.0.0.2"), 9876);
-    private final Partition p1 = new DefaultPartition(pid1, ImmutableSet.of(nid1));
-    private final Partition p2 = new DefaultPartition(pid2, ImmutableSet.of(nid1, nid2));
-    private final Partition p3 = new DefaultPartition(pid2, ImmutableSet.of(nid2));
+    private final Partition p1 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1));
+    private final Partition p2 = new DefaultPartition(pid2, Version.version("1.0.0"), ImmutableSet.of(nid1, nid2));
+    private final Partition p3 = new DefaultPartition(pid2, Version.version("1.0.0"), ImmutableSet.of(nid2));
     private final ClusterMetadata metadata1 =
             new ClusterMetadata("foo", ImmutableSet.of(n1), ImmutableSet.of(p1));
     private final ClusterMetadata metadata2 =
diff --git a/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataServiceAdapter.java b/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataServiceAdapter.java
index 3904cbc..443ee29 100644
--- a/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataServiceAdapter.java
+++ b/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataServiceAdapter.java
@@ -18,6 +18,7 @@
 import org.onlab.packet.IpAddress;
 
 import com.google.common.collect.Sets;
+import org.onosproject.core.Version;
 
 /**
  * Test adapter for the ClusterMetadata service.
@@ -28,7 +29,7 @@
     public ClusterMetadata getClusterMetadata() {
         final NodeId nid = new NodeId("test-node");
         final IpAddress addr = IpAddress.valueOf(0);
-        final Partition p = new DefaultPartition(PartitionId.from(1), Sets.newHashSet(nid));
+        final Partition p = new DefaultPartition(PartitionId.from(1), Version.version("1.0.0"), Sets.newHashSet(nid));
         return new ClusterMetadata("test-cluster",
                                    Sets.newHashSet(new DefaultControllerNode(nid, addr)),
                                    Sets.newHashSet(p));
diff --git a/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataTest.java b/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataTest.java
index 9d85ae9..3d86d93 100644
--- a/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataTest.java
+++ b/core/api/src/test/java/org/onosproject/cluster/ClusterMetadataTest.java
@@ -19,6 +19,7 @@
 import com.google.common.testing.EqualsTester;
 import org.junit.Test;
 import org.onlab.packet.IpAddress;
+import org.onosproject.core.Version;
 import org.onosproject.net.provider.ProviderId;
 
 import static org.hamcrest.Matchers.contains;
@@ -41,8 +42,8 @@
     private final ControllerNode n2 =
             new DefaultControllerNode(nid2, IpAddress.valueOf("10.0.0.2"), 9876);
 
-    private final Partition p1 = new DefaultPartition(pid1, ImmutableSet.of(nid1));
-    private final Partition p2 = new DefaultPartition(pid2, ImmutableSet.of(nid1, nid2));
+    private final Partition p1 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1));
+    private final Partition p2 = new DefaultPartition(pid2, Version.version("1.0.0"), ImmutableSet.of(nid1, nid2));
 
     private final ClusterMetadata metadata1 =
             new ClusterMetadata("foo", ImmutableSet.of(n1), ImmutableSet.of(p1));
diff --git a/core/api/src/test/java/org/onosproject/cluster/DefaultPartitionTest.java b/core/api/src/test/java/org/onosproject/cluster/DefaultPartitionTest.java
index be711a7..105c94e 100644
--- a/core/api/src/test/java/org/onosproject/cluster/DefaultPartitionTest.java
+++ b/core/api/src/test/java/org/onosproject/cluster/DefaultPartitionTest.java
@@ -21,6 +21,7 @@
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.testing.EqualsTester;
+import org.onosproject.core.Version;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.contains;
@@ -43,13 +44,13 @@
     PartitionId pid2 = new PartitionId(2);
     PartitionId pid3 = new PartitionId(3);
 
-    DefaultPartition partition1 = new DefaultPartition(pid1, ImmutableSet.of(id1));
-    DefaultPartition sameAsPartition1 = new DefaultPartition(pid1, ImmutableSet.of(id1));
+    DefaultPartition partition1 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(id1));
+    DefaultPartition sameAsPartition1 = new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(id1));
 
-    DefaultPartition partition2 = new DefaultPartition(pid2, ImmutableSet.of(id2));
+    DefaultPartition partition2 = new DefaultPartition(pid2, Version.version("1.0.0"), ImmutableSet.of(id2));
     DefaultPartition copyOfPartition2 = new DefaultPartition(partition2);
 
-    DefaultPartition partition3 = new DefaultPartition(pid3, ImmutableSet.of(id1, id2, id3));
+    DefaultPartition partition3 = new DefaultPartition(pid3, Version.version("1.0.0"), ImmutableSet.of(id1, id2, id3));
 
     /**
      * Checks that the default partition implementation is an immutable
diff --git a/core/api/src/test/java/org/onosproject/store/primitives/PartitionEventTest.java b/core/api/src/test/java/org/onosproject/store/primitives/PartitionEventTest.java
index 0aec80a..abcc659 100644
--- a/core/api/src/test/java/org/onosproject/store/primitives/PartitionEventTest.java
+++ b/core/api/src/test/java/org/onosproject/store/primitives/PartitionEventTest.java
@@ -22,6 +22,7 @@
 import org.onosproject.cluster.NodeId;
 import org.onosproject.cluster.Partition;
 import org.onosproject.cluster.PartitionId;
+import org.onosproject.core.Version;
 
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertThat;
@@ -41,9 +42,9 @@
 
 
     private final Partition p1 =
-            new DefaultPartition(pid1, ImmutableSet.of(nid1));
+            new DefaultPartition(pid1, Version.version("1.0.0"), ImmutableSet.of(nid1));
     private final Partition p2 =
-            new DefaultPartition(pid2, ImmutableSet.of(nid1, nid2));
+            new DefaultPartition(pid2, Version.version("1.0.0"), ImmutableSet.of(nid1, nid2));
 
     private final PartitionEvent event1 =
             new PartitionEvent(PartitionEvent.Type.UPDATED, p1, time);