You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ja...@apache.org on 2015/06/29 09:01:10 UTC

[49/50] [abbrv] git commit: updated refs/heads/dhcpoffload to 45721ae

CLOUDSTACK-8324: Added migration changes for config drive


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/b8c112e3
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/b8c112e3
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/b8c112e3

Branch: refs/heads/dhcpoffload
Commit: b8c112e35bcc98e1ee142cfb8901a0d9af28320d
Parents: 17ecd65
Author: Jayapal <ja...@apache.org>
Authored: Tue Jun 9 16:13:21 2015 +0530
Committer: Jayapal <ja...@apache.org>
Committed: Mon Jun 29 12:27:39 2015 +0530

----------------------------------------------------------------------
 .../api/AttachOrDettachConfigDriveCommand.java  |  58 +++++++++++
 .../com/cloud/vm/VirtualMachineManagerImpl.java |  59 ++++++++++-
 .../xenserver/resource/CitrixResourceBase.java  | 102 ++++++++++++++++++-
 ...rver610MigrateWithStorageCommandWrapper.java |   2 +-
 ...ttachOrDettachConfigDriveCommandWrapper.java |  95 +++++++++++++++++
 .../xenbase/CitrixMigrateCommandWrapper.java    |  22 +++-
 ...CitrixPrepareForMigrationCommandWrapper.java |  11 +-
 .../xenbase/XenServer610WrapperTest.java        |   2 +-
 8 files changed, 339 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b8c112e3/core/src/com/cloud/agent/api/AttachOrDettachConfigDriveCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/AttachOrDettachConfigDriveCommand.java b/core/src/com/cloud/agent/api/AttachOrDettachConfigDriveCommand.java
new file mode 100644
index 0000000..ebf5d0b
--- /dev/null
+++ b/core/src/com/cloud/agent/api/AttachOrDettachConfigDriveCommand.java
@@ -0,0 +1,58 @@
+//
+// 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.agent.api;
+
+import java.util.List;
+
+public class AttachOrDettachConfigDriveCommand extends Command {
+
+    String vmName;
+    List<String[]> vmData;
+    String configDriveLabel;
+    boolean isAttach = false;
+
+    public AttachOrDettachConfigDriveCommand(String vmName, List<String[]> vmData, String label, boolean attach) {
+        this.vmName = vmName;
+        this.vmData = vmData;
+        this.configDriveLabel = label;
+        this.isAttach = attach;
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        return false;
+    }
+
+    public String getVmName() {
+        return vmName;
+    }
+
+    public List<String[]> getVmData() {
+        return vmData;
+    }
+
+    public boolean isAttach() {
+        return isAttach;
+    }
+
+    public String getConfigDriveLabel() {
+        return configDriveLabel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b8c112e3/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 057c9e2..4114386 100644
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -38,6 +38,7 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import com.cloud.agent.api.AttachOrDettachConfigDriveCommand;
 import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
@@ -273,6 +274,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     protected VGPUTypesDao _vgpuTypesDao;
     @Inject
     protected EntityManager _entityMgr;
+    @Inject
+    protected GuestOSCategoryDao _guestOSCategoryDao;
+    @Inject
+    protected GuestOSDao _guestOSDao = null;
+    @Inject
+    protected UserVmDetailsDao _vmDetailsDao;
+    @Inject
+    ServiceOfferingDao _serviceOfferingDao = null;
 
     @Inject
     ConfigDepot _configDepot;
@@ -315,6 +324,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     protected VmWorkJobDao _workJobDao;
     @Inject
     protected AsyncJobManager _jobMgr;
+    @Inject
+    protected UserVmService _userVmSrv;
 
     VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this);
 
@@ -352,6 +363,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             Integer.class, "vm.job.report.interval", "60",
             "Interval to send application level pings to make sure the connection is still working", false);
 
+    static final ConfigKey<String> VmConfigDriveLabel = new ConfigKey<String>("Hidden", String.class, "vm.configdrive.label", "config",
+            "The default lable name for the config drive", false);
+
     ScheduledExecutorService _executor = null;
 
     protected long _nodeId;
@@ -1916,6 +1930,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm, null, _offeringDao.findById(vm.getId(), vm.getServiceOfferingId()), null, null);
         _networkMgr.prepareNicForMigration(profile, dest);
         volumeMgr.prepareForMigration(profile, dest);
+        profile.setConfigDriveLabel( _userVmSrv.VmConfigDriveLabel.value());
 
         final VirtualMachineTO to = toVmTO(profile);
         final PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to);
@@ -2215,6 +2230,48 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         boolean migrated = false;
         try {
+
+            // config drive: Detach the config drive at source host
+            // After migration successful attach the config drive in destination host
+            // On migration failure VM will be stopped, So configIso will be deleted
+
+            Nic defaultNic = _networkModel.getDefaultNic(vm.getId());
+
+            List<String[]> vmData = null;
+            if (defaultNic != null) {
+                UserVmVO userVm = _userVmDao.findById(vm.getId());
+                Map<String, String> details = _vmDetailsDao.listDetailsKeyPairs(vm.getId());
+                vm.setDetails(details);
+
+                Network network = _networkModel.getNetwork(defaultNic.getNetworkId());
+                if (_networkModel.isSharedNetworkWithoutServices(network.getId())) {
+                    final String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText();
+                    final String zoneName = _dcDao.findById(vm.getDataCenterId()).getName();
+                    boolean isWindows = _guestOSCategoryDao.findById(_guestOSDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
+
+                    vmData = _networkModel.generateVmData(userVm.getUserData(), serviceOffering, zoneName, vm.getInstanceName(), vm.getId(),
+                            (String) profile.getParameter(VirtualMachineProfile.Param.VmSshPubKey), (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
+                    String vmName = vm.getInstanceName();
+                    String configDriveIsoRootFolder = "/tmp";
+                    String isoFile = configDriveIsoRootFolder + "/" + vmName + "/configDrive/" + vmName + ".iso";
+                    profile.setVmData(vmData);
+                    profile.setConfigDriveLabel(VmConfigDriveLabel.value());
+                    profile.setConfigDriveIsoRootFolder(configDriveIsoRootFolder);
+                    profile.setConfigDriveIsoFile(isoFile);
+
+                    // At source host detach the config drive iso.
+                    AttachOrDettachConfigDriveCommand dettachCommand = new AttachOrDettachConfigDriveCommand(vm.getInstanceName(), vmData, VmConfigDriveLabel.value(), false);
+                    try {
+                        _agentMgr.send(srcHost.getId(), dettachCommand);
+                        s_logger.debug("Deleted config drive ISO for  vm " + vm.getInstanceName() + " In host " + srcHost);
+                    } catch (OperationTimedoutException e) {
+                        s_logger.debug("TIme out occured while exeuting command AttachOrDettachConfigDrive " + e.getMessage());
+
+                    }
+
+                }
+            }
+
             // Migrate the vm and its volume.
             volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPoolMap);
 
@@ -3614,7 +3671,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     public ConfigKey<?>[] getConfigKeys() {
         return new ConfigKey<?>[] {ClusterDeltaSyncInterval, StartRetry, VmDestroyForcestop, VmOpCancelInterval, VmOpCleanupInterval, VmOpCleanupWait,
                 VmOpLockStateRetry,
-                VmOpWaitInterval, ExecuteInSequence, VmJobCheckInterval, VmJobTimeout, VmJobStateReportInterval};
+                VmOpWaitInterval, ExecuteInSequence, VmJobCheckInterval, VmJobTimeout, VmJobStateReportInterval, VmConfigDriveLabel};
     }
 
     public List<StoragePoolAllocator> getStoragePoolAllocators() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b8c112e3/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
index 8ed4ffc..9fb18b8 100644
--- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java
@@ -257,7 +257,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
 
     protected  String _configDriveIsopath = "/opt/xensource/packages/configdrive_iso/";
     protected  String _configDriveSRName = "ConfigDriveISOs";
-    protected  String _attachIsoDeviceNum = "3";
+    public String _attachIsoDeviceNum = "3";
 
     protected int _wait;
     // Hypervisor specific params with generic value, may need to be overridden
@@ -3888,17 +3888,29 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return new ExecutionResult(true, null);
     }
 
-    public void prepareISO(final Connection conn, final String vmName) throws XmlRpcException, XenAPIException {
+    public void prepareISO(final Connection conn, final String vmName,  List<String[]> vmDataList, String configDriveLabel) throws XmlRpcException, XenAPIException {
 
         final Set<VM> vms = VM.getByNameLabel(conn, vmName);
         if (vms == null || vms.size() != 1) {
             throw new CloudRuntimeException("There are " + (vms == null ? "0" : vms.size()) + " VMs named " + vmName);
         }
         final VM vm = vms.iterator().next();
+
+        if (vmDataList != null) {
+            // create SR
+            SR sr =  createLocalIsoSR(conn, _configDriveSRName+getHost().getIp());
+
+            // 1. create vm data files
+            createVmdataFiles(vmName, vmDataList, configDriveLabel);
+
+            // 2. copy config drive iso to host
+            copyConfigDriveIsoToHost(conn, sr, vmName);
+        }
+
         final Set<VBD> vbds = vm.getVBDs(conn);
         for (final VBD vbd : vbds) {
             final VBD.Record vbdr = vbd.getRecord(conn);
-            if (vbdr.type == Types.VbdType.CD && vbdr.empty == false) {
+            if (vbdr.type == Types.VbdType.CD && vbdr.empty == false && vbdr.userdevice.equals(_attachIsoDeviceNum)) {
                 final VDI vdi = vbdr.VDI;
                 final SR sr = vdi.getSR(conn);
                 final Set<PBD> pbds = sr.getPBDs(conn);
@@ -5270,4 +5282,88 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         }
     }
 
+
+    protected SR getSRByNameLabel(Connection conn, String name) throws BadServerResponse, XenAPIException, XmlRpcException {
+        Set<SR> srs = SR.getByNameLabel(conn, name);
+        SR ressr = null;
+        for (SR sr : srs) {
+            Set<PBD> pbds;
+            pbds = sr.getPBDs(conn);
+            for (PBD pbd : pbds) {
+                PBD.Record pbdr = pbd.getRecord(conn);
+                if (pbdr.host != null) {
+                    ressr = sr;
+                    break;
+                }
+            }
+        }
+        return ressr;
+    }
+
+
+    public boolean AttachConfigDriveToMigratedVm(Connection conn, String vmName, String ipAddr) {
+
+        // attach the config drive in destination host
+
+        try {
+            s_logger.debug("Attaching config drive iso device for the VM "+ vmName + " In host "+ ipAddr);
+            Set<VM> vms = VM.getByNameLabel(conn, vmName);
+
+            SR sr = getSRByNameLabel(conn, _configDriveSRName + ipAddr);
+            //Here you will find only two vdis with the <vmname>.iso.
+            //one is from source host and second from dest host
+            Set<VDI> vdis = VDI.getByNameLabel(conn, vmName + ".iso");
+            if (vdis.isEmpty()) {
+                s_logger.debug("Could not find config drive ISO: " + vmName);
+                return false;
+            }
+
+            VDI configdriveVdi = null;
+            for (VDI vdi : vdis) {
+                SR vdiSr = vdi.getSR(conn);
+                if (vdiSr.getUuid(conn).equals(sr.getUuid(conn))) {
+                    //get this vdi to attach to vbd
+                    configdriveVdi = vdi;
+                    s_logger.debug("VDI for the config drive ISO  " + vdi);
+                } else {
+                    // delete the vdi in source host so that the <vmname>.iso file is get removed
+                    s_logger.debug("Removing the source host VDI for the config drive ISO  " + vdi);
+                    vdi.destroy(conn);
+                }
+            }
+
+            if (configdriveVdi == null) {
+                s_logger.debug("Config drive ISO VDI is not found ");
+                return false;
+            }
+
+            for (VM vm : vms) {
+
+                //create vbd
+                VBD.Record cfgDriveVbdr = new VBD.Record();
+                cfgDriveVbdr.VM = vm;
+                cfgDriveVbdr.empty = true;
+                cfgDriveVbdr.bootable = false;
+                cfgDriveVbdr.userdevice = "autodetect";
+                cfgDriveVbdr.mode = Types.VbdMode.RO;
+                cfgDriveVbdr.type = Types.VbdType.CD;
+
+                VBD cfgDriveVBD = VBD.create(conn, cfgDriveVbdr);
+
+                s_logger.debug("Inserting vbd " + configdriveVdi);
+                cfgDriveVBD.insert(conn, configdriveVdi);
+                break;
+
+            }
+
+            return true;
+
+        }catch (Exception ex) {
+            s_logger.debug("Failed to attach config drive ISO to the VM  "+ vmName + " In host " + ipAddr );
+            return false;
+        }
+
+    }
+
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b8c112e3/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageCommandWrapper.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageCommandWrapper.java
index b5c175a..2a79d26 100644
--- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageCommandWrapper.java
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageCommandWrapper.java
@@ -67,7 +67,7 @@ public final class XenServer610MigrateWithStorageCommandWrapper extends CommandW
         final XsHost xsHost = xenServer610Resource.getHost();
         final String uuid = xsHost.getUuid();
         try {
-            xenServer610Resource.prepareISO(connection, vmName);
+            xenServer610Resource.prepareISO(connection, vmName, null, null);
 
             // Get the list of networks and recreate VLAN, if required.
             for (final NicTO nicTo : vmSpec.getNics()) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b8c112e3/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixAttachOrDettachConfigDriveCommandWrapper.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixAttachOrDettachConfigDriveCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixAttachOrDettachConfigDriveCommandWrapper.java
new file mode 100644
index 0000000..a7bfa45
--- /dev/null
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixAttachOrDettachConfigDriveCommandWrapper.java
@@ -0,0 +1,95 @@
+//
+// 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.xenbase;
+
+import java.util.List;
+import java.util.Set;
+
+import com.cloud.agent.api.AttachOrDettachConfigDriveCommand;
+import com.cloud.resource.ResourceWrapper;
+import com.xensource.xenapi.Connection;
+import com.xensource.xenapi.VBD;
+import com.xensource.xenapi.VDI;
+import com.xensource.xenapi.VM;
+import com.xensource.xenapi.Types;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase;
+import com.cloud.resource.CommandWrapper;
+import org.apache.xmlrpc.XmlRpcException;
+
+@ResourceWrapper(handles =  AttachOrDettachConfigDriveCommand.class)
+public final class CitrixAttachOrDettachConfigDriveCommandWrapper extends CommandWrapper<AttachOrDettachConfigDriveCommand, Answer, CitrixResourceBase> {
+
+    private static final Logger s_logger = Logger.getLogger(CitrixAttachOrDettachConfigDriveCommandWrapper.class);
+
+    @Override
+    public Answer execute(final AttachOrDettachConfigDriveCommand command, final CitrixResourceBase citrixResourceBase) {
+        final Connection conn = citrixResourceBase.getConnection();
+
+        String vmName = command.getVmName();
+        List<String[]> vmData = command.getVmData();
+        String label = command.getConfigDriveLabel();
+        Boolean isAttach = command.isAttach();
+
+        try {
+            Set<VM> vms = VM.getByNameLabel(conn, vmName);
+            for (VM vm : vms) {
+                if (isAttach) {
+                    if (!citrixResourceBase.createAndAttachConfigDriveIsoForVM(conn, vm, vmData, label)) {
+                        s_logger.debug("Failed to attach config drive iso to VM " + vmName);
+                    }
+                } else {
+                    // delete the config drive iso attached to VM
+                    Set<VDI> vdis = VDI.getByNameLabel(conn, vmName+".iso");
+                    if (vdis != null && !vdis.isEmpty()) {
+                        s_logger.debug("Deleting config drive for the VM " + vmName);
+                        VDI vdi = vdis.iterator().next();
+                        // Find the VM's CD-ROM VBD
+                        Set<VBD> vbds = vdi.getVBDs(conn);
+
+                        for (VBD vbd : vbds) {
+                            VBD.Record vbdRec = vbd.getRecord(conn);
+
+                            if (vbdRec.type.equals(Types.VbdType.CD) && !vbdRec.empty && !vbdRec.userdevice.equals(citrixResourceBase._attachIsoDeviceNum)) {
+                                if (vbdRec.currentlyAttached) {
+                                    vbd.eject(conn);
+                                }
+                                vbd.destroy(conn);
+                            }
+                        }
+                        vdi.destroy(conn);
+                    }
+
+                    s_logger.debug("Successfully dettached config drive iso from the VM " + vmName);
+                }
+            }
+        }catch (Types.XenAPIException ex) {
+            s_logger.debug("Failed to attach config drive iso to VM " + vmName + " " + ex.getMessage() );
+        }catch (XmlRpcException ex) {
+            s_logger.debug("Failed to attach config drive iso to VM " + vmName + " "+ex.getMessage());
+        }
+
+        return new Answer(command, true, "success");
+
+
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b8c112e3/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixMigrateCommandWrapper.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixMigrateCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixMigrateCommandWrapper.java
index 07f7cc6..00ed622 100644
--- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixMigrateCommandWrapper.java
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixMigrateCommandWrapper.java
@@ -44,24 +44,23 @@ public final class CitrixMigrateCommandWrapper extends CommandWrapper<MigrateCom
     public Answer execute(final MigrateCommand command, final CitrixResourceBase citrixResourceBase) {
         final Connection conn = citrixResourceBase.getConnection();
         final String vmName = command.getVmName();
+        final String dstHostIpAddr = command.getDestinationIp();
 
         try {
             final Set<VM> vms = VM.getByNameLabel(conn, vmName);
 
-            final String ipaddr = command.getDestinationIp();
-
             final Set<Host> hosts = Host.getAll(conn);
             Host dsthost = null;
             if(hosts != null) {
                 for (final Host host : hosts) {
-                    if (host.getAddress(conn).equals(ipaddr)) {
+                    if (host.getAddress(conn).equals(dstHostIpAddr)) {
                         dsthost = host;
                         break;
                     }
                 }
             }
             if (dsthost == null) {
-                final String msg = "Migration failed due to unable to find host " + ipaddr + " in XenServer pool " + citrixResourceBase.getHost().getPool();
+                final String msg = "Migration failed due to unable to find host " + dstHostIpAddr + " in XenServer pool " + citrixResourceBase.getHost().getPool();
                 s_logger.warn(msg);
                 return new MigrateAnswer(command, false, msg, null);
             }
@@ -71,12 +70,25 @@ public final class CitrixMigrateCommandWrapper extends CommandWrapper<MigrateCom
                     final VBD.Record vbdRec = vbd.getRecord(conn);
                     if (vbdRec.type.equals(Types.VbdType.CD) && !vbdRec.empty) {
                         vbd.eject(conn);
-                        break;
+                        // for config drive vbd destroy the vbd.
+                        if (!vbdRec.userdevice.equals(citrixResourceBase._attachIsoDeviceNum)) {
+                            if (vbdRec.currentlyAttached) {
+                                vbd.destroy(conn);
+                            }
+                        }
+                        continue;
                     }
                 }
                 citrixResourceBase.migrateVM(conn, dsthost, vm, vmName);
                 vm.setAffinity(conn, dsthost);
             }
+
+            // The iso can be attached to vm only once the vm is (present in the host) migrated.
+            // Attach the config drive iso device to VM
+            if (!citrixResourceBase.AttachConfigDriveToMigratedVm(conn, vmName, dstHostIpAddr)) {
+                s_logger.debug("Config drive ISO attach failed after migration for vm "+vmName);
+            }
+
             return new MigrateAnswer(command, true, "migration succeeded", null);
         } catch (final Exception e) {
             s_logger.warn(e.getMessage(), e);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b8c112e3/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPrepareForMigrationCommandWrapper.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPrepareForMigrationCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPrepareForMigrationCommandWrapper.java
index ffe875c..2fa25be 100644
--- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPrepareForMigrationCommandWrapper.java
+++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPrepareForMigrationCommandWrapper.java
@@ -31,6 +31,8 @@ import com.cloud.resource.CommandWrapper;
 import com.cloud.resource.ResourceWrapper;
 import com.xensource.xenapi.Connection;
 
+import java.util.List;
+
 @ResourceWrapper(handles =  PrepareForMigrationCommand.class)
 public final class CitrixPrepareForMigrationCommandWrapper extends CommandWrapper<PrepareForMigrationCommand, Answer, CitrixResourceBase> {
 
@@ -41,13 +43,20 @@ public final class CitrixPrepareForMigrationCommandWrapper extends CommandWrappe
         final Connection conn = citrixResourceBase.getConnection();
 
         final VirtualMachineTO vm = command.getVirtualMachine();
+        List<String[]> vmDataList = vm.getVmData();
+        String configDriveLabel = vm.getConfigDriveLabel();
+
+        if (configDriveLabel == null)  {
+            configDriveLabel = "config";
+        }
+
         if (s_logger.isDebugEnabled()) {
             s_logger.debug("Preparing host for migrating " + vm);
         }
 
         final NicTO[] nics = vm.getNics();
         try {
-            citrixResourceBase.prepareISO(conn, vm.getName());
+            citrixResourceBase.prepareISO(conn, vm.getName(), vmDataList, configDriveLabel);
 
             for (final NicTO nic : nics) {
                 citrixResourceBase.getNetwork(conn, nic);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b8c112e3/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java
index f308ea3..70ddfad 100644
--- a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java
+++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java
@@ -170,7 +170,7 @@ public class XenServer610WrapperTest {
         verify(xenServer610Resource, times(1)).getConnection();
 
         try {
-            verify(xenServer610Resource, times(1)).prepareISO(conn, vmName);
+            verify(xenServer610Resource, times(1)).prepareISO(conn, vmName, null, null);
             verify(xenServer610Resource, times(1)).getNetwork(conn, nicTO1);
             verify(xenServer610Resource, times(1)).getNetwork(conn, nicTO2);
             verify(xenServer610Resource, times(1)).getNetwork(conn, nicTO3);