Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 1DB9C1781A for ; Sun, 5 Apr 2015 11:25:09 +0000 (UTC) Received: (qmail 62308 invoked by uid 500); 5 Apr 2015 11:25:08 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 62191 invoked by uid 500); 5 Apr 2015 11:25:08 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 61791 invoked by uid 99); 5 Apr 2015 11:25:08 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 05 Apr 2015 11:25:08 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 5247FE1057; Sun, 5 Apr 2015 11:25:08 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ekho@apache.org To: commits@cloudstack.apache.org Date: Sun, 05 Apr 2015 11:25:13 -0000 Message-Id: In-Reply-To: <3da53b3b1f8b4107abc7bf05ab1d420c@git.apache.org> References: <3da53b3b1f8b4107abc7bf05ab1d420c@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [6/8] git commit: updated refs/heads/master to 096d1b9 Refactoring the MigrateWithStorageSendCommand wrapper in order to cope with new design - Unit tests added: 47.2% coverage - It's a bit difficult to test the Xen API classes due to their static nature Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/d5414d26 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/d5414d26 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/d5414d26 Branch: refs/heads/master Commit: d5414d26b48ef5da0a5906d39b7e785c13e286a4 Parents: c5a2f92 Author: wilderrodrigues Authored: Fri Apr 3 16:13:09 2015 +0200 Committer: wilderrodrigues Committed: Sun Apr 5 09:23:10 2015 +0200 ---------------------------------------------------------------------- .../resource/XenServer610Resource.java | 207 +------------------ .../resource/wrapper/CitrixRequestWrapper.java | 4 + ...igrateWithStorageCompleteCommandWrapper.java | 81 ++++++++ ...610MigrateWithStorageSendCommandWrapper.java | 143 +++++++++++++ .../wrapper/XenServer610WrapperTest.java | 164 +++++++++++++++ 5 files changed, 393 insertions(+), 206 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d5414d26/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java index 7f5dfdb..261ace0 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/XenServer610Resource.java @@ -30,28 +30,18 @@ import org.apache.xmlrpc.XmlRpcException; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; -import com.cloud.agent.api.MigrateWithStorageAnswer; -import com.cloud.agent.api.MigrateWithStorageCommand; import com.cloud.agent.api.MigrateWithStorageCompleteAnswer; import com.cloud.agent.api.MigrateWithStorageCompleteCommand; -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.storage.MigrateVolumeAnswer; import com.cloud.agent.api.storage.MigrateVolumeCommand; import com.cloud.agent.api.to.DiskTO; -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.network.Networks.TrafficType; import com.cloud.resource.ServerResource; import com.cloud.storage.Volume; 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; import com.xensource.xenapi.Task; import com.xensource.xenapi.Types; @@ -68,11 +58,7 @@ public class XenServer610Resource extends XenServer600Resource { @Override public Answer executeRequest(final Command cmd) { - if (cmd instanceof MigrateWithStorageReceiveCommand) { - return execute((MigrateWithStorageReceiveCommand)cmd); - } else if (cmd instanceof MigrateWithStorageSendCommand) { - return execute((MigrateWithStorageSendCommand)cmd); - } else if (cmd instanceof MigrateWithStorageCompleteCommand) { + if (cmd instanceof MigrateWithStorageCompleteCommand) { return execute((MigrateWithStorageCompleteCommand)cmd); } else if (cmd instanceof MigrateVolumeCommand) { return execute((MigrateVolumeCommand)cmd); @@ -116,197 +102,6 @@ public class XenServer610Resource extends XenServer600Resource { return volumeToList; } - protected MigrateWithStorageAnswer execute(final MigrateWithStorageCommand cmd) { - final Connection connection = getConnection(); - final VirtualMachineTO vmSpec = cmd.getVirtualMachine(); - final Map volumeToFiler = cmd.getVolumeToFiler(); - final String vmName = vmSpec.getName(); - Task task = null; - - try { - prepareISO(connection, vmSpec.getName()); - - // Get the list of networks and recreate VLAN, if required. - for (final NicTO nicTo : vmSpec.getNics()) { - getNetwork(connection, nicTo); - } - - final Map other = new HashMap(); - other.put("live", "true"); - final Network networkForSm = getNativeNetworkForTraffic(connection, TrafficType.Storage, null).getNetwork(); - final Host host = Host.getByUuid(connection, _host.getUuid()); - final Map token = host.migrateReceive(connection, networkForSm, other); - - // Get the vm to migrate. - final Set vms = VM.getByNameLabel(connection, vmSpec.getName()); - final VM vmToMigrate = vms.iterator().next(); - - // Create the vif map. The vm stays in the same cluster so we have to pass an empty vif map. - final Map vifMap = new HashMap(); - final Map vdiMap = new HashMap(); - for (final Map.Entry entry : volumeToFiler.entrySet()) { - vdiMap.put(getVDIbyUuid(connection, entry.getKey().getPath()), getStorageRepository(connection, entry.getValue().getUuid())); - } - - // Check migration with storage is possible. - task = vmToMigrate.assertCanMigrateAsync(connection, token, true, vdiMap, vifMap, other); - try { - // poll every 1 seconds - final long timeout = _migratewait * 1000L; - waitForTask(connection, task, 1000, timeout); - checkForSuccess(connection, task); - } catch (final Types.HandleInvalid e) { - s_logger.error("Error while checking if vm " + vmName + " can be migrated to the destination host " + host, e); - throw new CloudRuntimeException("Error while checking if vm " + vmName + " can be migrated to the " + "destination host " + host, e); - } - - // Migrate now. - task = vmToMigrate.migrateSendAsync(connection, token, true, vdiMap, vifMap, other); - try { - // poll every 1 seconds. - final long timeout = _migratewait * 1000L; - waitForTask(connection, task, 1000, timeout); - checkForSuccess(connection, task); - } catch (final Types.HandleInvalid e) { - s_logger.error("Error while migrating vm " + vmName + " to the destination host " + host, e); - throw new CloudRuntimeException("Error while migrating vm " + vmName + " to the destination host " + host, e); - } - - // Volume paths would have changed. Return that information. - final List volumeToList = getUpdatedVolumePathsOfMigratedVm(connection, vmToMigrate, vmSpec.getDisks()); - vmToMigrate.setAffinity(connection, host); - return new MigrateWithStorageAnswer(cmd, volumeToList); - } catch (final Exception e) { - s_logger.warn("Catch Exception " + e.getClass().getName() + ". Storage motion failed due to " + e.toString(), e); - return new MigrateWithStorageAnswer(cmd, e); - } finally { - if (task != null) { - try { - task.destroy(connection); - } catch (final Exception e) { - s_logger.debug("Unable to destroy task " + task.toString() + " on host " + _host.getUuid() + " due to " + e.toString()); - } - } - } - } - - protected MigrateWithStorageReceiveAnswer execute(final MigrateWithStorageReceiveCommand cmd) { - final Connection connection = getConnection(); - final VirtualMachineTO vmSpec = cmd.getVirtualMachine(); - final Map volumeToFiler = cmd.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 SR sr = getStorageRepository(connection, entry.getValue().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 = getNetwork(connection, nicTo); - nicToNetwork.put(nicTo, network); - } - - final Map other = new HashMap(); - other.put("live", "true"); - final Network network = getNativeNetworkForTraffic(connection, TrafficType.Storage, null).getNetwork(); - final Host host = Host.getByUuid(connection, _host.getUuid()); - final Map token = host.migrateReceive(connection, network, other); - - return new MigrateWithStorageReceiveAnswer(cmd, 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(cmd, e); - } catch (final Exception e) { - s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); - return new MigrateWithStorageReceiveAnswer(cmd, e); - } - } - - protected MigrateWithStorageSendAnswer execute(final MigrateWithStorageSendCommand cmd) { - final Connection connection = getConnection(); - final VirtualMachineTO vmSpec = cmd.getVirtualMachine(); - final Map volumeToSr = cmd.getVolumeToSr(); - final Map nicToNetwork = cmd.getNicToNetwork(); - final Map token = cmd.getToken(); - final String vmName = vmSpec.getName(); - final Set volumeToSet = null; - Task task = null; - try { - final Set vms = VM.getByNameLabel(connection, vmSpec.getName()); - final VM vmToMigrate = vms.iterator().next(); - final Map other = new HashMap(); - other.put("live", "true"); - - // Create the vdi map which tells what volumes of the vm need to go on which sr on the destination. - final Map vdiMap = new HashMap(); - for (final Map.Entry entry : volumeToSr.entrySet()) { - if (entry.getValue() instanceof SR) { - final SR sr = (SR)entry.getValue(); - final VDI vdi = getVDIbyUuid(connection, entry.getKey().getPath()); - vdiMap.put(vdi, sr); - } else { - throw new CloudRuntimeException("The object " + entry.getValue() + " passed is not of type SR."); - } - } - - // Create the vif map. - final Map vifMap = new HashMap(); - for (final Map.Entry entry : nicToNetwork.entrySet()) { - if (entry.getValue() instanceof Network) { - final Network network = (Network)entry.getValue(); - final VIF vif = getVifByMac(connection, vmToMigrate, entry.getKey().getMac()); - vifMap.put(vif, network); - } else { - throw new CloudRuntimeException("The object " + entry.getValue() + " passed is not of type Network."); - } - } - - // Check migration with storage is possible. - task = vmToMigrate.assertCanMigrateAsync(connection, token, true, vdiMap, vifMap, other); - try { - // poll every 1 seconds. - final long timeout = _migratewait * 1000L; - waitForTask(connection, task, 1000, timeout); - checkForSuccess(connection, task); - } catch (final Types.HandleInvalid e) { - s_logger.error("Error while checking if vm " + vmName + " can be migrated.", e); - throw new CloudRuntimeException("Error while checking if vm " + vmName + " can be migrated.", e); - } - - // Migrate now. - task = vmToMigrate.migrateSendAsync(connection, token, true, vdiMap, vifMap, other); - try { - // poll every 1 seconds. - final long timeout = _migratewait * 1000L; - waitForTask(connection, task, 1000, timeout); - checkForSuccess(connection, task); - } catch (final Types.HandleInvalid e) { - s_logger.error("Error while migrating vm " + vmName, e); - throw new CloudRuntimeException("Error while migrating vm " + vmName, e); - } - - return new MigrateWithStorageSendAnswer(cmd, volumeToSet); - } catch (final CloudRuntimeException e) { - s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e); - return new MigrateWithStorageSendAnswer(cmd, e); - } catch (final Exception e) { - s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e); - return new MigrateWithStorageSendAnswer(cmd, e); - } finally { - if (task != null) { - try { - task.destroy(connection); - } catch (final Exception e) { - s_logger.debug("Unable to destroy task " + task.toString() + " on host " + _host.getUuid() + " due to " + e.toString()); - } - } - } - } - protected MigrateWithStorageCompleteAnswer execute(final MigrateWithStorageCompleteCommand cmd) { final Connection connection = getConnection(); final VirtualMachineTO vmSpec = cmd.getVirtualMachine(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d5414d26/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/CitrixRequestWrapper.java ---------------------------------------------------------------------- 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 e89d926..b0376c7 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,7 +45,9 @@ 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.MigrateWithStorageCompleteCommand; import com.cloud.agent.api.MigrateWithStorageReceiveCommand; +import com.cloud.agent.api.MigrateWithStorageSendCommand; import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.NetworkRulesSystemVmCommand; @@ -197,6 +199,8 @@ public class CitrixRequestWrapper extends RequestWrapper { final Hashtable, CommandWrapper> xenServer610Commands = new Hashtable, CommandWrapper>(); xenServer610Commands.put(MigrateWithStorageCommand.class, new XenServer610MigrateWithStorageCommandWrapper()); xenServer610Commands.put(MigrateWithStorageReceiveCommand.class, new XenServer610MigrateWithStorageReceiveCommandWrapper()); + xenServer610Commands.put(MigrateWithStorageSendCommand.class, new XenServer610MigrateWithStorageSendCommandWrapper()); + xenServer610Commands.put(MigrateWithStorageCompleteCommand.class, new XenServer610MigrateWithStorageCompleteCommandWrapper()); resources.put(XenServer610Resource.class, xenServer610Commands); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d5414d26/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageCompleteCommandWrapper.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageCompleteCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageCompleteCommandWrapper.java new file mode 100644 index 0000000..e993b96 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageCompleteCommandWrapper.java @@ -0,0 +1,81 @@ +// +// 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.List; +import java.util.Set; + +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.MigrateWithStorageCompleteAnswer; +import com.cloud.agent.api.MigrateWithStorageCompleteCommand; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.hypervisor.xenserver.resource.XenServer610Resource; +import com.cloud.hypervisor.xenserver.resource.XsHost; +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.VM; + +public final class XenServer610MigrateWithStorageCompleteCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(XenServer610MigrateWithStorageCompleteCommandWrapper.class); + + @Override + public Answer execute(final MigrateWithStorageCompleteCommand command, final XenServer610Resource xenServer610Resource) { + final Connection connection = xenServer610Resource.getConnection(); + final VirtualMachineTO vmSpec = command.getVirtualMachine(); + + final String name = vmSpec.getName(); + try { + final XsHost xsHost = xenServer610Resource.getHost(); + final String uuid = xsHost.getUuid(); + + final Set vms = VM.getByNameLabel(connection, name); + // Check if VMs can be found by label. + if (vms == null) { + throw new CloudRuntimeException("Couldn't find VMs by label " + name + " on the destination host."); + } + final VM migratedVm = vms.iterator().next(); + + // Check the vm is present on the new host. + if (migratedVm == null) { + throw new CloudRuntimeException("Couldn't find the migrated vm " + name + " on the destination host."); + } + + final Host host = Host.getByUuid(connection, uuid); + migratedVm.setAffinity(connection, host); + + // Volume paths would have changed. Return that information. + final List volumeToSet = xenServer610Resource.getUpdatedVolumePathsOfMigratedVm(connection, migratedVm, vmSpec.getDisks()); + + return new MigrateWithStorageCompleteAnswer(command, volumeToSet); + } catch (final CloudRuntimeException e) { + s_logger.error("Migration of vm " + name + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageCompleteAnswer(command, e); + } catch (final Exception e) { + s_logger.error("Migration of vm " + name + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageCompleteAnswer(command, e); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d5414d26/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageSendCommandWrapper.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageSendCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageSendCommandWrapper.java new file mode 100644 index 0000000..267f528 --- /dev/null +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610MigrateWithStorageSendCommandWrapper.java @@ -0,0 +1,143 @@ +// +// 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 java.util.Set; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.MigrateWithStorageSendAnswer; +import com.cloud.agent.api.MigrateWithStorageSendCommand; +import com.cloud.agent.api.to.NicTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.hypervisor.xenserver.resource.XenServer610Resource; +import com.cloud.resource.CommandWrapper; +import com.cloud.utils.exception.CloudRuntimeException; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Task; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VIF; +import com.xensource.xenapi.VM; + +public final class XenServer610MigrateWithStorageSendCommandWrapper extends CommandWrapper { + + private static final Logger s_logger = Logger.getLogger(XenServer610MigrateWithStorageSendCommandWrapper.class); + + @Override + public Answer execute(final MigrateWithStorageSendCommand command, final XenServer610Resource xenServer610Resource) { + final Connection connection = xenServer610Resource.getConnection(); + + final VirtualMachineTO vmSpec = command.getVirtualMachine(); + final Map volumeToSr = command.getVolumeToSr(); + final Map nicToNetwork = command.getNicToNetwork(); + final Map token = command.getToken(); + final String vmName = vmSpec.getName(); + + Task task = null; + try { + + final Map other = new HashMap(); + other.put("live", "true"); + + // Create the vdi map which tells what volumes of the vm need to go + // on which sr on the destination. + final Map vdiMap = new HashMap(); + for (final Map.Entry entry : volumeToSr.entrySet()) { + final Object srObj = entry.getValue(); + if (srObj instanceof SR) { + final SR sr = (SR) srObj; + final VolumeTO volume = entry.getKey(); + final VDI vdi = xenServer610Resource.getVDIbyUuid(connection, volume.getPath()); + vdiMap.put(vdi, sr); + } else { + throw new CloudRuntimeException("The object " + srObj + " passed is not of type SR."); + } + } + + final Set vms = VM.getByNameLabel(connection, vmSpec.getName()); + VM vmToMigrate = null; + if (vms != null) { + vmToMigrate = vms.iterator().next(); + } + + // Create the vif map. + final Map vifMap = new HashMap(); + for (final Map.Entry entry : nicToNetwork.entrySet()) { + Object networkObj = entry.getValue(); + if (networkObj instanceof Network) { + final Network network = (Network) networkObj; + NicTO nic = entry.getKey(); + final VIF vif = xenServer610Resource.getVifByMac(connection, vmToMigrate, nic.getMac()); + vifMap.put(vif, network); + } else { + throw new CloudRuntimeException("The object " + networkObj + " passed is not of type Network."); + } + } + + // Check migration with storage is possible. + task = vmToMigrate.assertCanMigrateAsync(connection, token, true, vdiMap, vifMap, other); + try { + // poll every 1 seconds. + final long timeout = xenServer610Resource.getMigrateWait() * 1000L; + xenServer610Resource.waitForTask(connection, task, 1000, timeout); + xenServer610Resource.checkForSuccess(connection, task); + } catch (final Types.HandleInvalid e) { + s_logger.error("Error while checking if vm " + vmName + " can be migrated.", e); + throw new CloudRuntimeException("Error while checking if vm " + vmName + " can be migrated.", e); + } + + // Migrate now. + task = vmToMigrate.migrateSendAsync(connection, token, true, vdiMap, vifMap, other); + try { + // poll every 1 seconds. + final long timeout = xenServer610Resource.getMigrateWait() * 1000L; + xenServer610Resource.waitForTask(connection, task, 1000, timeout); + xenServer610Resource.checkForSuccess(connection, task); + } catch (final Types.HandleInvalid e) { + s_logger.error("Error while migrating vm " + vmName, e); + throw new CloudRuntimeException("Error while migrating vm " + vmName, e); + } + + final Set volumeToSet = null; + return new MigrateWithStorageSendAnswer(command, volumeToSet); + } catch (final CloudRuntimeException e) { + s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageSendAnswer(command, e); + } catch (final Exception e) { + s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageSendAnswer(command, e); + } finally { + if (task != null) { + try { + task.destroy(connection); + } catch (final Exception e) { + s_logger.debug("Unable to destroy task " + task.toString() + " on host " + xenServer610Resource.getHost().getUuid() + " due to " + e.toString()); + } + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d5414d26/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/XenServer610WrapperTest.java ---------------------------------------------------------------------- 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 649dd1f..7f17ed4 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 @@ -40,6 +40,7 @@ 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.MigrateWithStorageSendCommand; import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.StorageFilerTO; @@ -56,6 +57,7 @@ import com.xensource.xenapi.Network; import com.xensource.xenapi.SR; import com.xensource.xenapi.Types.XenAPIException; import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VIF; @RunWith(PowerMockRunner.class) public class XenServer610WrapperTest { @@ -269,4 +271,166 @@ public class XenServer610WrapperTest { assertFalse(answer.getResult()); } + + @Test + public void testMigrateWithStorageSendCommand() { + final String vmName = "small"; + final String path = "/"; + final String mac = "3c:15:c2:c4:4f:18"; + + final Connection conn = Mockito.mock(Connection.class); + final VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class); + + final VolumeTO volume1 = Mockito.mock(VolumeTO.class); + final VolumeTO volume2 = Mockito.mock(VolumeTO.class); + + 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 NicTO nic1 = Mockito.mock(NicTO.class); + final NicTO nic2 = Mockito.mock(NicTO.class); + + final Network network1 = Mockito.mock(Network.class); + final Network network2 = Mockito.mock(Network.class); + + final Map volumeToSr = new HashMap(); + volumeToSr.put(volume1, sr1); + volumeToSr.put(volume2, sr2); + + final Map nicToNetwork = new HashMap(); + nicToNetwork.put(nic1, network1); + nicToNetwork.put(nic2, network2); + + final Map token = new HashMap(); + + final VIF vif1 = Mockito.mock(VIF.class); + final VIF vif2 = Mockito.mock(VIF.class); + + final MigrateWithStorageSendCommand migrateStorageCommand = new MigrateWithStorageSendCommand(vmSpec, volumeToSr, nicToNetwork, token); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(xenServer610Resource.getConnection()).thenReturn(conn); + when(vmSpec.getName()).thenReturn(vmName); + + when(volume1.getPath()).thenReturn(path); + when(volume2.getPath()).thenReturn(path); + + when(nic1.getMac()).thenReturn(mac); + when(nic2.getMac()).thenReturn(mac); + + when(xenServer610Resource.getVDIbyUuid(conn, volume1.getPath())).thenReturn(vdi1); + when(xenServer610Resource.getVDIbyUuid(conn, volume2.getPath())).thenReturn(vdi2); + + try { + when(xenServer610Resource.getVifByMac(conn, null, nic1.getMac())).thenReturn(vif1); + when(xenServer610Resource.getVifByMac(conn, null, nic2.getMac())).thenReturn(vif2); + } 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(2)).getVDIbyUuid(conn, volume1.getPath()); + verify(xenServer610Resource, times(2)).getVifByMac(conn, null, nic1.getMac()); + } catch (final XenAPIException e) { + fail(e.getMessage()); + } catch (final XmlRpcException e) { + fail(e.getMessage()); + } + + assertFalse(answer.getResult()); + } + + @Test + public void testMigrateWithStorageSendCommandSRException() { + final String vmName = "small"; + + final Connection conn = Mockito.mock(Connection.class); + final VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class); + + final VolumeTO volume1 = Mockito.mock(VolumeTO.class); + final VolumeTO volume2 = Mockito.mock(VolumeTO.class); + + final Map volumeToSr = new HashMap(); + volumeToSr.put(volume1, new String("a")); + volumeToSr.put(volume2, new String("b")); + + final Map nicToNetwork = new HashMap(); + final Map token = new HashMap(); + + final MigrateWithStorageSendCommand migrateStorageCommand = new MigrateWithStorageSendCommand(vmSpec, volumeToSr, nicToNetwork, token); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(xenServer610Resource.getConnection()).thenReturn(conn); + when(vmSpec.getName()).thenReturn(vmName); + + final Answer answer = wrapper.execute(migrateStorageCommand, xenServer610Resource); + + verify(xenServer610Resource, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } + + @Test + public void testMigrateWithStorageSendCommandNetException() { + final String vmName = "small"; + final String path = "/"; + + final Connection conn = Mockito.mock(Connection.class); + final VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class); + + final VolumeTO volume1 = Mockito.mock(VolumeTO.class); + final VolumeTO volume2 = Mockito.mock(VolumeTO.class); + + 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 NicTO nic1 = Mockito.mock(NicTO.class); + final NicTO nic2 = Mockito.mock(NicTO.class); + + final Map volumeToSr = new HashMap(); + volumeToSr.put(volume1, sr1); + volumeToSr.put(volume2, sr2); + + final Map nicToNetwork = new HashMap(); + nicToNetwork.put(nic1, new String("a")); + nicToNetwork.put(nic2, new String("b")); + + final Map token = new HashMap(); + + final MigrateWithStorageSendCommand migrateStorageCommand = new MigrateWithStorageSendCommand(vmSpec, volumeToSr, nicToNetwork, token); + + final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance(); + assertNotNull(wrapper); + + when(xenServer610Resource.getConnection()).thenReturn(conn); + when(vmSpec.getName()).thenReturn(vmName); + + when(volume1.getPath()).thenReturn(path); + when(volume2.getPath()).thenReturn(path); + + when(xenServer610Resource.getVDIbyUuid(conn, volume1.getPath())).thenReturn(vdi1); + when(xenServer610Resource.getVDIbyUuid(conn, volume2.getPath())).thenReturn(vdi2); + + final Answer answer = wrapper.execute(migrateStorageCommand, xenServer610Resource); + + verify(xenServer610Resource, times(1)).getConnection(); + + assertFalse(answer.getResult()); + } } \ No newline at end of file