cloudstack/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java
Harikrishna Patnala b83b8eb838 CLOUDSTACK-2502: Scalevm and over provisioning should respect each other
During Scale up of VM, memory/cpu calculations should consider the memory/cpu overprovisioning factors which are set per cluster.

CLOUDSTACK-2939:  CPU limit is not getting set for vm after scaleup to a service offering which have cpu cap enabled

Signed-off-by: Abhinandan Prateek <aprateek@apache.org>
2013-06-13 16:30:56 +05:30

447 lines
19 KiB
Java

// 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 com.cloud.vm;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.ScaleVmAnswer;
import com.cloud.agent.api.ScaleVmCommand;
import com.cloud.capacity.CapacityManager;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.server.ConfigurationServer;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeManager;
import com.cloud.storage.VolumeVO;
import com.cloud.agent.api.PrepareForMigrationAnswer;
import com.cloud.agent.api.PrepareForMigrationCommand;
import com.cloud.agent.api.MigrateWithStorageAnswer;
import com.cloud.agent.api.MigrateWithStorageCommand;
import com.cloud.agent.api.MigrateWithStorageReceiveAnswer;
import com.cloud.agent.api.MigrateWithStorageReceiveCommand;
import com.cloud.agent.api.MigrateWithStorageSendAnswer;
import com.cloud.agent.api.MigrateWithStorageSendCommand;
import com.cloud.agent.api.MigrateWithStorageCompleteAnswer;
import com.cloud.agent.api.MigrateWithStorageCompleteCommand;
import com.cloud.agent.api.CheckVirtualMachineAnswer;
import com.cloud.agent.api.CheckVirtualMachineCommand;
import com.cloud.capacity.CapacityManager;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.ManagementServerException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.VirtualMachineMigrationException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.HypervisorGuru;
import com.cloud.hypervisor.HypervisorGuruManager;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.NetworkManager;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.VolumeManager;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.*;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd;
import org.apache.cloudstack.api.command.user.vm.ScaleVMCmd;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.snapshot.VMSnapshotManager;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.junit.Test;
import org.junit.Before;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Mockito.*;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
public class VirtualMachineManagerImplTest {
@Spy VirtualMachineManagerImpl _vmMgr = new VirtualMachineManagerImpl();
@Mock
VolumeManager _storageMgr;
@Mock
Account _account;
@Mock
AccountManager _accountMgr;
@Mock
ConfigurationManager _configMgr;
@Mock
CapacityManager _capacityMgr;
@Mock
AgentManager _agentMgr;
@Mock
AccountDao _accountDao;
@Mock
ConfigurationDao _configDao;
@Mock
HostDao _hostDao;
@Mock
UserDao _userDao;
@Mock
UserVmDao _vmDao;
@Mock
ItWorkDao _workDao;
@Mock
VMInstanceDao _vmInstanceDao;
@Mock
VMTemplateDao _templateDao;
@Mock
VolumeDao _volsDao;
@Mock
RestoreVMCmd _restoreVMCmd;
@Mock
AccountVO _accountMock;
@Mock
UserVO _userMock;
@Mock
UserVmVO _vmMock;
@Mock
VMInstanceVO _vmInstance;
@Mock
HostVO _host;
@Mock
VMTemplateVO _templateMock;
@Mock
VolumeVO _volumeMock;
@Mock
List<VolumeVO> _rootVols;
@Mock
ItWorkVO _work;
@Mock
ConfigurationServer _configServer;
@Mock
HostVO hostVO;
@Mock ClusterDao _clusterDao;
@Mock HostPodDao _podDao;
@Mock DataCenterDao _dcDao;
@Mock DiskOfferingDao _diskOfferingDao;
@Mock PrimaryDataStoreDao _storagePoolDao;
@Mock StoragePoolHostDao _poolHostDao;
@Mock NetworkManager _networkMgr;
@Mock HypervisorGuruManager _hvGuruMgr;
@Mock VMSnapshotManager _vmSnapshotMgr;
// Mock objects for vm migration with storage test.
@Mock DiskOfferingVO _diskOfferingMock;
@Mock StoragePoolVO _srcStoragePoolMock;
@Mock StoragePoolVO _destStoragePoolMock;
@Mock HostVO _srcHostMock;
@Mock HostVO _destHostMock;
@Mock Map<VolumeVO, StoragePoolVO> _volumeToPoolMock;
@Before
public void setup(){
MockitoAnnotations.initMocks(this);
_vmMgr._templateDao = _templateDao;
_vmMgr._volsDao = _volsDao;
_vmMgr.volumeMgr = _storageMgr;
_vmMgr._accountDao = _accountDao;
_vmMgr._userDao = _userDao;
_vmMgr._accountMgr = _accountMgr;
_vmMgr._configMgr = _configMgr;
_vmMgr._capacityMgr = _capacityMgr;
_vmMgr._hostDao = _hostDao;
_vmMgr._nodeId = 1L;
_vmMgr._workDao = _workDao;
_vmMgr._agentMgr = _agentMgr;
_vmMgr._podDao = _podDao;
_vmMgr._clusterDao = _clusterDao;
_vmMgr._dcDao = _dcDao;
_vmMgr._diskOfferingDao = _diskOfferingDao;
_vmMgr._storagePoolDao = _storagePoolDao;
_vmMgr._poolHostDao= _poolHostDao;
_vmMgr._networkMgr = _networkMgr;
_vmMgr._hvGuruMgr = _hvGuruMgr;
_vmMgr._vmSnapshotMgr = _vmSnapshotMgr;
_vmMgr._vmDao = _vmInstanceDao;
_vmMgr._configServer = _configServer;
when(_vmMock.getId()).thenReturn(314l);
when(_vmInstance.getId()).thenReturn(1L);
when(_vmInstance.getServiceOfferingId()).thenReturn(2L);
when(_vmInstance.getInstanceName()).thenReturn("myVm");
when(_vmInstance.getHostId()).thenReturn(2L);
when(_vmInstance.getType()).thenReturn(VirtualMachine.Type.User);
when(_host.getId()).thenReturn(1L);
when(_hostDao.findById(anyLong())).thenReturn(null);
when(_configMgr.getServiceOffering(anyLong())).thenReturn(getSvcoffering(512));
when(_workDao.persist(_work)).thenReturn(_work);
when(_workDao.update("1", _work)).thenReturn(true);
when(_work.getId()).thenReturn("1");
doNothing().when(_work).setStep(ItWorkVO.Step.Done);
//doNothing().when(_volsDao).detachVolume(anyLong());
//when(_work.setStep(ItWorkVO.Step.Done)).thenReturn("1");
}
@Test(expected=CloudRuntimeException.class)
public void testScaleVM1() throws Exception {
DeployDestination dest = new DeployDestination(null, null, null, _host);
long l = 1L;
when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance);
_vmMgr.migrateForScale(_vmInstance, l, dest, l);
}
@Test (expected=CloudRuntimeException.class)
public void testScaleVM2() throws Exception {
DeployDestination dest = new DeployDestination(null, null, null, _host);
long l = 1L;
when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance);
ServiceOfferingVO newServiceOffering = getSvcoffering(512);
when(_hostDao.findById(_vmInstance.hostId)).thenReturn(hostVO);
doReturn(1L).when(hostVO).getClusterId();
when(_configServer.getConfigValue(Config.MemOverprovisioningFactor.key(), Config.ConfigurationParameterScope.cluster.toString(), 1L)).thenReturn("1.0");
when(_configServer.getConfigValue(Config.CPUOverprovisioningFactor.key(), Config.ConfigurationParameterScope.cluster.toString(), 1L)).thenReturn("1.0");
ScaleVmCommand reconfigureCmd = new ScaleVmCommand("myVmName", newServiceOffering.getCpu(),
newServiceOffering.getSpeed(), newServiceOffering.getSpeed(), newServiceOffering.getRamSize(), newServiceOffering.getRamSize(), newServiceOffering.getLimitCpuUse());
Answer answer = new ScaleVmAnswer(reconfigureCmd, true, "details");
when(_agentMgr.send(2l, reconfigureCmd)).thenReturn(null);
_vmMgr.reConfigureVm(_vmInstance, getSvcoffering(256), false);
}
@Test (expected=CloudRuntimeException.class)
public void testScaleVM3() throws Exception {
/*VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
Long srcHostId = vm.getHostId();
Long oldSvcOfferingId = vm.getServiceOfferingId();
if (srcHostId == null) {
throw new CloudRuntimeException("Unable to scale the vm because it doesn't have a host id");
}*/
when(_vmInstance.getHostId()).thenReturn(null);
when(_vmInstanceDao.findById(anyLong())).thenReturn(_vmInstance);
_vmMgr.findHostAndMigrate(VirtualMachine.Type.User, _vmInstance, 2l);
}
private ServiceOfferingVO getSvcoffering(int ramSize){
long id = 4L;
String name = "name";
String displayText = "displayText";
int cpu = 1;
//int ramSize = 256;
int speed = 128;
boolean ha = false;
boolean useLocalStorage = false;
ServiceOfferingVO serviceOffering = new ServiceOfferingVO(name, cpu, ramSize, speed, null, null, ha, displayText, useLocalStorage, false, null, false, null, false);
return serviceOffering;
}
private void initializeMockConfigForMigratingVmWithVolumes() throws OperationTimedoutException,
ResourceUnavailableException {
// Mock the source and destination hosts.
when(_srcHostMock.getId()).thenReturn(5L);
when(_destHostMock.getId()).thenReturn(6L);
when(_hostDao.findById(5L)).thenReturn(_srcHostMock);
when(_hostDao.findById(6L)).thenReturn(_destHostMock);
// Mock the vm being migrated.
when(_vmMock.getId()).thenReturn(1L);
when(_vmMock.getHypervisorType()).thenReturn(HypervisorType.XenServer);
when(_vmMock.getState()).thenReturn(State.Running).thenReturn(State.Running).thenReturn(State.Migrating)
.thenReturn(State.Migrating);
when(_vmMock.getHostId()).thenReturn(5L);
when(_vmInstance.getId()).thenReturn(1L);
when(_vmInstance.getServiceOfferingId()).thenReturn(2L);
when(_vmInstance.getInstanceName()).thenReturn("myVm");
when(_vmInstance.getHostId()).thenReturn(5L);
when(_vmInstance.getType()).thenReturn(VirtualMachine.Type.User);
when(_vmInstance.getState()).thenReturn(State.Running).thenReturn(State.Running).thenReturn(State.Migrating)
.thenReturn(State.Migrating);
// Mock the work item.
when(_workDao.persist(any(ItWorkVO.class))).thenReturn(_work);
when(_workDao.update("1", _work)).thenReturn(true);
when(_work.getId()).thenReturn("1");
doNothing().when(_work).setStep(ItWorkVO.Step.Done);
// Mock the vm guru and the user vm object that gets returned.
_vmMgr._vmGurus = new HashMap<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>>();
UserVmManagerImpl userVmManager = mock(UserVmManagerImpl.class);
_vmMgr.registerGuru(VirtualMachine.Type.User, userVmManager);
when(userVmManager.findById(anyLong())).thenReturn(_vmMock);
// Mock the iteration over all the volumes of an instance.
Iterator<VolumeVO> volumeIterator = mock(Iterator.class);
when(_volsDao.findUsableVolumesForInstance(anyLong())).thenReturn(_rootVols);
when(_rootVols.iterator()).thenReturn(volumeIterator);
when(volumeIterator.hasNext()).thenReturn(true, false);
when(volumeIterator.next()).thenReturn(_volumeMock);
// Mock the disk offering and pool objects for a volume.
when(_volumeMock.getDiskOfferingId()).thenReturn(5L);
when(_volumeMock.getPoolId()).thenReturn(200L);
when(_diskOfferingDao.findById(anyLong())).thenReturn(_diskOfferingMock);
when(_storagePoolDao.findById(anyLong())).thenReturn(_srcStoragePoolMock);
// Mock the volume to pool mapping.
when(_volumeToPoolMock.get(_volumeMock)).thenReturn(_destStoragePoolMock);
when(_destStoragePoolMock.getId()).thenReturn(201L);
when(_srcStoragePoolMock.getId()).thenReturn(200L);
when(_destStoragePoolMock.isLocal()).thenReturn(false);
when(_diskOfferingMock.getUseLocalStorage()).thenReturn(false);
when(_poolHostDao.findByPoolHost(anyLong(), anyLong())).thenReturn(mock(StoragePoolHostVO.class));
// Mock hypervisor guru.
HypervisorGuru guruMock = mock(HypervisorGuru.class);
when(_hvGuruMgr.getGuru(HypervisorType.XenServer)).thenReturn(guruMock);
when(_srcHostMock.getClusterId()).thenReturn(3L);
when(_destHostMock.getClusterId()).thenReturn(3L);
// Mock the commands and answers to the agent.
PrepareForMigrationAnswer prepAnswerMock = mock(PrepareForMigrationAnswer.class);
when(prepAnswerMock.getResult()).thenReturn(true);
when(_agentMgr.send(anyLong(), isA(PrepareForMigrationCommand.class))).thenReturn(prepAnswerMock);
MigrateWithStorageAnswer migAnswerMock = mock(MigrateWithStorageAnswer.class);
when(migAnswerMock.getResult()).thenReturn(true);
when(_agentMgr.send(anyLong(), isA(MigrateWithStorageCommand.class))).thenReturn(migAnswerMock);
MigrateWithStorageReceiveAnswer migRecAnswerMock = mock(MigrateWithStorageReceiveAnswer.class);
when(migRecAnswerMock.getResult()).thenReturn(true);
when(_agentMgr.send(anyLong(), isA(MigrateWithStorageReceiveCommand.class))).thenReturn(migRecAnswerMock);
MigrateWithStorageSendAnswer migSendAnswerMock = mock(MigrateWithStorageSendAnswer.class);
when(migSendAnswerMock.getResult()).thenReturn(true);
when(_agentMgr.send(anyLong(), isA(MigrateWithStorageSendCommand.class))).thenReturn(migSendAnswerMock);
MigrateWithStorageCompleteAnswer migCompleteAnswerMock = mock(MigrateWithStorageCompleteAnswer.class);
when(migCompleteAnswerMock.getResult()).thenReturn(true);
when(_agentMgr.send(anyLong(), isA(MigrateWithStorageCompleteCommand.class))).thenReturn(migCompleteAnswerMock);
CheckVirtualMachineAnswer checkVmAnswerMock = mock(CheckVirtualMachineAnswer.class);
when(checkVmAnswerMock.getResult()).thenReturn(true);
when(checkVmAnswerMock.getState()).thenReturn(State.Running);
when(_agentMgr.send(anyLong(), isA(CheckVirtualMachineCommand.class))).thenReturn(checkVmAnswerMock);
// Mock the state transitions of vm.
Pair<Long, Long> opaqueMock = new Pair<Long, Long> (_vmMock.getHostId(), _destHostMock.getId());
when(_vmSnapshotMgr.hasActiveVMSnapshotTasks(anyLong())).thenReturn(false);
when(_vmInstanceDao.updateState(State.Running, Event.MigrationRequested, State.Migrating, _vmMock, opaqueMock))
.thenReturn(true);
when(_vmInstanceDao.updateState(State.Migrating, Event.OperationSucceeded, State.Running, _vmMock, opaqueMock))
.thenReturn(true);
}
// Check migration of a vm with its volumes within a cluster.
@Test
public void testMigrateWithVolumeWithinCluster() throws ResourceUnavailableException, ConcurrentOperationException,
ManagementServerException, VirtualMachineMigrationException, OperationTimedoutException {
initializeMockConfigForMigratingVmWithVolumes();
when(_srcHostMock.getClusterId()).thenReturn(3L);
when(_destHostMock.getClusterId()).thenReturn(3L);
_vmMgr.migrateWithStorage(_vmInstance, _srcHostMock.getId(), _destHostMock.getId(), _volumeToPoolMock);
}
// Check migration of a vm with its volumes across a cluster.
@Test
public void testMigrateWithVolumeAcrossCluster() throws ResourceUnavailableException, ConcurrentOperationException,
ManagementServerException, VirtualMachineMigrationException, OperationTimedoutException {
initializeMockConfigForMigratingVmWithVolumes();
when(_srcHostMock.getClusterId()).thenReturn(3L);
when(_destHostMock.getClusterId()).thenReturn(4L);
_vmMgr.migrateWithStorage(_vmInstance, _srcHostMock.getId(), _destHostMock.getId(), _volumeToPoolMock);
}
// Check migration of a vm fails when src and destination pool are not of same type; that is, one is shared and
// other is local.
@Test(expected=CloudRuntimeException.class)
public void testMigrateWithVolumeFail1() throws ResourceUnavailableException, ConcurrentOperationException,
ManagementServerException, VirtualMachineMigrationException, OperationTimedoutException {
initializeMockConfigForMigratingVmWithVolumes();
when(_srcHostMock.getClusterId()).thenReturn(3L);
when(_destHostMock.getClusterId()).thenReturn(3L);
when(_destStoragePoolMock.isLocal()).thenReturn(true);
when(_diskOfferingMock.getUseLocalStorage()).thenReturn(false);
_vmMgr.migrateWithStorage(_vmInstance, _srcHostMock.getId(), _destHostMock.getId(), _volumeToPoolMock);
}
// Check migration of a vm fails when vm is not in Running state.
@Test(expected=ConcurrentOperationException.class)
public void testMigrateWithVolumeFail2() throws ResourceUnavailableException, ConcurrentOperationException,
ManagementServerException, VirtualMachineMigrationException, OperationTimedoutException {
initializeMockConfigForMigratingVmWithVolumes();
when(_srcHostMock.getClusterId()).thenReturn(3L);
when(_destHostMock.getClusterId()).thenReturn(3L);
when(_vmMock.getState()).thenReturn(State.Stopped);
_vmMgr.migrateWithStorage(_vmInstance, _srcHostMock.getId(), _destHostMock.getId(), _volumeToPoolMock);
}
}