Search in sources :

Example 21 with VolumeApiResult

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

the class SnapshotTest method createVolumeFromSnapshot.

@Test
public void createVolumeFromSnapshot() throws InterruptedException, ExecutionException {
    VolumeInfo vol = createCopyBaseImage();
    SnapshotVO snapshotVO = createSnapshotInDb(vol);
    SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
    boolean result = false;
    SnapshotStrategy snapshotStrategy = storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.TAKE);
    if (snapshotStrategy != null) {
        snapshot = snapshotStrategy.takeSnapshot(snapshot);
        result = true;
    }
    AssertJUnit.assertTrue(result);
    VolumeVO volVO = createVolume(vol.getTemplateId(), vol.getPoolId());
    VolumeInfo newVol = this.volFactory.getVolume(volVO.getId());
    AsyncCallFuture<VolumeApiResult> volFuture = this.volumeService.createVolumeFromSnapshot(newVol, newVol.getDataStore(), snapshot);
    VolumeApiResult apiResult = volFuture.get();
    Assert.assertTrue(apiResult.isSuccess());
}
Also used : SnapshotInfo(org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo) SnapshotVO(com.cloud.storage.SnapshotVO) VolumeVO(com.cloud.storage.VolumeVO) VolumeInfo(org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo) VolumeApiResult(org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult) SnapshotStrategy(org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy) Test(org.testng.annotations.Test)

Example 22 with VolumeApiResult

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

the class VolumeOrchestrator method createVolumeFromSnapshot.

@DB
@Override
public VolumeInfo createVolumeFromSnapshot(Volume volume, Snapshot snapshot, UserVm vm) throws StorageUnavailableException {
    Account account = _entityMgr.findById(Account.class, volume.getAccountId());
    final HashSet<StoragePool> poolsToAvoid = new HashSet<StoragePool>();
    StoragePool pool = null;
    Set<Long> podsToAvoid = new HashSet<Long>();
    Pair<Pod, Long> pod = null;
    DiskOffering diskOffering = _entityMgr.findById(DiskOffering.class, volume.getDiskOfferingId());
    DataCenter dc = _entityMgr.findById(DataCenter.class, volume.getDataCenterId());
    DiskProfile dskCh = new DiskProfile(volume, diskOffering, snapshot.getHypervisorType());
    String msg = "There are no available storage pools to store the volume in";
    if (vm != null) {
        Pod podofVM = _entityMgr.findById(Pod.class, vm.getPodIdToDeployIn());
        if (podofVM != null) {
            pod = new Pair<Pod, Long>(podofVM, podofVM.getId());
        }
    }
    if (vm != null && pod != null) {
        //if VM is running use the hostId to find the clusterID. If it is stopped, refer the cluster where the ROOT volume of the VM exists.
        Long hostId = null;
        Long clusterId = null;
        if (vm.getState() == State.Running) {
            hostId = vm.getHostId();
            if (hostId != null) {
                Host vmHost = _entityMgr.findById(Host.class, hostId);
                clusterId = vmHost.getClusterId();
            }
        } else {
            List<VolumeVO> rootVolumesOfVm = _volsDao.findByInstanceAndType(vm.getId(), Volume.Type.ROOT);
            if (rootVolumesOfVm.size() != 1) {
                throw new CloudRuntimeException("The VM " + vm.getHostName() + " has more than one ROOT volume and is in an invalid state. Please contact Cloud Support.");
            } else {
                VolumeVO rootVolumeOfVm = rootVolumesOfVm.get(0);
                StoragePoolVO rootDiskPool = _storagePoolDao.findById(rootVolumeOfVm.getPoolId());
                clusterId = (rootDiskPool == null ? null : rootDiskPool.getClusterId());
            }
        }
        // Determine what storage pool to store the volume in
        while ((pool = findStoragePool(dskCh, dc, pod.first(), clusterId, hostId, vm, poolsToAvoid)) != null) {
            break;
        }
        if (pool == null) {
            //pool could not be found in the VM's pod/cluster.
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Could not find any storage pool to create Volume in the pod/cluster of the provided VM " + vm.getUuid());
            }
            StringBuilder addDetails = new StringBuilder(msg);
            addDetails.append(", Could not find any storage pool to create Volume in the pod/cluster of the VM ");
            addDetails.append(vm.getUuid());
            msg = addDetails.toString();
        }
    } else {
        // Determine what pod to store the volume in
        while ((pod = findPod(null, null, dc, account.getId(), podsToAvoid)) != null) {
            podsToAvoid.add(pod.first().getId());
            // Determine what storage pool to store the volume in
            while ((pool = findStoragePool(dskCh, dc, pod.first(), null, null, null, poolsToAvoid)) != null) {
                break;
            }
            if (pool != null) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Found a suitable pool for create volume: " + pool.getId());
                }
                break;
            }
        }
    }
    if (pool == null) {
        s_logger.info(msg);
        throw new StorageUnavailableException(msg, -1);
    }
    VolumeInfo vol = volFactory.getVolume(volume.getId());
    DataStore store = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
    DataStoreRole dataStoreRole = getDataStoreRole(snapshot);
    SnapshotInfo snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), dataStoreRole);
    if (snapInfo == null && dataStoreRole == DataStoreRole.Image) {
        // snapshot is not backed up to secondary, let's do that now.
        snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), DataStoreRole.Primary);
        if (snapInfo == null) {
            throw new CloudRuntimeException("Cannot find snapshot " + snapshot.getId());
        }
        // We need to copy the snapshot onto secondary.
        SnapshotStrategy snapshotStrategy = _storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.BACKUP);
        snapshotStrategy.backupSnapshot(snapInfo);
        // Attempt to grab it again.
        snapInfo = snapshotFactory.getSnapshot(snapshot.getId(), dataStoreRole);
        if (snapInfo == null) {
            throw new CloudRuntimeException("Cannot find snapshot " + snapshot.getId() + " on secondary and could not create backup");
        }
    }
    // don't try to perform a sync if the DataStoreRole of the snapshot is equal to DataStoreRole.Primary
    if (!DataStoreRole.Primary.equals(dataStoreRole)) {
        try {
            // sync snapshot to region store if necessary
            DataStore snapStore = snapInfo.getDataStore();
            long snapVolId = snapInfo.getVolumeId();
            _snapshotSrv.syncVolumeSnapshotsToRegionStore(snapVolId, snapStore);
        } catch (Exception ex) {
            // log but ignore the sync error to avoid any potential S3 down issue, it should be sync next time
            s_logger.warn(ex.getMessage(), ex);
        }
    }
    // create volume on primary from snapshot
    AsyncCallFuture<VolumeApiResult> future = volService.createVolumeFromSnapshot(vol, store, snapInfo);
    try {
        VolumeApiResult result = future.get();
        if (result.isFailed()) {
            s_logger.debug("Failed to create volume from snapshot:" + result.getResult());
            throw new CloudRuntimeException("Failed to create volume from snapshot:" + result.getResult());
        }
        return result.getVolume();
    } catch (InterruptedException e) {
        s_logger.debug("Failed to create volume from snapshot", e);
        throw new CloudRuntimeException("Failed to create volume from snapshot", e);
    } catch (ExecutionException e) {
        s_logger.debug("Failed to create volume from snapshot", e);
        throw new CloudRuntimeException("Failed to create volume from snapshot", e);
    }
}
Also used : Account(com.cloud.user.Account) StoragePool(com.cloud.storage.StoragePool) DiskOffering(com.cloud.offering.DiskOffering) VolumeInfo(org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo) VolumeApiResult(org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult) DataStoreRole(com.cloud.storage.DataStoreRole) VolumeVO(com.cloud.storage.VolumeVO) StorageUnavailableException(com.cloud.exception.StorageUnavailableException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) PrimaryDataStore(org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore) DataStore(org.apache.cloudstack.engine.subsystem.api.storage.DataStore) StoragePoolVO(org.apache.cloudstack.storage.datastore.db.StoragePoolVO) ExecutionException(java.util.concurrent.ExecutionException) SnapshotStrategy(org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy) HashSet(java.util.HashSet) Pod(com.cloud.dc.Pod) Host(com.cloud.host.Host) DiskProfile(com.cloud.vm.DiskProfile) NoTransitionException(com.cloud.utils.fsm.NoTransitionException) InsufficientStorageCapacityException(com.cloud.exception.InsufficientStorageCapacityException) StorageUnavailableException(com.cloud.exception.StorageUnavailableException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) ExecutionException(java.util.concurrent.ExecutionException) InvalidParameterValueException(com.cloud.exception.InvalidParameterValueException) ConcurrentOperationException(com.cloud.exception.ConcurrentOperationException) ConfigurationException(javax.naming.ConfigurationException) SnapshotInfo(org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo) DataCenter(com.cloud.dc.DataCenter) DB(com.cloud.utils.db.DB)

Example 23 with VolumeApiResult

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

the class VolumeOrchestrator method liveMigrateVolume.

@DB
protected Volume liveMigrateVolume(Volume volume, StoragePool destPool) {
    VolumeInfo vol = volFactory.getVolume(volume.getId());
    AsyncCallFuture<VolumeApiResult> future = volService.migrateVolume(vol, (DataStore) destPool);
    try {
        VolumeApiResult result = future.get();
        if (result.isFailed()) {
            s_logger.debug("migrate volume failed:" + result.getResult());
            return null;
        }
        return result.getVolume();
    } catch (InterruptedException e) {
        s_logger.debug("migrate volume failed", e);
        return null;
    } catch (ExecutionException e) {
        s_logger.debug("migrate volume failed", e);
        return null;
    }
}
Also used : VolumeInfo(org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo) VolumeApiResult(org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult) ExecutionException(java.util.concurrent.ExecutionException) DB(com.cloud.utils.db.DB)

Example 24 with VolumeApiResult

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

the class StorageSystemDataMotionStrategy method handleCreateVolumeFromSnapshotBothOnStorageSystem.

private void handleCreateVolumeFromSnapshotBothOnStorageSystem(SnapshotInfo snapshotInfo, VolumeInfo volumeInfo, AsyncCompletionCallback<CopyCommandResult> callback) {
    CopyCmdAnswer copyCmdAnswer = null;
    String errMsg = null;
    try {
        HostVO hostVO = getHost(snapshotInfo);
        boolean usingBackendSnapshot = usingBackendSnapshotFor(snapshotInfo);
        boolean computeClusterSupportsResign = clusterDao.getSupportsResigning(hostVO.getClusterId());
        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);
        }
        boolean canStorageSystemCreateVolumeFromVolume = canStorageSystemCreateVolumeFromVolume(snapshotInfo);
        boolean useCloning = usingBackendSnapshot || (canStorageSystemCreateVolumeFromVolume && computeClusterSupportsResign);
        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 (useCloning) {
            copyCmdAnswer = performResignature(volumeInfo, hostVO);
        } 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(), false);
            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) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) DiskOfferingVO(com.cloud.storage.DiskOfferingVO) VolumeDetailVO(com.cloud.storage.VolumeDetailVO) 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 25 with VolumeApiResult

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

the class StorageSystemDataMotionStrategy method handleCreateVolumeFromTemplateBothOnStorageSystem.

/**
     * Clones a template present on the storage to a new volume and resignatures it.
     *
     * @param templateInfo   source template
     * @param volumeInfo  destination ROOT volume
     * @param callback  for async
     */
private void handleCreateVolumeFromTemplateBothOnStorageSystem(TemplateInfo templateInfo, VolumeInfo volumeInfo, AsyncCompletionCallback<CopyCommandResult> callback) {
    Preconditions.checkArgument(templateInfo != null, "Passing 'null' to templateInfo of handleCreateVolumeFromTemplateBothOnStorageSystem is not supported.");
    Preconditions.checkArgument(volumeInfo != null, "Passing 'null' to volumeInfo of handleCreateVolumeFromTemplateBothOnStorageSystem is not supported.");
    CopyCmdAnswer copyCmdAnswer = null;
    String errMsg = null;
    HostVO hostVO = getHost(volumeInfo.getDataCenterId(), true);
    if (hostVO == null) {
        throw new CloudRuntimeException("Unable to locate a host capable of resigning in the zone with the following ID: " + volumeInfo.getDataCenterId());
    }
    boolean computeClusterSupportsResign = clusterDao.getSupportsResigning(hostVO.getClusterId());
    if (!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 {
        VolumeDetailVO volumeDetail = new VolumeDetailVO(volumeInfo.getId(), "cloneOfTemplate", String.valueOf(templateInfo.getId()), false);
        volumeDetail = volumeDetailsDao.persist(volumeDetail);
        AsyncCallFuture<VolumeApiResult> future = _volumeService.createVolumeAsync(volumeInfo, volumeInfo.getDataStore());
        int storagePoolMaxWaitSeconds = NumbersUtil.parseInt(_configDao.getValue(Config.StoragePoolMaxWaitSeconds.key()), 3600);
        VolumeApiResult result = future.get(storagePoolMaxWaitSeconds, TimeUnit.SECONDS);
        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());
        copyCmdAnswer = performResignature(volumeInfo, hostVO);
        if (copyCmdAnswer == null || !copyCmdAnswer.getResult()) {
            if (copyCmdAnswer != null && !StringUtils.isEmpty(copyCmdAnswer.getDetails())) {
                throw new CloudRuntimeException(copyCmdAnswer.getDetails());
            } else {
                throw new CloudRuntimeException("Unable to create a volume from a template");
            }
        }
    } catch (InterruptedException | ExecutionException | TimeoutException ex) {
        volumeInfo.getDataStore().getDriver().deleteAsync(volumeInfo.getDataStore(), volumeInfo, null);
        throw new CloudRuntimeException("Create volume from template (ID = " + templateInfo.getId() + ") failed " + ex.getMessage());
    }
    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) EndPoint(org.apache.cloudstack.engine.subsystem.api.storage.EndPoint) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) ExecutionException(java.util.concurrent.ExecutionException) CopyCommandResult(org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult) CopyCmdAnswer(org.apache.cloudstack.storage.command.CopyCmdAnswer) TimeoutException(java.util.concurrent.TimeoutException)

Aggregations

VolumeApiResult (org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult)29 ExecutionException (java.util.concurrent.ExecutionException)23 VolumeInfo (org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo)22 DataStore (org.apache.cloudstack.engine.subsystem.api.storage.DataStore)17 VolumeVO (com.cloud.storage.VolumeVO)16 CloudRuntimeException (com.cloud.utils.exception.CloudRuntimeException)14 DB (com.cloud.utils.db.DB)9 Test (org.testng.annotations.Test)8 InvalidParameterValueException (com.cloud.exception.InvalidParameterValueException)7 StorageUnavailableException (com.cloud.exception.StorageUnavailableException)7 ConcurrentOperationException (com.cloud.exception.ConcurrentOperationException)6 StoragePoolVO (org.apache.cloudstack.storage.datastore.db.StoragePoolVO)5 AgentUnavailableException (com.cloud.exception.AgentUnavailableException)4 OperationTimedoutException (com.cloud.exception.OperationTimedoutException)4 HostVO (com.cloud.host.HostVO)4 NoTransitionException (com.cloud.utils.fsm.NoTransitionException)4 TemplateInfo (org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo)4 PermissionDeniedException (com.cloud.exception.PermissionDeniedException)3 Host (com.cloud.host.Host)3 SnapshotVO (com.cloud.storage.SnapshotVO)3