blob: a1562b52e384894737e1402d2aa71d571f51fbae [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.cloudstack.cluster;
import com.cloud.host.Host;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.utils.Ternary;
import com.cloud.vm.VirtualMachine;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import javax.naming.ConfigurationException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.apache.cloudstack.cluster.ClusterDrsService.ClusterDrsImbalanceThreshold;
import static org.apache.cloudstack.cluster.ClusterDrsService.ClusterDrsMetric;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
@RunWith(MockitoJUnitRunner.class)
public class BalancedTest {
@InjectMocks
Balanced balanced;
VirtualMachine vm1, vm2, vm3;
Host destHost;
ServiceOfferingVO serviceOffering;
long clusterId = 1L;
Map<Long, List<VirtualMachine>> hostVmMap;
Map<Long, Ternary<Long, Long, Long>> hostCpuFreeMap, hostMemoryFreeMap;
private AutoCloseable closeable;
@Before
public void setUp() throws NoSuchFieldException, IllegalAccessException {
closeable = MockitoAnnotations.openMocks(this);
vm1 = Mockito.mock(VirtualMachine.class);
vm2 = Mockito.mock(VirtualMachine.class);
vm3 = Mockito.mock(VirtualMachine.class); // vm to migrate
destHost = Mockito.mock(Host.class);
hostVmMap = new HashMap<>();
hostVmMap.put(1L, Collections.singletonList(vm1));
hostVmMap.put(2L, Arrays.asList(vm2, vm3));
serviceOffering = Mockito.mock(ServiceOfferingVO.class);
Mockito.when(vm3.getHostId()).thenReturn(2L);
Mockito.when(destHost.getId()).thenReturn(1L);
Mockito.when(serviceOffering.getCpu()).thenReturn(1);
Mockito.when(serviceOffering.getSpeed()).thenReturn(1000);
Mockito.when(serviceOffering.getRamSize()).thenReturn(1024);
overrideDefaultConfigValue(ClusterDrsImbalanceThreshold, "_defaultValue", "0.5");
hostCpuFreeMap = new HashMap<>();
hostCpuFreeMap.put(1L, new Ternary<>(1000L, 0L, 10000L));
hostCpuFreeMap.put(2L, new Ternary<>(2000L, 0L, 10000L));
hostMemoryFreeMap = new HashMap<>();
hostMemoryFreeMap.put(1L, new Ternary<>(512L * 1024L * 1024L, 0L, 8192L * 1024L * 1024L));
hostMemoryFreeMap.put(2L, new Ternary<>(2048L * 1024L * 1024L, 0L, 8192L * 1024L * 1024L));
}
private void overrideDefaultConfigValue(final ConfigKey configKey, final String name,
final Object o) throws IllegalAccessException, NoSuchFieldException {
Field f = ConfigKey.class.getDeclaredField(name);
f.setAccessible(true);
f.set(configKey, o);
}
@After
public void tearDown() throws Exception {
closeable.close();
}
/**
* <b>needsDrs tests</b>
* <p>Scenarios to test for needsDrs
* <p>1. cluster with cpu metric
* <p>2. cluster with memory metric
* <p>3. cluster with "unknown" metric
* <p>
* <p>CPU imbalance = 0.333
* <p>Memory imbalance = 0.6
*/
/*
1. cluster with cpu metric
0.3333 > 0.5 -> False
*/
@Test
public void needsDrsWithCpu() throws ConfigurationException, NoSuchFieldException, IllegalAccessException {
overrideDefaultConfigValue(ClusterDrsMetric, "_defaultValue", "cpu");
assertFalse(balanced.needsDrs(clusterId, new ArrayList<>(hostCpuFreeMap.values()), new ArrayList<>(hostMemoryFreeMap.values())));
}
/*
2. cluster with memory metric
0.6 > 0.5 -> True
*/
@Test
public void needsDrsWithMemory() throws ConfigurationException, NoSuchFieldException, IllegalAccessException {
overrideDefaultConfigValue(ClusterDrsMetric, "_defaultValue", "memory");
assertTrue(balanced.needsDrs(clusterId, new ArrayList<>(hostCpuFreeMap.values()), new ArrayList<>(hostMemoryFreeMap.values())));
}
/* 3. cluster with "unknown" metric */
@Test
public void needsDrsWithUnknown() throws NoSuchFieldException, IllegalAccessException {
overrideDefaultConfigValue(ClusterDrsMetric, "_defaultValue", "unknown");
assertThrows(ConfigurationException.class, () -> balanced.needsDrs(clusterId, new ArrayList<>(hostCpuFreeMap.values()), new ArrayList<>(hostMemoryFreeMap.values())));
}
/**
* getMetrics tests
* <p>Scenarios to test for getMetrics
* <p>1. cluster with cpu metric
* <p>2. cluster with memory metric
* <p>3. cluster with default metric
* <p>
* <p>Pre
* <p>CPU imbalance = 0.333333
* <p>Memory imbalance = 0.6
* <p>
* <p>Post
* <p>CPU imbalance = 0.3333
* <p>Memory imbalance = 0.2
* <p>
* <p>Cost 512.0
* <p>Benefit (0.6-0.2) * 8192 = 3276.8
*/
/*
1. cluster with cpu metric
improvement = 0.3333 - 0.3333 = 0.0
*/
@Test
public void getMetricsWithCpu() throws NoSuchFieldException, IllegalAccessException, ConfigurationException {
overrideDefaultConfigValue(ClusterDrsMetric, "_defaultValue", "cpu");
Ternary<Double, Double, Double> result = balanced.getMetrics(clusterId, vm3, serviceOffering, destHost,
hostCpuFreeMap, hostMemoryFreeMap, false);
assertEquals(0.0, result.first(), 0.01);
assertEquals(0.0, result.second(), 0.0);
assertEquals(1.0, result.third(), 0.0);
}
/*
2. cluster with memory metric
improvement = 0.6 - 0.2 = 0.4
*/
@Test
public void getMetricsWithMemory() throws NoSuchFieldException, IllegalAccessException, ConfigurationException {
overrideDefaultConfigValue(ClusterDrsMetric, "_defaultValue", "memory");
Ternary<Double, Double, Double> result = balanced.getMetrics(clusterId, vm3, serviceOffering, destHost,
hostCpuFreeMap, hostMemoryFreeMap, false);
assertEquals(0.4, result.first(), 0.01);
assertEquals(0, result.second(), 0.0);
assertEquals(1, result.third(), 0.0);
}
}