/*************************************************************************** * Copyright (c) 2013 VMware, Inc. All Rights Reserved. * 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 com.vmware.vhadoop.vhm; import java.util.Iterator; import java.util.PriorityQueue; import java.util.Set; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.vmware.vhadoop.api.vhm.ClusterMapReader; import com.vmware.vhadoop.api.vhm.strategy.VMChooser.RankedVM; import com.vmware.vhadoop.vhm.strategy.BalancedVMChooser; import static org.junit.Assert.*; public class TestBalancedVMChooser extends AbstractJUnitTest { BalancedVMChooser _chooser; StandaloneSimpleClusterMap _map; ClusterMapReader _parentClusterMapReader; @Before public void init() { _chooser = new BalancedVMChooser(); _map = new StandaloneSimpleClusterMap(true); _chooser.initialize(getTestClusterMapReader(_map)); } @After public void destroy() { MultipleReaderSingleWriterClusterMapAccess.destroy(); } @Test public void testDisableAll() { Set<String> clusters = _map.getAllKnownClusterIds(); if (clusters != null) { for (String clusterId : clusters) { Set<String> candidateVmIds = _map.listComputeVMsForClusterAndPowerState(clusterId, true); Set<RankedVM> rankedVMs = _chooser.rankVMsToDisable(clusterId, candidateVmIds); assertEquals(candidateVmIds.size(), rankedVMs.size()); } } } @Test public void testEnableAll() { Set<String> clusters = _map.getAllKnownClusterIds(); if (clusters != null) { for (String clusterId : clusters) { Set<String> candidateVmIds = _map.listComputeVMsForClusterAndPowerState(clusterId, false); Set<RankedVM> rankedVMs = _chooser.rankVMsToEnable(clusterId, candidateVmIds); assertEquals(candidateVmIds.size(), rankedVMs.size()); } } } private void chooseVMsAndSetPowerState(String clusterId, int numToChoose, Integer expectedCandidateSize, boolean targetPowerState) { Set<String> candidateVmIds = _map.listComputeVMsForClusterAndPowerState(clusterId, !targetPowerState); if (expectedCandidateSize != null) { assertEquals((long)expectedCandidateSize, candidateVmIds.size()); } Set<RankedVM> rankedVMs = targetPowerState ? _chooser.rankVMsToEnable(clusterId, candidateVmIds) : _chooser.rankVMsToDisable(clusterId, candidateVmIds); PriorityQueue<RankedVM> orderedQueue = new PriorityQueue<RankedVM>(rankedVMs); RankedVM current = null; for (int cntr=0; (cntr < numToChoose) && ((current = orderedQueue.poll()) != null); cntr++) { assertEquals(!targetPowerState, _map.setPowerStateForVM(current.getVmId(), targetPowerState)); } } @Test public void testIncrementalEnableAll() { String clusterId = "clusterA"; _map.clearMap(); int i = 0; for (i = 0; i < 7; i++) { /* 7 powered on */ _map.addVMToMap("vm"+i, clusterId, "hostX", true); } for (; i < 13; i++) { /* 6 powered off */ _map.addVMToMap("vm"+i, clusterId, "hostX", false); } for (; i < 20; i++) { /* 7 powered off */ _map.addVMToMap("vm"+i, clusterId, "hostY", false); } /* choose and power on 6, should all be host Y */ chooseVMsAndSetPowerState(clusterId, 6, 13, true); /* power off 3 on hostX */ for (i = 0; i < 3; i++) { assertTrue(_map.setPowerStateForVM("vm"+i, false)); } /* now hostX should have 4 on, and hostY should have 6, power on 3 should have 2 on hostX and 1 on either */ Set<String> candidateVmIds = _map.listComputeVMsForClusterAndPowerState(clusterId, false); Set<RankedVM> rankedVMs = _chooser.rankVMsToEnable(clusterId, candidateVmIds); assertEquals(10, rankedVMs.size()); Iterator<RankedVM> iterator = rankedVMs.iterator(); int x = 0, y = 0; for (int cntr=0; (cntr < 3) && (iterator.hasNext()); cntr++) { RankedVM vm = iterator.next(); String hostId = _map.getHostIdForVm(vm.getVmId()); if (hostId.equals("hostX")) { x++; } else { y++; } } assertTrue("expected 2 or 3 VMs powered on on hostX", x >= 2); assertTrue("expected at most 1 VM powered on on hostY", y <= 1); } /* 19 powered on and 24 powered off: * Host X: 6 on; 3 off; 9 total * Host Y: 10 on; 0 off; 10 total * Host A: 1 on; 10 off; 11 total * Host B: 1 on; 11 off; 11 total * Host C: 1 on; 0 off: 1 total */ private void createUnevenDistribution() { String clusterId = "clusterA"; _map.clearMap(); int vm = 0; for (int i = 0; i < 6; i++, vm++) { _map.addVMToMap("vm"+vm, clusterId, "hostX", true); } for (int i = 0; i < 3; i++, vm++) { _map.addVMToMap("vm"+vm, clusterId, "hostX", false); } for (int i = 0; i < 10; i++, vm++) { _map.addVMToMap("vm"+vm, clusterId, "hostY", true); } _map.addVMToMap("vm"+vm++, clusterId, "hostA", true); for (int i = 0; i < 10; i++, vm++) { _map.addVMToMap("vm"+vm, clusterId, "hostA", false); } _map.addVMToMap("vm"+vm++, clusterId, "hostB", true); for (int i = 0; i < 11; i++, vm++) { _map.addVMToMap("vm"+vm, clusterId, "hostB", false); } _map.addVMToMap("vm"+vm++, clusterId, "hostC", true); } @Test public void testUnevenDistributionPowerOff() { String clusterId = "clusterA"; createUnevenDistribution(); /* Power off 9 */ chooseVMsAndSetPowerState(clusterId, 9, 19, false); assertTrue("Expected no change in hostA", _map.listComputeVMsForClusterHostAndPowerState(clusterId, "hostA", true).size() == 1); assertTrue("Expected no change in hostB", _map.listComputeVMsForClusterHostAndPowerState(clusterId, "hostB", true).size() == 1); assertTrue("Expected no change in hostC", _map.listComputeVMsForClusterHostAndPowerState(clusterId, "hostC", true).size() == 1); int num = _map.listComputeVMsForClusterHostAndPowerState(clusterId, "hostX", true).size(); assertTrue("Expected hostX to have 3 or 4 VMs powered on, found "+num, num == 3 || num == 4); num = _map.listComputeVMsForClusterHostAndPowerState(clusterId, "hostY", true).size(); assertTrue("Expected hostY to have 3 or 4 VMs powered on, found "+num, num == 3 || num == 4); } @Test public void testUnevenDistributionPowerOffAndOn() { String clusterId = "clusterA"; createUnevenDistribution(); /* Power off 9 */ System.out.println("*** POWER OFF 9 ***"); chooseVMsAndSetPowerState(clusterId, 9, 19, false); /* Power on 11 */ System.out.println("*** POWER ON 11 ***"); chooseVMsAndSetPowerState(clusterId, 11, 33, true); String hosts[] = new String[] { "hostX", "hostY", "hostA", "hostB"} ; for (String host : hosts) { int num = _map.listComputeVMsForClusterHostAndPowerState(clusterId, host, true).size(); assertEquals("Expected "+host+" to have 5 VMs powered on, found "+num, 5, num); } int num = _map.listComputeVMsForClusterHostAndPowerState(clusterId, "hostC", true).size(); assertEquals("Expected hostC to have 1 VMs powered on, found "+num, 1, num); } }