diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java index 59d1a5f6361..e89d926dd7b 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java @@ -45,6 +45,7 @@ import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.MigrateWithStorageCommand; +import com.cloud.agent.api.MigrateWithStorageReceiveCommand; import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.NetworkRulesSystemVmCommand; @@ -195,6 +196,7 @@ public class CitrixRequestWrapper extends RequestWrapper { // XenServer610Resource commands final Hashtable, CommandWrapper> xenServer610Commands = new Hashtable, CommandWrapper>(); xenServer610Commands.put(MigrateWithStorageCommand.class, new XenServer610MigrateWithStorageCommandWrapper()); + xenServer610Commands.put(MigrateWithStorageReceiveCommand.class, new XenServer610MigrateWithStorageReceiveCommandWrapper()); resources.put(XenServer610Resource.class, xenServer610Commands); } diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageCommandWrapper.java index 0d1cac47cc8..970ed107a0f 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageCommandWrapper.java @@ -82,7 +82,9 @@ public final class XenServer610MigrateWithStorageCommandWrapper extends CommandW final Map vifMap = new HashMap(); final Map vdiMap = new HashMap(); for (final Map.Entry entry : volumeToFiler.entrySet()) { - vdiMap.put(xenServer610Resource.getVDIbyUuid(connection, entry.getKey().getPath()), xenServer610Resource.getStorageRepository(connection, entry.getValue().getUuid())); + final VolumeTO volume = entry.getKey(); + final StorageFilerTO sotrageFiler = entry.getValue(); + vdiMap.put(xenServer610Resource.getVDIbyUuid(connection, volume.getPath()), xenServer610Resource.getStorageRepository(connection, sotrageFiler.getUuid())); } // Get the vm to migrate. diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageReceiveCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageReceiveCommandWrapper.java new file mode 100644 index 00000000000..57f5851c46a --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageReceiveCommandWrapper.java @@ -0,0 +1,91 @@ +// +// 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.hypervisor.xenserver.resource.wrapper; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.MigrateWithStorageReceiveAnswer; +import com.cloud.agent.api.MigrateWithStorageReceiveCommand; +import com.cloud.agent.api.to.NicTO; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.hypervisor.xenserver.resource.XenServer610Resource; +import com.cloud.hypervisor.xenserver.resource.XsHost; +import com.cloud.hypervisor.xenserver.resource.XsLocalNetwork; +import com.cloud.network.Networks.TrafficType; +import com.cloud.resource.CommandWrapper; +import com.cloud.utils.exception.CloudRuntimeException; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.SR; + +public final class XenServer610MigrateWithStorageReceiveCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(XenServer610MigrateWithStorageReceiveCommandWrapper.class); + + @Override + public Answer execute(final MigrateWithStorageReceiveCommand command, final XenServer610Resource xenServer610Resource) { + final Connection connection = xenServer610Resource.getConnection(); + final VirtualMachineTO vmSpec = command.getVirtualMachine(); + final Map volumeToFiler = command.getVolumeToFiler(); + + try { + // Get a map of all the SRs to which the vdis will be migrated. + final Map volumeToSr = new HashMap(); + for (final Map.Entry entry : volumeToFiler.entrySet()) { + final StorageFilerTO storageFiler = entry.getValue(); + final SR sr = xenServer610Resource.getStorageRepository(connection, storageFiler.getUuid()); + volumeToSr.put(entry.getKey(), sr); + } + + // Get the list of networks to which the vifs will attach. + final Map nicToNetwork = new HashMap(); + for (final NicTO nicTo : vmSpec.getNics()) { + final Network network = xenServer610Resource.getNetwork(connection, nicTo); + nicToNetwork.put(nicTo, network); + } + + final XsLocalNetwork nativeNetworkForTraffic = xenServer610Resource.getNativeNetworkForTraffic(connection, TrafficType.Storage, null); + final Network network = nativeNetworkForTraffic.getNetwork(); + final XsHost xsHost = xenServer610Resource.getHost(); + final String uuid = xsHost.getUuid(); + + final Map other = new HashMap(); + other.put("live", "true"); + + final Host host = Host.getByUuid(connection, uuid); + final Map token = host.migrateReceive(connection, network, other); + + return new MigrateWithStorageReceiveAnswer(command, volumeToSr, nicToNetwork, token); + } catch (final CloudRuntimeException e) { + s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageReceiveAnswer(command, e); + } catch (final Exception e) { + s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageReceiveAnswer(command, e); + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610WrapperTest.java b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610WrapperTest.java index a708684e4d6..649dd1feac1 100644 --- a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610WrapperTest.java +++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610WrapperTest.java @@ -34,12 +34,12 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckNetworkCommand; import com.cloud.agent.api.MigrateWithStorageCommand; +import com.cloud.agent.api.MigrateWithStorageReceiveCommand; import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.StorageFilerTO; @@ -52,12 +52,12 @@ import com.cloud.hypervisor.xenserver.resource.XsLocalNetwork; import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetworkSetupInfo; import com.xensource.xenapi.Connection; -import com.xensource.xenapi.Host; import com.xensource.xenapi.Network; +import com.xensource.xenapi.SR; import com.xensource.xenapi.Types.XenAPIException; +import com.xensource.xenapi.VDI; @RunWith(PowerMockRunner.class) -@PrepareForTest({Host.class}) public class XenServer610WrapperTest { @Mock @@ -96,10 +96,19 @@ public class XenServer610WrapperTest { public void testMigrateWithStorageCommand() { final String vmName = "small"; final String uuid = "206b21a7-c6ec-40e2-b5e2-f861b9612f04"; + final String path = "/"; final Connection conn = Mockito.mock(Connection.class); final VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class); + + final VolumeTO vol1 = Mockito.mock(VolumeTO.class); + final VolumeTO vol2 = Mockito.mock(VolumeTO.class); + final StorageFilerTO storage1 = Mockito.mock(StorageFilerTO.class); + final StorageFilerTO storage2 = Mockito.mock(StorageFilerTO.class); + final Map volumeToFiler = new HashMap(); + volumeToFiler.put(vol1, storage1); + volumeToFiler.put(vol2, storage2); final NicTO nicTO1 = Mockito.mock(NicTO.class); final NicTO nicTO2 = Mockito.mock(NicTO.class); @@ -108,11 +117,15 @@ public class XenServer610WrapperTest { final XsLocalNetwork nativeNetworkForTraffic = Mockito.mock(XsLocalNetwork.class); final Network networkForSm = Mockito.mock(Network.class); - final XsHost xsHost = Mockito.mock(XsHost.class); - final Host host = Mockito.mock(Host.class); - final MigrateWithStorageCommand gpuStats = new MigrateWithStorageCommand(vmSpec, volumeToFiler); + final SR sr1 = Mockito.mock(SR.class); + final SR sr2 = Mockito.mock(SR.class); + + final VDI vdi1 = Mockito.mock(VDI.class); + final VDI vdi2 = Mockito.mock(VDI.class); + + final MigrateWithStorageCommand migrateStorageCommand = new MigrateWithStorageCommand(vmSpec, volumeToFiler); final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); assertNotNull(wrapper); @@ -121,19 +134,31 @@ public class XenServer610WrapperTest { when(vmSpec.getName()).thenReturn(vmName); when(vmSpec.getNics()).thenReturn(nicTOs); - try { - when(xenServer610Resource.getHost()).thenReturn(xsHost); - when(xsHost.getUuid()).thenReturn(uuid); + when(storage1.getUuid()).thenReturn(uuid); + when(storage2.getUuid()).thenReturn(uuid); + when(vol1.getPath()).thenReturn(path); + when(vol2.getPath()).thenReturn(path); + + when(xenServer610Resource.getStorageRepository(conn, storage1.getUuid())).thenReturn(sr1); + when(xenServer610Resource.getStorageRepository(conn, storage2.getUuid())).thenReturn(sr2); + + when(xenServer610Resource.getVDIbyUuid(conn, storage1.getPath())).thenReturn(vdi1); + when(xenServer610Resource.getVDIbyUuid(conn, storage2.getPath())).thenReturn(vdi2); + + try { when(xenServer610Resource.getNativeNetworkForTraffic(conn, TrafficType.Storage, null)).thenReturn(nativeNetworkForTraffic); when(nativeNetworkForTraffic.getNetwork()).thenReturn(networkForSm); + + when(xenServer610Resource.getHost()).thenReturn(xsHost); + when(xsHost.getUuid()).thenReturn(uuid); } catch (final XenAPIException e) { fail(e.getMessage()); } catch (final XmlRpcException e) { fail(e.getMessage()); } - final Answer answer = wrapper.execute(gpuStats, xenServer610Resource); + final Answer answer = wrapper.execute(migrateStorageCommand, xenServer610Resource); verify(xenServer610Resource, times(1)).getConnection(); @@ -145,6 +170,97 @@ public class XenServer610WrapperTest { verify(xenServer610Resource, times(1)).getNativeNetworkForTraffic(conn, TrafficType.Storage, null); verify(nativeNetworkForTraffic, times(1)).getNetwork(); + + verify(xenServer610Resource, times(1)).getHost(); + verify(xsHost, times(1)).getUuid(); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + assertFalse(answer.getResult()); + } + + @Test + public void testMigrateWithStorageReceiveCommand() { + final String vmName = "small"; + final String uuid = "206b21a7-c6ec-40e2-b5e2-f861b9612f04"; + + final Connection conn = Mockito.mock(Connection.class); + final VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class); + + final VolumeTO vol1 = Mockito.mock(VolumeTO.class); + final VolumeTO vol2 = Mockito.mock(VolumeTO.class); + final StorageFilerTO storage1 = Mockito.mock(StorageFilerTO.class); + final StorageFilerTO storage2 = Mockito.mock(StorageFilerTO.class); + + final Map volumeToFiler = new HashMap(); + volumeToFiler.put(vol1, storage1); + volumeToFiler.put(vol2, storage2); + + final NicTO nicTO1 = Mockito.mock(NicTO.class); + final NicTO nicTO2 = Mockito.mock(NicTO.class); + final NicTO nicTO3 = Mockito.mock(NicTO.class); + final NicTO [] nicTOs = {nicTO1, nicTO2, nicTO3}; + + final XsLocalNetwork nativeNetworkForTraffic = Mockito.mock(XsLocalNetwork.class); + final Network network = Mockito.mock(Network.class); + final XsHost xsHost = Mockito.mock(XsHost.class); + + final Network nw1 = Mockito.mock(Network.class); + final Network nw2 = Mockito.mock(Network.class); + final Network nw3 = Mockito.mock(Network.class); + + final SR sr1 = Mockito.mock(SR.class); + final SR sr2 = Mockito.mock(SR.class); + + final MigrateWithStorageReceiveCommand migrateStorageCommand = new MigrateWithStorageReceiveCommand(vmSpec, volumeToFiler); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(xenServer610Resource.getConnection()).thenReturn(conn); + when(vmSpec.getName()).thenReturn(vmName); + when(vmSpec.getNics()).thenReturn(nicTOs); + + when(storage1.getUuid()).thenReturn(uuid); + when(storage2.getUuid()).thenReturn(uuid); + + when(xenServer610Resource.getStorageRepository(conn, storage1.getUuid())).thenReturn(sr1); + when(xenServer610Resource.getStorageRepository(conn, storage2.getUuid())).thenReturn(sr2); + + try { + + when(xenServer610Resource.getNetwork(conn, nicTO1)).thenReturn(nw1); + when(xenServer610Resource.getNetwork(conn, nicTO2)).thenReturn(nw2); + when(xenServer610Resource.getNetwork(conn, nicTO3)).thenReturn(nw3); + + when(xenServer610Resource.getNativeNetworkForTraffic(conn, TrafficType.Storage, null)).thenReturn(nativeNetworkForTraffic); + when(nativeNetworkForTraffic.getNetwork()).thenReturn(network); + + when(xenServer610Resource.getHost()).thenReturn(xsHost); + when(xsHost.getUuid()).thenReturn(uuid); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + final Answer answer = wrapper.execute(migrateStorageCommand, xenServer610Resource); + + verify(xenServer610Resource, times(1)).getConnection(); + + try { + verify(xenServer610Resource, times(1)).getNetwork(conn, nicTO1); + verify(xenServer610Resource, times(1)).getNetwork(conn, nicTO2); + verify(xenServer610Resource, times(1)).getNetwork(conn, nicTO3); + + verify(xenServer610Resource, times(1)).getNativeNetworkForTraffic(conn, TrafficType.Storage, null); + verify(nativeNetworkForTraffic, times(1)).getNetwork(); + + verify(xenServer610Resource, times(1)).getHost(); + verify(xsHost, times(1)).getUuid(); } catch (final XenAPIException e) { fail(e.getMessage()); } catch (final XmlRpcException e) {