Search in sources :

Example 1 with CopyCommandResult

use of org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult in project cloudstack by apache.

the class StorageSystemDataMotionStrategy method handleCreateVolumeFromSnapshotOnSecondaryStorage.

/**
     * Creates a volume on the storage from a snapshot that resides on the secondary storage (archived snapshot).
     * @param snapshotInfo snapshot on secondary
     * @param volumeInfo volume to be created on the storage
     * @param callback  for async
     */
private void handleCreateVolumeFromSnapshotOnSecondaryStorage(SnapshotInfo snapshotInfo, VolumeInfo volumeInfo, AsyncCompletionCallback<CopyCommandResult> callback) {
    // at this point, the snapshotInfo and volumeInfo should have the same disk offering ID (so either one should be OK to get a DiskOfferingVO instance)
    DiskOfferingVO diskOffering = _diskOfferingDao.findByIdIncludingRemoved(volumeInfo.getDiskOfferingId());
    SnapshotVO snapshot = _snapshotDao.findById(snapshotInfo.getId());
    // update the volume's hv_ss_reserve (hypervisor snapshot reserve) from a disk offering (used for managed storage)
    _volumeService.updateHypervisorSnapshotReserveForVolume(diskOffering, volumeInfo.getId(), snapshot.getHypervisorType());
    CopyCmdAnswer copyCmdAnswer = null;
    String errMsg = null;
    HostVO hostVO = null;
    try {
        // create a volume on the storage
        AsyncCallFuture<VolumeApiResult> future = _volumeService.createVolumeAsync(volumeInfo, volumeInfo.getDataStore());
        VolumeApiResult result = future.get();
        if (result.isFailed()) {
            LOGGER.error("Failed to create a volume: " + result.getResult());
            throw new CloudRuntimeException(result.getResult());
        }
        volumeInfo = _volumeDataFactory.getVolume(volumeInfo.getId(), volumeInfo.getDataStore());
        volumeInfo.processEvent(Event.MigrationRequested);
        volumeInfo = _volumeDataFactory.getVolume(volumeInfo.getId(), volumeInfo.getDataStore());
        hostVO = getHost(snapshotInfo.getDataCenterId(), false);
        // copy the volume from secondary via the hypervisor
        copyCmdAnswer = performCopyOfVdi(volumeInfo, snapshotInfo, hostVO);
        if (copyCmdAnswer == null || !copyCmdAnswer.getResult()) {
            if (copyCmdAnswer != null && !StringUtils.isEmpty(copyCmdAnswer.getDetails())) {
                errMsg = copyCmdAnswer.getDetails();
            } else {
                errMsg = "Unable to create volume from snapshot";
            }
        }
    } catch (Exception ex) {
        errMsg = ex.getMessage() != null ? ex.getMessage() : "Copy operation failed in 'StorageSystemDataMotionStrategy.handleCreateVolumeFromSnapshotBothOnStorageSystem'";
    }
    CopyCommandResult result = new CopyCommandResult(null, copyCmdAnswer);
    result.setResult(errMsg);
    callback.complete(result);
}
Also used : SnapshotVO(com.cloud.storage.SnapshotVO) DiskOfferingVO(com.cloud.storage.DiskOfferingVO) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) VolumeApiResult(org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult) CopyCommandResult(org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult) CopyCmdAnswer(org.apache.cloudstack.storage.command.CopyCmdAnswer) HostVO(com.cloud.host.HostVO) TimeoutException(java.util.concurrent.TimeoutException) AgentUnavailableException(com.cloud.exception.AgentUnavailableException) OperationTimedoutException(com.cloud.exception.OperationTimedoutException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) ExecutionException(java.util.concurrent.ExecutionException)

Example 2 with CopyCommandResult

use of org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult in project cloudstack by apache.

the class StorageSystemDataMotionStrategy method handleCopyDataToSecondaryStorage.

/**
     * This function is responsible for copying a volume from the managed store to a secondary store. This is used in two cases
     * 1) When creating a template from a snapshot
     * 2) When createSnapshot is called with location=SECONDARY
     *
     * @param snapshotInfo Source snapshot
     * @param destData destination (can be template or snapshot)
     * @param callback callback for async
     */
private void handleCopyDataToSecondaryStorage(SnapshotInfo snapshotInfo, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
    try {
        snapshotInfo.processEvent(Event.CopyingRequested);
    } catch (Exception ex) {
        throw new CloudRuntimeException("This snapshot is not currently in a state where it can be used to create a template.");
    }
    HostVO hostVO = getHost(snapshotInfo);
    boolean usingBackendSnapshot = usingBackendSnapshotFor(snapshotInfo);
    boolean computeClusterSupportsResign = clusterDao.getSupportsResigning(hostVO.getClusterId());
    boolean needCache = needCacheStorage(snapshotInfo, destData);
    DataObject destOnStore = destData;
    if (needCache) {
        // creates an object in the DB for data to be cached
        Scope selectedScope = pickCacheScopeForCopy(snapshotInfo, destData);
        destOnStore = cacheMgr.getCacheObject(snapshotInfo, selectedScope);
        destOnStore.processEvent(Event.CreateOnlyRequested);
    }
    if (usingBackendSnapshot && !computeClusterSupportsResign) {
        String noSupportForResignErrMsg = "Unable to locate an applicable host with which to perform a resignature operation : Cluster ID = " + hostVO.getClusterId();
        LOGGER.warn(noSupportForResignErrMsg);
        throw new CloudRuntimeException(noSupportForResignErrMsg);
    }
    try {
        if (usingBackendSnapshot) {
            createVolumeFromSnapshot(hostVO, snapshotInfo, true);
        }
        DataStore srcDataStore = snapshotInfo.getDataStore();
        String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
        int primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
        CopyCommand copyCommand = new CopyCommand(snapshotInfo.getTO(), destOnStore.getTO(), primaryStorageDownloadWait, VirtualMachineManager.ExecuteInSequence.value());
        String errMsg = null;
        CopyCmdAnswer copyCmdAnswer = null;
        try {
            // (because we passed in true as the third parameter to createVolumeFromSnapshot above).
            if (!usingBackendSnapshot) {
                _volumeService.grantAccess(snapshotInfo, hostVO, srcDataStore);
            }
            Map<String, String> srcDetails = getSnapshotDetails(snapshotInfo);
            copyCommand.setOptions(srcDetails);
            copyCmdAnswer = (CopyCmdAnswer) _agentMgr.send(hostVO.getId(), copyCommand);
            if (!copyCmdAnswer.getResult()) {
                // We were not able to copy. Handle it.
                errMsg = copyCmdAnswer.getDetails();
                throw new CloudRuntimeException(errMsg);
            }
            if (needCache) {
                // If cached storage was needed (in case of object store as secondary
                // storage), at this point, the data has been copied from the primary
                // to the NFS cache by the hypervisor. We now invoke another copy
                // command to copy this data from cache to secondary storage. We
                // then cleanup the cache
                destOnStore.processEvent(Event.OperationSuccessed, copyCmdAnswer);
                CopyCommand cmd = new CopyCommand(destOnStore.getTO(), destData.getTO(), primaryStorageDownloadWait, VirtualMachineManager.ExecuteInSequence.value());
                EndPoint ep = selector.select(destOnStore, destData);
                if (ep == null) {
                    errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
                    LOGGER.error(errMsg);
                    copyCmdAnswer = new CopyCmdAnswer(errMsg);
                } else {
                    copyCmdAnswer = (CopyCmdAnswer) ep.sendMessage(cmd);
                }
                // clean up snapshot copied to staging
                cacheMgr.deleteCacheObject(destOnStore);
            }
        } catch (CloudRuntimeException | AgentUnavailableException | OperationTimedoutException ex) {
            String msg = "Failed to create template from snapshot (Snapshot ID = " + snapshotInfo.getId() + ") : ";
            LOGGER.warn(msg, ex);
            throw new CloudRuntimeException(msg + ex.getMessage());
        } finally {
            _volumeService.revokeAccess(snapshotInfo, hostVO, srcDataStore);
            if (copyCmdAnswer == null || !copyCmdAnswer.getResult()) {
                if (copyCmdAnswer != null && !StringUtils.isEmpty(copyCmdAnswer.getDetails())) {
                    errMsg = copyCmdAnswer.getDetails();
                    if (needCache) {
                        cacheMgr.deleteCacheObject(destOnStore);
                    }
                } else {
                    errMsg = "Unable to create template from snapshot";
                }
            }
            try {
                if (StringUtils.isEmpty(errMsg)) {
                    snapshotInfo.processEvent(Event.OperationSuccessed);
                } else {
                    snapshotInfo.processEvent(Event.OperationFailed);
                }
            } catch (Exception ex) {
                LOGGER.warn("Error processing snapshot event: " + ex.getMessage(), ex);
            }
        }
        CopyCommandResult result = new CopyCommandResult(null, copyCmdAnswer);
        result.setResult(errMsg);
        callback.complete(result);
    } finally {
        if (usingBackendSnapshot) {
            deleteVolumeFromSnapshot(snapshotInfo);
        }
    }
}
Also used : OperationTimedoutException(com.cloud.exception.OperationTimedoutException) CopyCommand(org.apache.cloudstack.storage.command.CopyCommand) EndPoint(org.apache.cloudstack.engine.subsystem.api.storage.EndPoint) TimeoutException(java.util.concurrent.TimeoutException) AgentUnavailableException(com.cloud.exception.AgentUnavailableException) OperationTimedoutException(com.cloud.exception.OperationTimedoutException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) ExecutionException(java.util.concurrent.ExecutionException) HostVO(com.cloud.host.HostVO) EndPoint(org.apache.cloudstack.engine.subsystem.api.storage.EndPoint) DataObject(org.apache.cloudstack.engine.subsystem.api.storage.DataObject) ZoneScope(org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope) Scope(org.apache.cloudstack.engine.subsystem.api.storage.Scope) HostScope(org.apache.cloudstack.engine.subsystem.api.storage.HostScope) ClusterScope(org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) AgentUnavailableException(com.cloud.exception.AgentUnavailableException) DataStore(org.apache.cloudstack.engine.subsystem.api.storage.DataStore) CopyCommandResult(org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult) CopyCmdAnswer(org.apache.cloudstack.storage.command.CopyCmdAnswer)

Example 3 with CopyCommandResult

use of org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult in project cloudstack by apache.

the class DataMotionServiceImpl method invokeCallback.

private void invokeCallback(String errMsg, AsyncCompletionCallback<CopyCommandResult> callback) {
    CopyCmdAnswer copyCmdAnswer = new CopyCmdAnswer(errMsg);
    CopyCommandResult result = new CopyCommandResult(null, copyCmdAnswer);
    result.setResult(errMsg);
    callback.complete(result);
}
Also used : CopyCommandResult(org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult) CopyCmdAnswer(org.apache.cloudstack.storage.command.CopyCmdAnswer)

Example 4 with CopyCommandResult

use of org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult in project cloudstack by apache.

the class StorageSystemDataMotionStrategy method handleVolumeMigrationFromNonManagedStorageToManagedStorage.

private void handleVolumeMigrationFromNonManagedStorageToManagedStorage(VolumeInfo srcVolumeInfo, VolumeInfo destVolumeInfo, AsyncCompletionCallback<CopyCommandResult> callback) {
    String errMsg = null;
    try {
        HypervisorType hypervisorType = srcVolumeInfo.getHypervisorType();
        if (!HypervisorType.XenServer.equals(hypervisorType) && !HypervisorType.KVM.equals(hypervisorType)) {
            throw new CloudRuntimeException("Currently, only the XenServer and KVM hypervisor types are supported for the migration of a volume " + "from non-managed storage to managed storage.");
        }
        if (HypervisorType.XenServer.equals(hypervisorType)) {
            handleVolumeMigrationForXenServer(srcVolumeInfo, destVolumeInfo);
        } else {
            handleVolumeMigrationForKVM(srcVolumeInfo, destVolumeInfo);
        }
    } catch (Exception ex) {
        errMsg = "Migration operation failed in 'StorageSystemDataMotionStrategy.handleVolumeMigrationFromNonManagedStorageToManagedStorage': " + ex.getMessage();
        throw new CloudRuntimeException(errMsg);
    } finally {
        CopyCmdAnswer copyCmdAnswer;
        if (errMsg != null) {
            copyCmdAnswer = new CopyCmdAnswer(errMsg);
        } else {
            destVolumeInfo = _volumeDataFactory.getVolume(destVolumeInfo.getId(), destVolumeInfo.getDataStore());
            DataTO dataTO = destVolumeInfo.getTO();
            copyCmdAnswer = new CopyCmdAnswer(dataTO);
        }
        CopyCommandResult result = new CopyCommandResult(null, copyCmdAnswer);
        result.setResult(errMsg);
        callback.complete(result);
    }
}
Also used : HypervisorType(com.cloud.hypervisor.Hypervisor.HypervisorType) DataTO(com.cloud.agent.api.to.DataTO) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) CopyCommandResult(org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult) AgentUnavailableException(com.cloud.exception.AgentUnavailableException) OperationTimedoutException(com.cloud.exception.OperationTimedoutException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) CopyCmdAnswer(org.apache.cloudstack.storage.command.CopyCmdAnswer)

Example 5 with CopyCommandResult

use of org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult in project cloudstack by apache.

the class StorageSystemDataMotionStrategy method handleCreateManagedVolumeFromManagedSnapshot.

private void handleCreateManagedVolumeFromManagedSnapshot(SnapshotInfo snapshotInfo, VolumeInfo volumeInfo, AsyncCompletionCallback<CopyCommandResult> callback) {
    String errMsg = null;
    CopyCmdAnswer copyCmdAnswer = null;
    boolean useCloning = true;
    try {
        verifyFormat(snapshotInfo);
        HostVO hostVO = getHost(snapshotInfo);
        boolean usingBackendSnapshot = usingBackendSnapshotFor(snapshotInfo);
        boolean computeClusterSupportsVolumeClone = true;
        if (HypervisorType.XenServer.equals(snapshotInfo.getHypervisorType())) {
            computeClusterSupportsVolumeClone = clusterDao.getSupportsResigning(hostVO.getClusterId());
            if (usingBackendSnapshot && !computeClusterSupportsVolumeClone) {
                String noSupportForResignErrMsg = "Unable to locate an applicable host with which to perform a resignature operation : Cluster ID = " + hostVO.getClusterId();
                LOGGER.warn(noSupportForResignErrMsg);
                throw new CloudRuntimeException(noSupportForResignErrMsg);
            }
        }
        boolean canStorageSystemCreateVolumeFromVolume = canStorageSystemCreateVolumeFromVolume(snapshotInfo.getDataStore().getId());
        useCloning = usingBackendSnapshot || (canStorageSystemCreateVolumeFromVolume && computeClusterSupportsVolumeClone);
        VolumeDetailVO volumeDetail = null;
        if (useCloning) {
            volumeDetail = new VolumeDetailVO(volumeInfo.getId(), "cloneOfSnapshot", String.valueOf(snapshotInfo.getId()), false);
            volumeDetail = volumeDetailsDao.persist(volumeDetail);
        }
        // at this point, the snapshotInfo and volumeInfo should have the same disk offering ID (so either one should be OK to get a DiskOfferingVO instance)
        DiskOfferingVO diskOffering = _diskOfferingDao.findByIdIncludingRemoved(volumeInfo.getDiskOfferingId());
        SnapshotVO snapshot = _snapshotDao.findById(snapshotInfo.getId());
        // update the volume's hv_ss_reserve (hypervisor snapshot reserve) from a disk offering (used for managed storage)
        _volumeService.updateHypervisorSnapshotReserveForVolume(diskOffering, volumeInfo.getId(), snapshot.getHypervisorType());
        AsyncCallFuture<VolumeApiResult> future = _volumeService.createVolumeAsync(volumeInfo, volumeInfo.getDataStore());
        VolumeApiResult result = future.get();
        if (volumeDetail != null) {
            volumeDetailsDao.remove(volumeDetail.getId());
        }
        if (result.isFailed()) {
            LOGGER.warn("Failed to create a volume: " + result.getResult());
            throw new CloudRuntimeException(result.getResult());
        }
        volumeInfo = _volumeDataFactory.getVolume(volumeInfo.getId(), volumeInfo.getDataStore());
        volumeInfo.processEvent(Event.MigrationRequested);
        volumeInfo = _volumeDataFactory.getVolume(volumeInfo.getId(), volumeInfo.getDataStore());
        if (HypervisorType.XenServer.equals(snapshotInfo.getHypervisorType()) || HypervisorType.VMware.equals(snapshotInfo.getHypervisorType())) {
            if (useCloning) {
                Map<String, String> extraDetails = null;
                if (HypervisorType.VMware.equals(snapshotInfo.getHypervisorType())) {
                    extraDetails = new HashMap<>();
                    String extraDetailsVmdk = getSnapshotProperty(snapshotInfo.getId(), DiskTO.VMDK);
                    extraDetails.put(DiskTO.VMDK, extraDetailsVmdk);
                }
                copyCmdAnswer = performResignature(volumeInfo, hostVO, extraDetails);
                // If using VMware, have the host rescan its software HBA if dynamic discovery is in use.
                if (HypervisorType.VMware.equals(snapshotInfo.getHypervisorType())) {
                    disconnectHostFromVolume(hostVO, volumeInfo.getPoolId(), volumeInfo.get_iScsiName());
                }
            } else {
                // asking for a XenServer host here so we don't always prefer to use XenServer hosts that support resigning
                // even when we don't need those hosts to do this kind of copy work
                hostVO = getHost(snapshotInfo.getDataCenterId(), snapshotInfo.getHypervisorType(), false);
                handleQualityOfServiceForVolumeMigration(volumeInfo, PrimaryDataStoreDriver.QualityOfServiceState.MIGRATION);
                copyCmdAnswer = performCopyOfVdi(volumeInfo, snapshotInfo, hostVO);
            }
            verifyCopyCmdAnswer(copyCmdAnswer, snapshotInfo);
        } else if (HypervisorType.KVM.equals(snapshotInfo.getHypervisorType())) {
            VolumeObjectTO newVolume = new VolumeObjectTO();
            newVolume.setSize(volumeInfo.getSize());
            newVolume.setPath(volumeInfo.get_iScsiName());
            newVolume.setFormat(volumeInfo.getFormat());
            copyCmdAnswer = new CopyCmdAnswer(newVolume);
        } else {
            throw new CloudRuntimeException("Unsupported hypervisor type");
        }
    } catch (Exception ex) {
        errMsg = "Copy operation failed in 'StorageSystemDataMotionStrategy.handleCreateManagedVolumeFromManagedSnapshot': " + ex.getMessage();
        throw new CloudRuntimeException(errMsg);
    } finally {
        if (useCloning) {
            handleQualityOfServiceForVolumeMigration(volumeInfo, PrimaryDataStoreDriver.QualityOfServiceState.NO_MIGRATION);
        }
        if (copyCmdAnswer == null) {
            copyCmdAnswer = new CopyCmdAnswer(errMsg);
        }
        CopyCommandResult result = new CopyCommandResult(null, copyCmdAnswer);
        result.setResult(errMsg);
        callback.complete(result);
    }
}
Also used : VolumeDetailVO(com.cloud.storage.VolumeDetailVO) VolumeApiResult(org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult) HostVO(com.cloud.host.HostVO) AgentUnavailableException(com.cloud.exception.AgentUnavailableException) OperationTimedoutException(com.cloud.exception.OperationTimedoutException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) SnapshotVO(com.cloud.storage.SnapshotVO) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) DiskOfferingVO(com.cloud.storage.DiskOfferingVO) VolumeObjectTO(org.apache.cloudstack.storage.to.VolumeObjectTO) CopyCommandResult(org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult) CopyCmdAnswer(org.apache.cloudstack.storage.command.CopyCmdAnswer)

Aggregations

CopyCommandResult (org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult)68 CloudRuntimeException (com.cloud.utils.exception.CloudRuntimeException)48 ExecutionException (java.util.concurrent.ExecutionException)27 CopyCmdAnswer (org.apache.cloudstack.storage.command.CopyCmdAnswer)21 VolumeInfo (org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo)20 ResourceAllocationException (com.cloud.exception.ResourceAllocationException)19 AgentUnavailableException (com.cloud.exception.AgentUnavailableException)17 OperationTimedoutException (com.cloud.exception.OperationTimedoutException)17 StorageAccessException (com.cloud.exception.StorageAccessException)17 DataStore (org.apache.cloudstack.engine.subsystem.api.storage.DataStore)16 DataObject (org.apache.cloudstack.engine.subsystem.api.storage.DataObject)14 AsyncCallFuture (org.apache.cloudstack.framework.async.AsyncCallFuture)14 HostVO (com.cloud.host.HostVO)12 Answer (com.cloud.agent.api.Answer)11 VMTemplateStoragePoolVO (com.cloud.storage.VMTemplateStoragePoolVO)11 HashMap (java.util.HashMap)10 EndPoint (org.apache.cloudstack.engine.subsystem.api.storage.EndPoint)9 MigrateWithStorageAnswer (com.cloud.agent.api.MigrateWithStorageAnswer)8 VMInstanceVO (com.cloud.vm.VMInstanceVO)8 StoragePoolVO (org.apache.cloudstack.storage.datastore.db.StoragePoolVO)8