diff --git a/rebalance-zone-expansion.sh b/rebalance-zone-expansion.sh index 51e4a356b0..f37f4775ad 100755 --- a/rebalance-zone-expansion.sh +++ b/rebalance-zone-expansion.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -e # # Copyright 2013 LinkedIn, Inc @@ -15,21 +15,23 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This script uses getopts which means only a single character switch are allowed. +# This script uses getopts which means only single character switches are allowed. # Using getopt would allow for multi charcter switch names but would come at a -# cost of being cross compatibility. +# cost of not being cross compatibility. +# This script generates a cluster.xml and a plan for the zone expansion # Argument = -v vold_home -c current_cluster -s current_stores -i interim_cluster -f final_stores # -o output dir # Function to display usage usage_and_exit() { + echo "ERROR: $1." cat < emptyList(), false, null, 0, @@ -256,6 +259,65 @@ public void verifyRandomSwapsImproveBalance(Cluster currentCluster, assertTrue(repartitionedPb.getUtility() < currentPb.getUtility()); } + /** + * Verify that random swaps within improve balance + * + * @param currentCluster + * @param currentStores + * @param swapZoneIds + */ + public void verifyRandomSwapsWithinZoneOnlyShufflesParitionsInThatZone(Cluster currentCluster, + List currentStores, + List swapZoneIds) { + + PartitionBalance currentPb = new PartitionBalance(currentCluster, currentStores); + // Disable basic balancing among zones & nodes + boolean disableNodeBalancing = true; + boolean disableZoneBalancing = true; + // Do some random swaps within zone + boolean enableRandomSwaps = true; + int swapAttempts = 100; + int swapSuccesses = 10; + Cluster repartitionedCluster = Repartitioner.repartition(currentCluster, + currentStores, + currentCluster, + currentStores, + null, + 1, + disableNodeBalancing, + disableZoneBalancing, + enableRandomSwaps, + swapAttempts, + swapSuccesses, + swapZoneIds, + false, + null, + 0, + 0, + 0, + 0); + PartitionBalance repartitionedPb = new PartitionBalance(repartitionedCluster, currentStores); + + Set allNodeIds = repartitionedCluster.getNodeIds(); + Set swapNodeIds = null; + for (Integer swapZoneId: swapZoneIds) { + swapNodeIds = repartitionedCluster.getNodeIdsInZone(swapZoneId); + } + // Remove nodes that we don't want to verify the partition count on + allNodeIds.removeAll(swapNodeIds); + for (Integer remainingNodeId : allNodeIds) { + Set beforeRepartition = new HashSet(currentCluster + .getNodeById(remainingNodeId) + .getPartitionIds()); + Set afterRepartition = new HashSet(currentCluster + .getNodeById(remainingNodeId) + .getPartitionIds()); + assertTrue(beforeRepartition.equals(afterRepartition)); + assertTrue(repartitionedPb.getUtility() <= currentPb.getUtility()); + } + + } + /** * Verify that greedy swaps improve balance. * @@ -388,6 +450,39 @@ public void testShuffle() { verifyGreedySwapsImproveBalance(currentCluster, storeDefs); } + @Test + public void testShuffleWithinZone() { + // Two zone cluster + Cluster currentCluster = ClusterTestUtils.getZZCluster(); + List storeDefs = ClusterTestUtils.getZZStoreDefsInMemory(); + List swapZoneIds = new ArrayList(); + // Only shuffle within zone 1 + swapZoneIds.add(1); + verifyRandomSwapsWithinZoneOnlyShufflesParitionsInThatZone(currentCluster, storeDefs, + swapZoneIds); + + // Three zone cluster + currentCluster = ClusterTestUtils.getZZZCluster(); + storeDefs = ClusterTestUtils.getZZZStoreDefsInMemory(); + // Shuffle only within zone 2 + swapZoneIds.clear(); + swapZoneIds.add(2); + verifyRandomSwapsWithinZoneOnlyShufflesParitionsInThatZone(currentCluster, storeDefs, + swapZoneIds); + // Shuffle only within zone 1, 2 + swapZoneIds.clear(); + swapZoneIds.add(1); + swapZoneIds.add(2); + verifyRandomSwapsWithinZoneOnlyShufflesParitionsInThatZone(currentCluster, storeDefs, + swapZoneIds); + // Shuffle only within zone 0, 2 + swapZoneIds.clear(); + swapZoneIds.add(0); + swapZoneIds.add(2); + verifyRandomSwapsWithinZoneOnlyShufflesParitionsInThatZone(currentCluster, storeDefs, + swapZoneIds); + } + @Test public void testClusterExpansion() { // Two zone cluster