Unit tests for vmware storage motion. These test the VmwareStorageMotionStrategy.
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/97694606 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/97694606 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/97694606 Branch: refs/heads/vmware-storage-motion Commit: 97694606ef6ca99d20f9e51f6e4cd2de3e83c3f4 Parents: de3ae48 Author: Devdeep Singh <devd...@gmail.com> Authored: Wed May 22 12:23:54 2013 +0530 Committer: Sateesh Chodapuneedi <sate...@apache.org> Committed: Fri May 24 15:24:07 2013 +0530 ---------------------------------------------------------------------- .../motion/VmwareStorageMotionStrategyTest.java | 271 +++++++++++++++ 1 files changed, 271 insertions(+), 0 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/97694606/plugins/hypervisors/vmware/test/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategyTest.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/test/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategyTest.java b/plugins/hypervisors/vmware/test/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategyTest.java new file mode 100644 index 0000000..ae4f41d --- /dev/null +++ b/plugins/hypervisors/vmware/test/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategyTest.java @@ -0,0 +1,271 @@ +// 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.storage.motion; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.test.utils.SpringUtils; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.core.type.filter.TypeFilter; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.MigrateWithStorageAnswer; +import com.cloud.agent.api.MigrateWithStorageCommand; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.host.Host; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.utils.component.ComponentContext; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.dao.VMInstanceDao; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class) +public class VmwareStorageMotionStrategyTest { + + @Inject VmwareStorageMotionStrategy strategy = new VmwareStorageMotionStrategy(); + @Inject AgentManager agentMgr; + @Inject VolumeDao volDao; + @Inject VolumeDataFactory volFactory; + @Inject PrimaryDataStoreDao storagePoolDao; + @Inject VMInstanceDao instanceDao; + + CopyCommandResult result; + + @BeforeClass + public static void setUp() throws ConfigurationException { + } + + @Before + public void testSetUp() { + ComponentContext.initComponentsLifeCycle(); + } + + @Test + public void testStrategyHandlesVmwareHosts() throws Exception { + Host srcHost = mock(Host.class); + Host destHost = mock(Host.class); + when(srcHost.getHypervisorType()).thenReturn(HypervisorType.VMware); + when(destHost.getHypervisorType()).thenReturn(HypervisorType.VMware); + Map<VolumeInfo, DataStore> volumeMap = new HashMap<VolumeInfo, DataStore>(); + boolean canHandle = strategy.canHandle(volumeMap, srcHost, destHost); + assertTrue("The strategy is only supposed to handle vmware hosts", canHandle); + } + + @Test + public void testStrategyDoesnotHandlesNonVmwareHosts() throws Exception { + Host srcHost = mock(Host.class); + Host destHost = mock(Host.class); + when(srcHost.getHypervisorType()).thenReturn(HypervisorType.XenServer); + when(destHost.getHypervisorType()).thenReturn(HypervisorType.XenServer); + Map<VolumeInfo, DataStore> volumeMap = new HashMap<VolumeInfo, DataStore>(); + boolean canHandle = strategy.canHandle(volumeMap, srcHost, destHost); + assertFalse("The strategy is only supposed to handle vmware hosts", canHandle); + } + + @Test + public void testMigrateWithinClusterSuccess() throws Exception { + Host srcHost = mock(Host.class); + Host destHost = mock(Host.class); + when(srcHost.getClusterId()).thenReturn(1L); + when(destHost.getClusterId()).thenReturn(1L); + Map<VolumeInfo, DataStore> volumeMap = new HashMap<VolumeInfo, DataStore>(); + VirtualMachineTO to = mock(VirtualMachineTO.class); + when(to.getId()).thenReturn(6L); + VMInstanceVO instance = mock(VMInstanceVO.class); + when(instanceDao.findById(6L)).thenReturn(instance); + + MockContext<CommandResult> context = new MockContext<CommandResult>(null, null, volumeMap); + AsyncCallbackDispatcher<VmwareStorageMotionStrategyTest, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().mockCallBack(null, null)).setContext(context); + + MigrateWithStorageAnswer migAnswerMock = mock(MigrateWithStorageAnswer.class); + when(migAnswerMock.getResult()).thenReturn(true); + when(agentMgr.send(anyLong(), isA(MigrateWithStorageCommand.class))).thenReturn(migAnswerMock); + + strategy.copyAsync(volumeMap, to, srcHost, destHost, caller); + assertTrue("Migration within cluster isn't successful.", this.result.isSuccess()); + } + + @Test + public void testMigrateWithinClusterFailure() throws Exception { + Host srcHost = mock(Host.class); + Host destHost = mock(Host.class); + when(srcHost.getClusterId()).thenReturn(1L); + when(destHost.getClusterId()).thenReturn(1L); + Map<VolumeInfo, DataStore> volumeMap = new HashMap<VolumeInfo, DataStore>(); + VirtualMachineTO to = mock(VirtualMachineTO.class); + when(to.getId()).thenReturn(6L); + VMInstanceVO instance = mock(VMInstanceVO.class); + when(instanceDao.findById(6L)).thenReturn(instance); + + MockContext<CommandResult> context = new MockContext<CommandResult>(null, null, volumeMap); + AsyncCallbackDispatcher<VmwareStorageMotionStrategyTest, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().mockCallBack(null, null)).setContext(context); + + MigrateWithStorageAnswer migAnswerMock = mock(MigrateWithStorageAnswer.class); + when(migAnswerMock.getResult()).thenReturn(false); + when(agentMgr.send(anyLong(), isA(MigrateWithStorageCommand.class))).thenReturn(migAnswerMock); + + strategy.copyAsync(volumeMap, to, srcHost, destHost, caller); + assertFalse("Migration within cluster didn't fail.", this.result.isSuccess()); + } + + @Test + public void testMigrateAcrossClusterSuccess() throws Exception { + Host srcHost = mock(Host.class); + Host destHost = mock(Host.class); + when(srcHost.getClusterId()).thenReturn(1L); + when(destHost.getClusterId()).thenReturn(2L); + Map<VolumeInfo, DataStore> volumeMap = new HashMap<VolumeInfo, DataStore>(); + VirtualMachineTO to = mock(VirtualMachineTO.class); + when(to.getId()).thenReturn(6L); + VMInstanceVO instance = mock(VMInstanceVO.class); + when(instanceDao.findById(6L)).thenReturn(instance); + + MockContext<CommandResult> context = new MockContext<CommandResult>(null, null, volumeMap); + AsyncCallbackDispatcher<VmwareStorageMotionStrategyTest, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().mockCallBack(null, null)).setContext(context); + + MigrateWithStorageAnswer migAnswerMock = mock(MigrateWithStorageAnswer.class); + when(migAnswerMock.getResult()).thenReturn(true); + when(agentMgr.send(anyLong(), isA(MigrateWithStorageCommand.class))).thenReturn(migAnswerMock); + + strategy.copyAsync(volumeMap, to, srcHost, destHost, caller); + assertTrue("Migration across cluster isn't successful.", this.result.isSuccess()); + } + + @Test + public void testMigrateAcrossClusterFailure() throws Exception { + Host srcHost = mock(Host.class); + Host destHost = mock(Host.class); + when(srcHost.getClusterId()).thenReturn(1L); + when(destHost.getClusterId()).thenReturn(2L); + Map<VolumeInfo, DataStore> volumeMap = new HashMap<VolumeInfo, DataStore>(); + VirtualMachineTO to = mock(VirtualMachineTO.class); + when(to.getId()).thenReturn(6L); + VMInstanceVO instance = mock(VMInstanceVO.class); + when(instanceDao.findById(6L)).thenReturn(instance); + + MockContext<CommandResult> context = new MockContext<CommandResult>(null, null, volumeMap); + AsyncCallbackDispatcher<VmwareStorageMotionStrategyTest, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().mockCallBack(null, null)).setContext(context); + + MigrateWithStorageAnswer migAnswerMock = mock(MigrateWithStorageAnswer.class); + when(migAnswerMock.getResult()).thenReturn(false); + when(agentMgr.send(anyLong(), isA(MigrateWithStorageCommand.class))).thenReturn(migAnswerMock); + + strategy.copyAsync(volumeMap, to, srcHost, destHost, caller); + assertFalse("Migration across cluster didn't fail.", this.result.isSuccess()); + } + + private class MockContext<T> extends AsyncRpcConext<T> { + final Map<VolumeInfo, DataStore> volumeToPool; + final AsyncCallFuture<CommandResult> future; + /** + * @param callback + */ + public MockContext(AsyncCompletionCallback<T> callback, AsyncCallFuture<CommandResult> future, + Map<VolumeInfo, DataStore> volumeToPool) { + super(callback); + this.volumeToPool = volumeToPool; + this.future = future; + } + } + + protected Void mockCallBack(AsyncCallbackDispatcher<VmwareStorageMotionStrategyTest, + CopyCommandResult> callback, MockContext<CommandResult> context) { + this.result = callback.getResult(); + return null; + } + + @Configuration + @ComponentScan(basePackageClasses = { VmwareStorageMotionStrategy.class }, + includeFilters = {@Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM)}, + useDefaultFilters = false) + public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration { + + @Bean + public VolumeDao volumeDao() { + return Mockito.mock(VolumeDao.class); + } + + @Bean + public VolumeDataFactory volumeDataFactory() { + return Mockito.mock(VolumeDataFactory.class); + } + + @Bean + public PrimaryDataStoreDao primaryDataStoreDao() { + return Mockito.mock(PrimaryDataStoreDao.class); + } + + @Bean + public VMInstanceDao vmInstanceDao() { + return Mockito.mock(VMInstanceDao.class); + } + + @Bean + public AgentManager agentManager() { + return Mockito.mock(AgentManager.class); + } + + public static class Library implements TypeFilter { + @Override + public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException { + ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class); + return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs); + } + } + } +} \ No newline at end of file