Search in sources :

Example 6 with VirtualMachineMO

use of com.cloud.hypervisor.vmware.mo.VirtualMachineMO in project cloudstack by apache.

the class VmwareResourceTest method testFindVmOnDatacenter.

@Test
public void testFindVmOnDatacenter() throws Exception {
    when(hyperHost.getHyperHostDatacenter()).thenReturn(mor);
    when(datacenter.getMor()).thenReturn(mor);
    when(datacenter.findVm(VOLUME_PATH)).thenReturn(vmMo);
    whenNew(DatacenterMO.class).withArguments(context, mor).thenReturn(datacenter);
    VirtualMachineMO result = _resource.findVmOnDatacenter(context, hyperHost, volume);
    assertEquals(vmMo, result);
}
Also used : VirtualMachineMO(com.cloud.hypervisor.vmware.mo.VirtualMachineMO) PrepareForTest(org.powermock.core.classloader.annotations.PrepareForTest) Test(org.junit.Test)

Example 7 with VirtualMachineMO

use of com.cloud.hypervisor.vmware.mo.VirtualMachineMO in project cloudstack by apache.

the class VmwareStorageProcessor method copyTemplateFromSecondaryToPrimary.

private Pair<VirtualMachineMO, Long> copyTemplateFromSecondaryToPrimary(VmwareHypervisorHost hyperHost, DatastoreMO datastoreMo, String secondaryStorageUrl, String templatePathAtSecondaryStorage, String templateName, String templateUuid, boolean createSnapshot, Integer nfsVersion) throws Exception {
    s_logger.info("Executing copyTemplateFromSecondaryToPrimary. secondaryStorage: " + secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage + ", templateName: " + templateName);
    String secondaryMountPoint = mountService.getMountPoint(secondaryStorageUrl, nfsVersion);
    s_logger.info("Secondary storage mount point: " + secondaryMountPoint);
    String srcOVAFileName = VmwareStorageLayoutHelper.getTemplateOnSecStorageFilePath(secondaryMountPoint, templatePathAtSecondaryStorage, templateName, ImageFormat.OVA.getFileExtension());
    String srcFileName = getOVFFilePath(srcOVAFileName);
    if (srcFileName == null) {
        Script command = new Script("tar", 0, s_logger);
        command.add("--no-same-owner");
        command.add("-xf", srcOVAFileName);
        command.setWorkDir(secondaryMountPoint + "/" + templatePathAtSecondaryStorage);
        s_logger.info("Executing command: " + command.toString());
        String result = command.execute();
        if (result != null) {
            String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
            s_logger.error(msg);
            throw new Exception(msg);
        }
    }
    srcFileName = getOVFFilePath(srcOVAFileName);
    if (srcFileName == null) {
        String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
        s_logger.error(msg);
        throw new Exception(msg);
    }
    String vmName = templateUuid;
    hyperHost.importVmFromOVF(srcFileName, vmName, datastoreMo, "thin");
    VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
    if (vmMo == null) {
        String msg = "Failed to import OVA template. secondaryStorage: " + secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage + ", templateName: " + templateName + ", templateUuid: " + templateUuid;
        s_logger.error(msg);
        throw new Exception(msg);
    }
    OVAProcessor processor = new OVAProcessor();
    Map<String, Object> params = new HashMap<String, Object>();
    params.put(StorageLayer.InstanceConfigKey, _storage);
    processor.configure("OVA Processor", params);
    long virtualSize = processor.getTemplateVirtualSize(secondaryMountPoint + "/" + templatePathAtSecondaryStorage, templateName);
    if (createSnapshot) {
        if (vmMo.createSnapshot("cloud.template.base", "Base snapshot", false, false)) {
            // the same template may be deployed with multiple copies at per-datastore per-host basis,
            // save the original template name from CloudStack DB as the UUID to associate them.
            vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, templateName);
            vmMo.markAsTemplate();
        } else {
            vmMo.destroy();
            String msg = "Unable to create base snapshot for template, templateName: " + templateName + ", templateUuid: " + templateUuid;
            s_logger.error(msg);
            throw new Exception(msg);
        }
    }
    return new Pair<VirtualMachineMO, Long>(vmMo, new Long(virtualSize));
}
Also used : Script(com.cloud.utils.script.Script) OVAProcessor(com.cloud.storage.template.OVAProcessor) HashMap(java.util.HashMap) VirtualMachineMO(com.cloud.hypervisor.vmware.mo.VirtualMachineMO) RemoteException(java.rmi.RemoteException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) Pair(com.cloud.utils.Pair)

Example 8 with VirtualMachineMO

use of com.cloud.hypervisor.vmware.mo.VirtualMachineMO in project cloudstack by apache.

the class VmwareStorageProcessor method createTemplateFromVolume.

@Override
public Answer createTemplateFromVolume(CopyCommand cmd) {
    VolumeObjectTO volume = (VolumeObjectTO) cmd.getSrcTO();
    TemplateObjectTO template = (TemplateObjectTO) cmd.getDestTO();
    DataStoreTO imageStore = template.getDataStore();
    if (!(imageStore instanceof NfsTO)) {
        return new CopyCmdAnswer("unsupported protocol");
    }
    NfsTO nfsImageStore = (NfsTO) imageStore;
    String secondaryStoragePoolURL = nfsImageStore.getUrl();
    String volumePath = volume.getPath();
    String details = null;
    VmwareContext context = hostService.getServiceContext(cmd);
    try {
        VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
        VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(volume.getVmName());
        if (vmMo == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Unable to find the owner VM for CreatePrivateTemplateFromVolumeCommand on host " + hyperHost.getHyperHostName() + ", try within datacenter");
            }
            vmMo = hyperHost.findVmOnPeerHyperHost(volume.getVmName());
            if (vmMo == null) {
                // This means either the volume is on a zone wide storage pool or VM is deleted by external entity.
                // Look for the VM in the datacenter.
                ManagedObjectReference dcMor = hyperHost.getHyperHostDatacenter();
                DatacenterMO dcMo = new DatacenterMO(context, dcMor);
                vmMo = dcMo.findVm(volume.getVmName());
            }
            if (vmMo == null) {
                String msg = "Unable to find the owner VM for volume operation. vm: " + volume.getVmName();
                s_logger.error(msg);
                throw new Exception(msg);
            }
        }
        Ternary<String, Long, Long> result = createTemplateFromVolume(vmMo, template.getPath(), template.getId(), template.getName(), secondaryStoragePoolURL, volumePath, hostService.getWorkerName(context, cmd, 0), _nfsVersion);
        TemplateObjectTO newTemplate = new TemplateObjectTO();
        newTemplate.setPath(result.first());
        newTemplate.setFormat(ImageFormat.OVA);
        newTemplate.setSize(result.third());
        newTemplate.setPhysicalSize(result.second());
        return new CopyCmdAnswer(newTemplate);
    } catch (Throwable e) {
        if (e instanceof RemoteException) {
            hostService.invalidateServiceContext(context);
        }
        s_logger.error("Unexpecpted exception ", e);
        details = "create template from volume exception: " + VmwareHelper.getExceptionMessage(e);
        return new CopyCmdAnswer(details);
    }
}
Also used : PrimaryDataStoreTO(org.apache.cloudstack.storage.to.PrimaryDataStoreTO) DataStoreTO(com.cloud.agent.api.to.DataStoreTO) VirtualMachineMO(com.cloud.hypervisor.vmware.mo.VirtualMachineMO) VmwareHypervisorHost(com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost) NfsTO(com.cloud.agent.api.to.NfsTO) RemoteException(java.rmi.RemoteException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) VmwareContext(com.cloud.hypervisor.vmware.util.VmwareContext) VolumeObjectTO(org.apache.cloudstack.storage.to.VolumeObjectTO) TemplateObjectTO(org.apache.cloudstack.storage.to.TemplateObjectTO) RemoteException(java.rmi.RemoteException) CopyCmdAnswer(org.apache.cloudstack.storage.command.CopyCmdAnswer) ManagedObjectReference(com.vmware.vim25.ManagedObjectReference) DatacenterMO(com.cloud.hypervisor.vmware.mo.DatacenterMO)

Example 9 with VirtualMachineMO

use of com.cloud.hypervisor.vmware.mo.VirtualMachineMO in project cloudstack by apache.

the class VmwareStorageProcessor method copyTemplateToPrimaryStorage.

@Override
public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
    DataTO srcData = cmd.getSrcTO();
    TemplateObjectTO template = (TemplateObjectTO) srcData;
    DataStoreTO srcStore = srcData.getDataStore();
    if (!(srcStore instanceof NfsTO)) {
        return new CopyCmdAnswer("unsupported protocol");
    }
    NfsTO nfsImageStore = (NfsTO) srcStore;
    DataTO destData = cmd.getDestTO();
    DataStoreTO destStore = destData.getDataStore();
    DataStoreTO primaryStore = destStore;
    String secondaryStorageUrl = nfsImageStore.getUrl();
    assert (secondaryStorageUrl != null);
    boolean managed = false;
    String storageHost = null;
    int storagePort = Integer.MIN_VALUE;
    String managedStoragePoolName = null;
    String managedStoragePoolRootVolumeName = null;
    String chapInitiatorUsername = null;
    String chapInitiatorSecret = null;
    String chapTargetUsername = null;
    String chapTargetSecret = null;
    if (destStore instanceof PrimaryDataStoreTO) {
        PrimaryDataStoreTO destPrimaryDataStoreTo = (PrimaryDataStoreTO) destStore;
        Map<String, String> details = destPrimaryDataStoreTo.getDetails();
        if (details != null) {
            managed = Boolean.parseBoolean(details.get(PrimaryDataStoreTO.MANAGED));
            if (managed) {
                storageHost = details.get(PrimaryDataStoreTO.STORAGE_HOST);
                try {
                    storagePort = Integer.parseInt(details.get(PrimaryDataStoreTO.STORAGE_PORT));
                } catch (Exception ex) {
                    storagePort = 3260;
                }
                managedStoragePoolName = details.get(PrimaryDataStoreTO.MANAGED_STORE_TARGET);
                managedStoragePoolRootVolumeName = details.get(PrimaryDataStoreTO.MANAGED_STORE_TARGET_ROOT_VOLUME);
                chapInitiatorUsername = details.get(PrimaryDataStoreTO.CHAP_INITIATOR_USERNAME);
                chapInitiatorSecret = details.get(PrimaryDataStoreTO.CHAP_INITIATOR_SECRET);
                chapTargetUsername = details.get(PrimaryDataStoreTO.CHAP_TARGET_USERNAME);
                chapTargetSecret = details.get(PrimaryDataStoreTO.CHAP_TARGET_SECRET);
            }
        }
    }
    String templateUrl = secondaryStorageUrl + "/" + srcData.getPath();
    Pair<String, String> templateInfo = VmwareStorageLayoutHelper.decodeTemplateRelativePathAndNameFromUrl(secondaryStorageUrl, templateUrl, template.getName());
    VmwareContext context = hostService.getServiceContext(cmd);
    if (context == null) {
        return new CopyCmdAnswer("Failed to create a Vmware context, check the management server logs or the ssvm log for details");
    }
    try {
        VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
        String storageUuid = managed ? managedStoragePoolName : primaryStore.getUuid();
        String templateUuidName = deriveTemplateUuidOnHost(hyperHost, storageUuid, templateInfo.second());
        DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
        VirtualMachineMO templateMo = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templateUuidName), true);
        DatastoreMO dsMo = null;
        Pair<VirtualMachineMO, Long> vmInfo = null;
        if (templateMo == null) {
            if (s_logger.isInfoEnabled()) {
                s_logger.info("Template " + templateInfo.second() + " is not setup yet. Set up template from secondary storage with uuid name: " + templateUuidName);
            }
            final ManagedObjectReference morDs;
            if (managed) {
                morDs = prepareManagedDatastore(context, hyperHost, null, managedStoragePoolName, storageHost, storagePort, chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
            } else {
                morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, storageUuid);
            }
            assert (morDs != null);
            dsMo = new DatastoreMO(context, morDs);
            if (managed) {
                vmInfo = copyTemplateFromSecondaryToPrimary(hyperHost, dsMo, secondaryStorageUrl, templateInfo.first(), templateInfo.second(), managedStoragePoolRootVolumeName, false, _nfsVersion);
                VirtualMachineMO vmMo = vmInfo.first();
                vmMo.unregisterVm();
                String[] vmwareLayoutFilePair = VmwareStorageLayoutHelper.getVmdkFilePairDatastorePath(dsMo, managedStoragePoolRootVolumeName, managedStoragePoolRootVolumeName, VmwareStorageLayoutType.VMWARE, false);
                String[] legacyCloudStackLayoutFilePair = VmwareStorageLayoutHelper.getVmdkFilePairDatastorePath(dsMo, null, managedStoragePoolRootVolumeName, VmwareStorageLayoutType.CLOUDSTACK_LEGACY, false);
                dsMo.moveDatastoreFile(vmwareLayoutFilePair[0], dcMo.getMor(), dsMo.getMor(), legacyCloudStackLayoutFilePair[0], dcMo.getMor(), true);
                dsMo.moveDatastoreFile(vmwareLayoutFilePair[1], dcMo.getMor(), dsMo.getMor(), legacyCloudStackLayoutFilePair[1], dcMo.getMor(), true);
                String folderToDelete = dsMo.getDatastorePath(managedStoragePoolRootVolumeName, true);
                dsMo.deleteFolder(folderToDelete, dcMo.getMor());
            } else {
                vmInfo = copyTemplateFromSecondaryToPrimary(hyperHost, dsMo, secondaryStorageUrl, templateInfo.first(), templateInfo.second(), templateUuidName, true, _nfsVersion);
            }
        } else {
            s_logger.info("Template " + templateInfo.second() + " has already been setup, skip the template setup process in primary storage");
        }
        TemplateObjectTO newTemplate = new TemplateObjectTO();
        if (managed) {
            if (dsMo != null) {
                String path = dsMo.getDatastorePath(managedStoragePoolRootVolumeName + ".vmdk");
                newTemplate.setPath(path);
            }
        } else {
            newTemplate.setPath(templateUuidName);
        }
        newTemplate.setSize((vmInfo != null) ? vmInfo.second() : new Long(0));
        return new CopyCmdAnswer(newTemplate);
    } catch (Throwable e) {
        if (e instanceof RemoteException) {
            hostService.invalidateServiceContext(context);
        }
        String msg = "Unable to copy template to primary storage due to exception:" + VmwareHelper.getExceptionMessage(e);
        s_logger.error(msg, e);
        return new CopyCmdAnswer(msg);
    }
}
Also used : PrimaryDataStoreTO(org.apache.cloudstack.storage.to.PrimaryDataStoreTO) DataStoreTO(com.cloud.agent.api.to.DataStoreTO) VirtualMachineMO(com.cloud.hypervisor.vmware.mo.VirtualMachineMO) VmwareHypervisorHost(com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost) NfsTO(com.cloud.agent.api.to.NfsTO) RemoteException(java.rmi.RemoteException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) DatastoreMO(com.cloud.hypervisor.vmware.mo.DatastoreMO) VmwareContext(com.cloud.hypervisor.vmware.util.VmwareContext) DataTO(com.cloud.agent.api.to.DataTO) PrimaryDataStoreTO(org.apache.cloudstack.storage.to.PrimaryDataStoreTO) TemplateObjectTO(org.apache.cloudstack.storage.to.TemplateObjectTO) RemoteException(java.rmi.RemoteException) CopyCmdAnswer(org.apache.cloudstack.storage.command.CopyCmdAnswer) DatacenterMO(com.cloud.hypervisor.vmware.mo.DatacenterMO) ManagedObjectReference(com.vmware.vim25.ManagedObjectReference)

Example 10 with VirtualMachineMO

use of com.cloud.hypervisor.vmware.mo.VirtualMachineMO in project cloudstack by apache.

the class VmwareResource method execute.

protected Answer execute(MigrateWithStorageCommand cmd) {
    if (s_logger.isInfoEnabled()) {
        s_logger.info("Executing resource MigrateWithStorageCommand: " + _gson.toJson(cmd));
    }
    VirtualMachineTO vmTo = cmd.getVirtualMachine();
    String vmName = vmTo.getName();
    VmwareHypervisorHost srcHyperHost = null;
    VmwareHypervisorHost tgtHyperHost = null;
    VirtualMachineMO vmMo = null;
    ManagedObjectReference morDsAtTarget = null;
    ManagedObjectReference morDsAtSource = null;
    ManagedObjectReference morDc = null;
    ManagedObjectReference morDcOfTargetHost = null;
    ManagedObjectReference morTgtHost = new ManagedObjectReference();
    ManagedObjectReference morTgtDatastore = new ManagedObjectReference();
    VirtualMachineRelocateSpec relocateSpec = new VirtualMachineRelocateSpec();
    List<VirtualMachineRelocateSpecDiskLocator> diskLocators = new ArrayList<VirtualMachineRelocateSpecDiskLocator>();
    VirtualMachineRelocateSpecDiskLocator diskLocator = null;
    String tgtDsName = "";
    String tgtDsHost;
    String tgtDsPath;
    int tgtDsPort;
    VolumeTO volume;
    StorageFilerTO filerTo;
    Set<String> mountedDatastoresAtSource = new HashSet<String>();
    List<VolumeObjectTO> volumeToList = new ArrayList<VolumeObjectTO>();
    Map<Long, Integer> volumeDeviceKey = new HashMap<Long, Integer>();
    List<Pair<VolumeTO, StorageFilerTO>> volToFiler = cmd.getVolumeToFilerAsList();
    String tgtHost = cmd.getTargetHost();
    String tgtHostMorInfo = tgtHost.split("@")[0];
    morTgtHost.setType(tgtHostMorInfo.split(":")[0]);
    morTgtHost.setValue(tgtHostMorInfo.split(":")[1]);
    try {
        srcHyperHost = getHyperHost(getServiceContext());
        tgtHyperHost = new HostMO(getServiceContext(), morTgtHost);
        morDc = srcHyperHost.getHyperHostDatacenter();
        morDcOfTargetHost = tgtHyperHost.getHyperHostDatacenter();
        if (!morDc.getValue().equalsIgnoreCase(morDcOfTargetHost.getValue())) {
            String msg = "Source host & target host are in different datacentesr";
            throw new CloudRuntimeException(msg);
        }
        VmwareManager mgr = tgtHyperHost.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
        String srcHostApiVersion = ((HostMO) srcHyperHost).getHostAboutInfo().getApiVersion();
        // find VM through datacenter (VM is not at the target host yet)
        vmMo = srcHyperHost.findVmOnPeerHyperHost(vmName);
        if (vmMo == null) {
            String msg = "VM " + vmName + " does not exist in VMware datacenter " + morDc.getValue();
            s_logger.error(msg);
            throw new Exception(msg);
        }
        vmName = vmMo.getName();
        // Specify destination datastore location for each volume
        for (Pair<VolumeTO, StorageFilerTO> entry : volToFiler) {
            volume = entry.first();
            filerTo = entry.second();
            s_logger.debug("Preparing spec for volume : " + volume.getName());
            morDsAtTarget = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(tgtHyperHost, filerTo.getUuid());
            morDsAtSource = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(srcHyperHost, filerTo.getUuid());
            if (morDsAtTarget == null) {
                String msg = "Unable to find the target datastore: " + filerTo.getUuid() + " on target host: " + tgtHyperHost.getHyperHostName() + " to execute MigrateWithStorageCommand";
                s_logger.error(msg);
                throw new Exception(msg);
            }
            morTgtDatastore = morDsAtTarget;
            // So since only the datastore will be changed first, ensure the target datastore is mounted on source host.
            if (srcHostApiVersion.compareTo("5.1") < 0) {
                tgtDsName = filerTo.getUuid().replace("-", "");
                tgtDsHost = filerTo.getHost();
                tgtDsPath = filerTo.getPath();
                tgtDsPort = filerTo.getPort();
                // If datastore is NFS and target datastore is not already mounted on source host then mount the datastore.
                if (filerTo.getType().equals(StoragePoolType.NetworkFilesystem)) {
                    if (morDsAtSource == null) {
                        morDsAtSource = srcHyperHost.mountDatastore(false, tgtDsHost, tgtDsPort, tgtDsPath, tgtDsName);
                        if (morDsAtSource == null) {
                            throw new Exception("Unable to mount NFS datastore " + tgtDsHost + ":/" + tgtDsPath + " on " + _hostName);
                        }
                        mountedDatastoresAtSource.add(tgtDsName);
                        s_logger.debug("Mounted datastore " + tgtDsHost + ":/" + tgtDsPath + " on " + _hostName);
                    }
                }
                // If datastore is VMFS and target datastore is not mounted or accessible to source host then fail migration.
                if (filerTo.getType().equals(StoragePoolType.VMFS)) {
                    if (morDsAtSource == null) {
                        s_logger.warn("If host version is below 5.1, then target VMFS datastore(s) need to manually mounted on source host for a successful live storage migration.");
                        throw new Exception("Target VMFS datastore: " + tgtDsPath + " is not mounted on source host: " + _hostName);
                    }
                    DatastoreMO dsAtSourceMo = new DatastoreMO(getServiceContext(), morDsAtSource);
                    String srcHostValue = srcHyperHost.getMor().getValue();
                    if (!dsAtSourceMo.isAccessibleToHost(srcHostValue)) {
                        s_logger.warn("If host version is below 5.1, then target VMFS datastore(s) need to accessible to source host for a successful live storage migration.");
                        throw new Exception("Target VMFS datastore: " + tgtDsPath + " is not accessible on source host: " + _hostName);
                    }
                }
                morTgtDatastore = morDsAtSource;
            }
            if (volume.getType() == Volume.Type.ROOT) {
                relocateSpec.setDatastore(morTgtDatastore);
            }
            diskLocator = new VirtualMachineRelocateSpecDiskLocator();
            diskLocator.setDatastore(morDsAtSource);
            Pair<VirtualDisk, String> diskInfo = getVirtualDiskInfo(vmMo, volume.getPath() + ".vmdk");
            String vmdkAbsFile = getAbsoluteVmdkFile(diskInfo.first());
            if (vmdkAbsFile != null && !vmdkAbsFile.isEmpty()) {
                vmMo.updateAdapterTypeIfRequired(vmdkAbsFile);
            }
            int diskId = diskInfo.first().getKey();
            diskLocator.setDiskId(diskId);
            diskLocators.add(diskLocator);
            volumeDeviceKey.put(volume.getId(), diskId);
        }
        // If a target datastore is provided for the VM, then by default all volumes associated with the VM will be migrated to that target datastore.
        // Hence set the existing datastore as target datastore for volumes that are not to be migrated.
        List<Pair<Integer, ManagedObjectReference>> diskDatastores = vmMo.getAllDiskDatastores();
        for (Pair<Integer, ManagedObjectReference> diskDatastore : diskDatastores) {
            if (!volumeDeviceKey.containsValue(diskDatastore.first().intValue())) {
                diskLocator = new VirtualMachineRelocateSpecDiskLocator();
                diskLocator.setDiskId(diskDatastore.first().intValue());
                diskLocator.setDatastore(diskDatastore.second());
                diskLocators.add(diskLocator);
            }
        }
        relocateSpec.getDisk().addAll(diskLocators);
        // Prepare network at target before migration
        NicTO[] nics = vmTo.getNics();
        for (NicTO nic : nics) {
            // prepare network on the host
            prepareNetworkFromNicInfo(new HostMO(getServiceContext(), morTgtHost), nic, false, vmTo.getType());
        }
        // Ensure secondary storage mounted on target host
        Pair<String, Long> secStoreUrlAndId = mgr.getSecondaryStorageStoreUrlAndId(Long.parseLong(_dcId));
        String secStoreUrl = secStoreUrlAndId.first();
        Long secStoreId = secStoreUrlAndId.second();
        if (secStoreUrl == null) {
            String msg = "secondary storage for dc " + _dcId + " is not ready yet?";
            throw new Exception(msg);
        }
        mgr.prepareSecondaryStorageStore(secStoreUrl, secStoreId);
        ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnSpecificHost(secStoreUrl, tgtHyperHost);
        if (morSecDs == null) {
            String msg = "Failed to prepare secondary storage on host, secondary store url: " + secStoreUrl;
            throw new Exception(msg);
        }
        if (srcHostApiVersion.compareTo("5.1") < 0) {
            // Migrate VM's volumes to target datastore(s).
            if (!vmMo.changeDatastore(relocateSpec)) {
                throw new Exception("Change datastore operation failed during storage migration");
            } else {
                s_logger.debug("Successfully migrated storage of VM " + vmName + " to target datastore(s)");
            }
            // Migrate VM to target host.
            ManagedObjectReference morPool = tgtHyperHost.getHyperHostOwnerResourcePool();
            if (!vmMo.migrate(morPool, tgtHyperHost.getMor())) {
                throw new Exception("VM migration to target host failed during storage migration");
            } else {
                s_logger.debug("Successfully migrated VM " + vmName + " from " + _hostName + " to " + tgtHyperHost.getHyperHostName());
            }
        } else {
            // Simultaneously migrate VM's volumes to target datastore and VM to target host.
            relocateSpec.setHost(tgtHyperHost.getMor());
            relocateSpec.setPool(tgtHyperHost.getHyperHostOwnerResourcePool());
            if (!vmMo.changeDatastore(relocateSpec)) {
                throw new Exception("Change datastore operation failed during storage migration");
            } else {
                s_logger.debug("Successfully migrated VM " + vmName + " from " + _hostName + " to " + tgtHyperHost.getHyperHostName() + " and its storage to target datastore(s)");
            }
        }
        // In case of a linked clone VM, if VM's disks are not consolidated, further VM operations such as volume snapshot, VM snapshot etc. will result in DB inconsistencies.
        if (!vmMo.consolidateVmDisks()) {
            s_logger.warn("VM disk consolidation failed after storage migration. Yet proceeding with VM migration.");
        } else {
            s_logger.debug("Successfully consolidated disks of VM " + vmName + ".");
        }
        // Update and return volume path and chain info for every disk because that could have changed after migration
        VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
        for (Pair<VolumeTO, StorageFilerTO> entry : volToFiler) {
            volume = entry.first();
            long volumeId = volume.getId();
            VirtualDisk[] disks = vmMo.getAllDiskDevice();
            for (VirtualDisk disk : disks) {
                if (volumeDeviceKey.get(volumeId) == disk.getKey()) {
                    VolumeObjectTO newVol = new VolumeObjectTO();
                    String newPath = vmMo.getVmdkFileBaseName(disk);
                    String poolName = entry.second().getUuid().replace("-", "");
                    VirtualMachineDiskInfo diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(newPath, poolName);
                    newVol.setId(volumeId);
                    newVol.setPath(newPath);
                    newVol.setChainInfo(_gson.toJson(diskInfo));
                    volumeToList.add(newVol);
                    break;
                }
            }
        }
        return new MigrateWithStorageAnswer(cmd, volumeToList);
    } catch (Throwable e) {
        if (e instanceof RemoteException) {
            s_logger.warn("Encountered remote exception at vCenter, invalidating VMware session context");
            invalidateServiceContext();
        }
        String msg = "MigrationCommand failed due to " + VmwareHelper.getExceptionMessage(e);
        s_logger.warn(msg, e);
        return new MigrateWithStorageAnswer(cmd, (Exception) e);
    } finally {
        // Cleanup datastores mounted on source host
        for (String mountedDatastore : mountedDatastoresAtSource) {
            s_logger.debug("Attempting to unmount datastore " + mountedDatastore + " at " + _hostName);
            try {
                srcHyperHost.unmountDatastore(mountedDatastore);
            } catch (Exception unmountEx) {
                s_logger.debug("Failed to unmount datastore " + mountedDatastore + " at " + _hostName + ". Seems the datastore is still being used by " + _hostName + ". Please unmount manually to cleanup.");
            }
            s_logger.debug("Successfully unmounted datastore " + mountedDatastore + " at " + _hostName);
        }
    }
}
Also used : HashMap(java.util.HashMap) HostMO(com.cloud.hypervisor.vmware.mo.HostMO) ArrayList(java.util.ArrayList) StorageFilerTO(com.cloud.agent.api.to.StorageFilerTO) VirtualMachineTO(com.cloud.agent.api.to.VirtualMachineTO) VolumeTO(com.cloud.agent.api.to.VolumeTO) VirtualMachineRelocateSpec(com.vmware.vim25.VirtualMachineRelocateSpec) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) VirtualMachineDiskInfo(org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo) VolumeObjectTO(org.apache.cloudstack.storage.to.VolumeObjectTO) HashSet(java.util.HashSet) Pair(com.cloud.utils.Pair) NicTO(com.cloud.agent.api.to.NicTO) MigrateWithStorageAnswer(com.cloud.agent.api.MigrateWithStorageAnswer) VmwareManager(com.cloud.hypervisor.vmware.manager.VmwareManager) VirtualMachineMO(com.cloud.hypervisor.vmware.mo.VirtualMachineMO) VirtualMachineDiskInfoBuilder(com.cloud.hypervisor.vmware.mo.VirtualMachineDiskInfoBuilder) VmwareHypervisorHost(com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost) ConnectException(java.net.ConnectException) IOException(java.io.IOException) RemoteException(java.rmi.RemoteException) InternalErrorException(com.cloud.exception.InternalErrorException) CloudException(com.cloud.exception.CloudException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ConfigurationException(javax.naming.ConfigurationException) DatastoreMO(com.cloud.hypervisor.vmware.mo.DatastoreMO) VirtualDisk(com.vmware.vim25.VirtualDisk) RemoteException(java.rmi.RemoteException) ManagedObjectReference(com.vmware.vim25.ManagedObjectReference) VirtualMachineRelocateSpecDiskLocator(com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator)

Aggregations

VirtualMachineMO (com.cloud.hypervisor.vmware.mo.VirtualMachineMO)51 RemoteException (java.rmi.RemoteException)46 CloudRuntimeException (com.cloud.utils.exception.CloudRuntimeException)41 VmwareHypervisorHost (com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost)35 UnsupportedEncodingException (java.io.UnsupportedEncodingException)31 VmwareContext (com.cloud.hypervisor.vmware.util.VmwareContext)28 ManagedObjectReference (com.vmware.vim25.ManagedObjectReference)25 CloudException (com.cloud.exception.CloudException)17 InternalErrorException (com.cloud.exception.InternalErrorException)17 IOException (java.io.IOException)17 ConnectException (java.net.ConnectException)17 ConfigurationException (javax.naming.ConfigurationException)17 DatastoreMO (com.cloud.hypervisor.vmware.mo.DatastoreMO)16 HostMO (com.cloud.hypervisor.vmware.mo.HostMO)14 DatacenterMO (com.cloud.hypervisor.vmware.mo.DatacenterMO)13 VolumeObjectTO (org.apache.cloudstack.storage.to.VolumeObjectTO)11 VirtualDisk (com.vmware.vim25.VirtualDisk)9 DataStoreTO (com.cloud.agent.api.to.DataStoreTO)8 Script (com.cloud.utils.script.Script)8 VmwareManager (com.cloud.hypervisor.vmware.manager.VmwareManager)7