Search in sources :

Example 31 with VolumeInfo

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

the class UserVmManagerImpl method restoreVMInternal.

public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId) throws InsufficientCapacityException, ResourceUnavailableException {
    Long userId = caller.getId();
    Account owner = _accountDao.findById(vm.getAccountId());
    _userDao.findById(userId);
    long vmId = vm.getId();
    boolean needRestart = false;
    // Input validation
    if (owner == null) {
        throw new InvalidParameterValueException("The owner of " + vm + " does not exist: " + vm.getAccountId());
    }
    if (owner.getState() == Account.State.disabled) {
        throw new PermissionDeniedException("The owner of " + vm + " is disabled: " + vm.getAccountId());
    }
    if (vm.getState() != VirtualMachine.State.Running && vm.getState() != VirtualMachine.State.Stopped) {
        throw new CloudRuntimeException("Vm " + vm.getUuid() + " currently in " + vm.getState() + " state, restore vm can only execute when VM in Running or Stopped");
    }
    if (vm.getState() == VirtualMachine.State.Running) {
        needRestart = true;
    }
    List<VolumeVO> rootVols = _volsDao.findByInstanceAndType(vmId, Volume.Type.ROOT);
    if (rootVols.isEmpty()) {
        InvalidParameterValueException ex = new InvalidParameterValueException("Can not find root volume for VM " + vm.getUuid());
        ex.addProxyObject(vm.getUuid(), "vmId");
        throw ex;
    }
    if (rootVols.size() > 1) {
        InvalidParameterValueException ex = new InvalidParameterValueException("There are " + rootVols.size() + " root volumes for VM " + vm.getUuid());
        ex.addProxyObject(vm.getUuid(), "vmId");
        throw ex;
    }
    VolumeVO root = rootVols.get(0);
    if (!Volume.State.Allocated.equals(root.getState()) || newTemplateId != null) {
        Long templateId = root.getTemplateId();
        boolean isISO = false;
        if (templateId == null) {
            // Assuming that for a vm deployed using ISO, template ID is set to NULL
            isISO = true;
            templateId = vm.getIsoId();
        }
        // If target VM has associated VM snapshots then don't allow restore of VM
        List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
        if (vmSnapshots.size() > 0) {
            throw new InvalidParameterValueException("Unable to restore VM, please remove VM snapshots before restoring VM");
        }
        VMTemplateVO template = null;
        //newTemplateId can be either template or ISO id. In the following snippet based on the vm deployment (from template or ISO) it is handled accordingly
        if (newTemplateId != null) {
            template = _templateDao.findById(newTemplateId);
            _accountMgr.checkAccess(caller, null, true, template);
            if (isISO) {
                if (!template.getFormat().equals(ImageFormat.ISO)) {
                    throw new InvalidParameterValueException("Invalid ISO id provided to restore the VM ");
                }
            } else {
                if (template.getFormat().equals(ImageFormat.ISO)) {
                    throw new InvalidParameterValueException("Invalid template id provided to restore the VM ");
                }
            }
        } else {
            if (isISO && templateId == null) {
                throw new CloudRuntimeException("Cannot restore the VM since there is no ISO attached to VM");
            }
            template = _templateDao.findById(templateId);
            if (template == null) {
                InvalidParameterValueException ex = new InvalidParameterValueException("Cannot find template/ISO for specified volumeid and vmId");
                ex.addProxyObject(vm.getUuid(), "vmId");
                ex.addProxyObject(root.getUuid(), "volumeId");
                throw ex;
            }
        }
        TemplateDataStoreVO tmplStore = _templateStoreDao.findByTemplateZoneReady(template.getId(), vm.getDataCenterId());
        if (tmplStore == null) {
            throw new InvalidParameterValueException("Cannot restore the vm as the template " + template.getUuid() + " isn't available in the zone");
        }
        if (needRestart) {
            try {
                _itMgr.stop(vm.getUuid());
            } catch (ResourceUnavailableException e) {
                s_logger.debug("Stop vm " + vm.getUuid() + " failed", e);
                CloudRuntimeException ex = new CloudRuntimeException("Stop vm failed for specified vmId");
                ex.addProxyObject(vm.getUuid(), "vmId");
                throw ex;
            }
        }
        /* If new template/ISO is provided allocate a new volume from new template/ISO otherwise allocate new volume from original template/ISO */
        Volume newVol = null;
        if (newTemplateId != null) {
            if (isISO) {
                newVol = volumeMgr.allocateDuplicateVolume(root, null);
                vm.setIsoId(newTemplateId);
                vm.setGuestOSId(template.getGuestOSId());
                vm.setTemplateId(newTemplateId);
                _vmDao.update(vmId, vm);
            } else {
                newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId);
                vm.setGuestOSId(template.getGuestOSId());
                vm.setTemplateId(newTemplateId);
                _vmDao.update(vmId, vm);
            }
        } else {
            newVol = volumeMgr.allocateDuplicateVolume(root, null);
        }
        // 1. Save usage event and update resource count for user vm volumes
        _resourceLimitMgr.incrementResourceCount(newVol.getAccountId(), ResourceType.volume, newVol.isDisplay());
        _resourceLimitMgr.incrementResourceCount(newVol.getAccountId(), ResourceType.primary_storage, newVol.isDisplay(), new Long(newVol.getSize()));
        // 2. Create Usage event for the newly created volume
        UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, newVol.getAccountId(), newVol.getDataCenterId(), newVol.getId(), newVol.getName(), newVol.getDiskOfferingId(), template.getId(), newVol.getSize());
        _usageEventDao.persist(usageEvent);
        handleManagedStorage(vm, root);
        _volsDao.attachVolume(newVol.getId(), vmId, newVol.getDeviceId());
        // Detach, destroy and create the usage event for the old root volume.
        _volsDao.detachVolume(root.getId());
        volumeMgr.destroyVolume(root);
        // For VMware hypervisor since the old root volume is replaced by the new root volume, force expunge old root volume if it has been created in storage
        if (vm.getHypervisorType() == HypervisorType.VMware) {
            VolumeInfo volumeInStorage = volFactory.getVolume(root.getId());
            if (volumeInStorage != null) {
                s_logger.info("Expunging volume " + root.getId() + " from primary data store");
                AsyncCallFuture<VolumeApiResult> future = _volService.expungeVolumeAsync(volFactory.getVolume(root.getId()));
                try {
                    future.get();
                } catch (Exception e) {
                    s_logger.debug("Failed to expunge volume:" + root.getId(), e);
                }
            }
        }
        Map<VirtualMachineProfile.Param, Object> params = null;
        String password = null;
        if (template.getEnablePassword()) {
            password = _mgr.generateRandomPassword();
            boolean result = resetVMPasswordInternal(vmId, password);
            if (result) {
                vm.setPassword(password);
                _vmDao.loadDetails(vm);
                // update the password in vm_details table too
                // Check if an SSH key pair was selected for the instance and if so
                // use it to encrypt & save the vm password
                encryptAndStorePassword(vm, password);
            } else {
                throw new CloudRuntimeException("VM reset is completed but failed to reset password for the virtual machine ");
            }
        }
        if (needRestart) {
            try {
                if (vm.getDetail("password") != null) {
                    params = new HashMap<VirtualMachineProfile.Param, Object>();
                    params.put(VirtualMachineProfile.Param.VmPassword, password);
                }
                _itMgr.start(vm.getUuid(), params);
                vm = _vmDao.findById(vmId);
                if (template.getEnablePassword()) {
                    // this value is not being sent to the backend; need only for api
                    // display purposes
                    vm.setPassword(password);
                    if (vm.isUpdateParameters()) {
                        vm.setUpdateParameters(false);
                        _vmDao.loadDetails(vm);
                        if (vm.getDetail("password") != null) {
                            _vmDetailsDao.remove(_vmDetailsDao.findDetail(vm.getId(), "password").getId());
                        }
                        _vmDao.update(vm.getId(), vm);
                    }
                }
            } catch (Exception e) {
                s_logger.debug("Unable to start VM " + vm.getUuid(), e);
                CloudRuntimeException ex = new CloudRuntimeException("Unable to start VM with specified id" + e.getMessage());
                ex.addProxyObject(vm.getUuid(), "vmId");
                throw ex;
            }
        }
    }
    s_logger.debug("Restore VM " + vmId + " done successfully");
    return vm;
}
Also used : Account(com.cloud.user.Account) VMTemplateVO(com.cloud.storage.VMTemplateVO) UsageEventVO(com.cloud.event.UsageEventVO) VolumeInfo(org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo) VolumeApiResult(org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult) VolumeVO(com.cloud.storage.VolumeVO) InvalidParameterValueException(com.cloud.exception.InvalidParameterValueException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) TemplateDataStoreVO(org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO) ExecutionException(com.cloud.utils.exception.ExecutionException) AgentUnavailableException(com.cloud.exception.AgentUnavailableException) TransactionCallbackWithException(com.cloud.utils.db.TransactionCallbackWithException) ResourceUnavailableException(com.cloud.exception.ResourceUnavailableException) VirtualMachineMigrationException(com.cloud.exception.VirtualMachineMigrationException) PermissionDeniedException(com.cloud.exception.PermissionDeniedException) NoTransitionException(com.cloud.utils.fsm.NoTransitionException) CloudException(com.cloud.exception.CloudException) OperationTimedoutException(com.cloud.exception.OperationTimedoutException) InsufficientCapacityException(com.cloud.exception.InsufficientCapacityException) InsufficientAddressCapacityException(com.cloud.exception.InsufficientAddressCapacityException) StorageUnavailableException(com.cloud.exception.StorageUnavailableException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) InvalidParameterValueException(com.cloud.exception.InvalidParameterValueException) ResourceAllocationException(com.cloud.exception.ResourceAllocationException) ConcurrentOperationException(com.cloud.exception.ConcurrentOperationException) ConfigurationException(javax.naming.ConfigurationException) ManagementServerException(com.cloud.exception.ManagementServerException) VMSnapshotVO(com.cloud.vm.snapshot.VMSnapshotVO) Volume(com.cloud.storage.Volume) ResourceUnavailableException(com.cloud.exception.ResourceUnavailableException) PermissionDeniedException(com.cloud.exception.PermissionDeniedException)

Example 32 with VolumeInfo

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

the class VolumeOrchestrator method revokeAccess.

@Override
public void revokeAccess(long vmId, long hostId) {
    HostVO host = _hostDao.findById(hostId);
    List<VolumeVO> volumesForVm = _volsDao.findByInstance(vmId);
    if (volumesForVm != null) {
        for (VolumeVO volumeForVm : volumesForVm) {
            VolumeInfo volumeInfo = volFactory.getVolume(volumeForVm.getId());
            // pool id can be null for the VM's volumes in Allocated state
            if (volumeForVm.getPoolId() != null) {
                DataStore dataStore = dataStoreMgr.getDataStore(volumeForVm.getPoolId(), DataStoreRole.Primary);
                volService.revokeAccess(volumeInfo, host, dataStore);
            }
        }
    }
}
Also used : VolumeVO(com.cloud.storage.VolumeVO) PrimaryDataStore(org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore) DataStore(org.apache.cloudstack.engine.subsystem.api.storage.DataStore) VolumeInfo(org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo) HostVO(com.cloud.host.HostVO)

Example 33 with VolumeInfo

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

the class VolumeOrchestrator method prepareForMigration.

@Override
public void prepareForMigration(VirtualMachineProfile vm, DeployDestination dest) {
    List<VolumeVO> vols = _volsDao.findUsableVolumesForInstance(vm.getId());
    if (s_logger.isDebugEnabled()) {
        s_logger.debug("Preparing " + vols.size() + " volumes for " + vm);
    }
    for (VolumeVO vol : vols) {
        VolumeInfo volumeInfo = volFactory.getVolume(vol.getId());
        DataTO volTO = volumeInfo.getTO();
        DiskTO disk = storageMgr.getDiskWithThrottling(volTO, vol.getVolumeType(), vol.getDeviceId(), vol.getPath(), vm.getServiceOfferingId(), vol.getDiskOfferingId());
        DataStore dataStore = dataStoreMgr.getDataStore(vol.getPoolId(), DataStoreRole.Primary);
        disk.setDetails(getDetails(volumeInfo, dataStore));
        vm.addDisk(disk);
    }
    //if (vm.getType() == VirtualMachine.Type.User && vm.getTemplate().getFormat() == ImageFormat.ISO) {
    if (vm.getType() == VirtualMachine.Type.User) {
        _tmpltMgr.prepareIsoForVmProfile(vm);
    //DataTO dataTO = tmplFactory.getTemplate(vm.getTemplate().getId(), DataStoreRole.Image, vm.getVirtualMachine().getDataCenterId()).getTO();
    //DiskTO iso = new DiskTO(dataTO, 3L, null, Volume.Type.ISO);
    //vm.addDisk(iso);
    }
}
Also used : DataTO(com.cloud.agent.api.to.DataTO) VolumeVO(com.cloud.storage.VolumeVO) PrimaryDataStore(org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore) DataStore(org.apache.cloudstack.engine.subsystem.api.storage.DataStore) VolumeInfo(org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo) DiskTO(com.cloud.agent.api.to.DiskTO)

Example 34 with VolumeInfo

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

the class VolumeOrchestrator method recreateVolume.

private Pair<VolumeVO, DataStore> recreateVolume(VolumeVO vol, VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException {
    VolumeVO newVol;
    boolean recreate = RecreatableSystemVmEnabled.value();
    DataStore destPool = null;
    if (recreate && (dest.getStorageForDisks() == null || dest.getStorageForDisks().get(vol) == null)) {
        destPool = dataStoreMgr.getDataStore(vol.getPoolId(), DataStoreRole.Primary);
        s_logger.debug("existing pool: " + destPool.getId());
    } else {
        StoragePool pool = dest.getStorageForDisks().get(vol);
        destPool = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
    }
    if (vol.getState() == Volume.State.Allocated || vol.getState() == Volume.State.Creating) {
        newVol = vol;
    } else {
        newVol = switchVolume(vol, vm);
        // changed
        if (dest.getStorageForDisks() != null && dest.getStorageForDisks().containsKey(vol)) {
            StoragePool poolWithOldVol = dest.getStorageForDisks().get(vol);
            dest.getStorageForDisks().put(newVol, poolWithOldVol);
            dest.getStorageForDisks().remove(vol);
        }
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Created new volume " + newVol + " for old volume " + vol);
        }
    }
    VolumeInfo volume = volFactory.getVolume(newVol.getId(), destPool);
    Long templateId = newVol.getTemplateId();
    for (int i = 0; i < 2; i++) {
        // retry one more time in case of template reload is required for Vmware case
        AsyncCallFuture<VolumeApiResult> future = null;
        if (templateId == null) {
            DiskOffering diskOffering = _entityMgr.findById(DiskOffering.class, volume.getDiskOfferingId());
            HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType();
            // update the volume's hv_ss_reserve (hypervisor snapshot reserve) from a disk offering (used for managed storage)
            volService.updateHypervisorSnapshotReserveForVolume(diskOffering, volume.getId(), hyperType);
            volume = volFactory.getVolume(newVol.getId(), destPool);
            future = volService.createVolumeAsync(volume, destPool);
        } else {
            TemplateInfo templ = tmplFactory.getReadyTemplateOnImageStore(templateId, dest.getDataCenter().getId());
            if (templ == null) {
                s_logger.debug("can't find ready template: " + templateId + " for data center " + dest.getDataCenter().getId());
                throw new CloudRuntimeException("can't find ready template: " + templateId + " for data center " + dest.getDataCenter().getId());
            }
            PrimaryDataStore primaryDataStore = (PrimaryDataStore) destPool;
            if (primaryDataStore.isManaged()) {
                DiskOffering diskOffering = _entityMgr.findById(DiskOffering.class, volume.getDiskOfferingId());
                HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType();
                // update the volume's hv_ss_reserve (hypervisor snapshot reserve) from a disk offering (used for managed storage)
                volService.updateHypervisorSnapshotReserveForVolume(diskOffering, volume.getId(), hyperType);
                long hostId = vm.getVirtualMachine().getHostId();
                future = volService.createManagedStorageVolumeFromTemplateAsync(volume, destPool.getId(), templ, hostId);
            } else {
                future = volService.createVolumeFromTemplateAsync(volume, destPool.getId(), templ);
            }
        }
        VolumeApiResult result;
        try {
            result = future.get();
            if (result.isFailed()) {
                if (result.getResult().contains("request template reload") && (i == 0)) {
                    s_logger.debug("Retry template re-deploy for vmware");
                    continue;
                } else {
                    s_logger.debug("Unable to create " + newVol + ":" + result.getResult());
                    throw new StorageUnavailableException("Unable to create " + newVol + ":" + result.getResult(), destPool.getId());
                }
            }
            StoragePoolVO storagePool = _storagePoolDao.findById(destPool.getId());
            if (storagePool.isManaged()) {
                long hostId = vm.getVirtualMachine().getHostId();
                Host host = _hostDao.findById(hostId);
                volService.grantAccess(volFactory.getVolume(newVol.getId()), host, destPool);
            }
            newVol = _volsDao.findById(newVol.getId());
            //break out of template-redeploy retry loop
            break;
        } catch (InterruptedException | ExecutionException e) {
            s_logger.error("Unable to create " + newVol, e);
            throw new StorageUnavailableException("Unable to create " + newVol + ":" + e.toString(), destPool.getId());
        }
    }
    return new Pair<VolumeVO, DataStore>(newVol, destPool);
}
Also used : StoragePool(com.cloud.storage.StoragePool) DiskOffering(com.cloud.offering.DiskOffering) VolumeInfo(org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo) Host(com.cloud.host.Host) VolumeApiResult(org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult) HypervisorType(com.cloud.hypervisor.Hypervisor.HypervisorType) TemplateInfo(org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo) 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) PrimaryDataStore(org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore) Pair(com.cloud.utils.Pair)

Example 35 with VolumeInfo

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

the class VolumeOrchestrator method migrateVolume.

@Override
@DB
public Volume migrateVolume(Volume volume, StoragePool destPool) throws StorageUnavailableException {
    VolumeInfo vol = volFactory.getVolume(volume.getId());
    AsyncCallFuture<VolumeApiResult> future = volService.copyVolume(vol, (DataStore) destPool);
    try {
        VolumeApiResult result = future.get();
        if (result.isFailed()) {
            s_logger.error("Migrate volume failed:" + result.getResult());
            throw new StorageUnavailableException("Migrate volume failed: " + result.getResult(), destPool.getId());
        } else {
            // update the volumeId for snapshots on secondary
            if (!_snapshotDao.listByVolumeId(vol.getId()).isEmpty()) {
                _snapshotDao.updateVolumeIds(vol.getId(), result.getVolume().getId());
                _snapshotDataStoreDao.updateVolumeIds(vol.getId(), result.getVolume().getId());
            }
        }
        return result.getVolume();
    } catch (InterruptedException e) {
        s_logger.debug("migrate volume failed", e);
        throw new CloudRuntimeException(e.getMessage());
    } catch (ExecutionException e) {
        s_logger.debug("migrate volume failed", e);
        throw new CloudRuntimeException(e.getMessage());
    }
}
Also used : StorageUnavailableException(com.cloud.exception.StorageUnavailableException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) 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)

Aggregations

VolumeInfo (org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo)112 CloudRuntimeException (com.cloud.utils.exception.CloudRuntimeException)51 DataStore (org.apache.cloudstack.engine.subsystem.api.storage.DataStore)50 VolumeVO (com.cloud.storage.VolumeVO)36 ConcurrentOperationException (com.cloud.exception.ConcurrentOperationException)23 ResourceAllocationException (com.cloud.exception.ResourceAllocationException)22 ExecutionException (java.util.concurrent.ExecutionException)22 VolumeApiResult (org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult)22 InvalidParameterValueException (com.cloud.exception.InvalidParameterValueException)19 StoragePoolVO (org.apache.cloudstack.storage.datastore.db.StoragePoolVO)19 CopyCommandResult (org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult)18 SnapshotInfo (org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo)17 ArrayList (java.util.ArrayList)15 HashMap (java.util.HashMap)15 StorageUnavailableException (com.cloud.exception.StorageUnavailableException)13 Map (java.util.Map)13 SnapshotVO (com.cloud.storage.SnapshotVO)12 DB (com.cloud.utils.db.DB)12 Test (org.testng.annotations.Test)12 Account (com.cloud.user.Account)11