Search in sources :

Example 76 with ConcurrentOperationException

use of com.cloud.legacymodel.exceptions.ConcurrentOperationException in project cosmic by MissionCriticalCloud.

the class AsyncJobExecutionContext method disjoinJob.

// 
// check failure exception before we disjoin the worker job, work job usually fails with exception
// this will help propogate exception between jobs
// TODO : it is ugly and this will become unnecessary after we switch to full-async mode
// 
public void disjoinJob(final long joinedJobId) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
    assert (_job != null);
    final AsyncJobJoinMapVO record = s_joinMapDao.getJoinRecord(_job.getId(), joinedJobId);
    s_jobMgr.disjoinJob(_job.getId(), joinedJobId);
    if (record.getJoinStatus() == JobInfo.Status.FAILED) {
        if (record.getJoinResult() != null) {
            final Object exception = JobSerializerHelper.fromObjectSerializedString(record.getJoinResult());
            if (exception != null && exception instanceof Exception) {
                if (exception instanceof InsufficientCapacityException) {
                    s_logger.error("Job " + joinedJobId + " failed with InsufficientCapacityException");
                    throw (InsufficientCapacityException) exception;
                } else if (exception instanceof ConcurrentOperationException) {
                    s_logger.error("Job " + joinedJobId + " failed with ConcurrentOperationException");
                    throw (ConcurrentOperationException) exception;
                } else if (exception instanceof ResourceUnavailableException) {
                    s_logger.error("Job " + joinedJobId + " failed with ResourceUnavailableException");
                    throw (ResourceUnavailableException) exception;
                } else {
                    s_logger.error("Job " + joinedJobId + " failed with exception");
                    throw new RuntimeException((Exception) exception);
                }
            }
        } else {
            s_logger.error("Job " + joinedJobId + " failed without providing an error object");
            throw new RuntimeException("Job " + joinedJobId + " failed without providing an error object");
        }
    }
}
Also used : AsyncJobJoinMapVO(com.cloud.framework.jobs.impl.AsyncJobJoinMapVO) ResourceUnavailableException(com.cloud.legacymodel.exceptions.ResourceUnavailableException) InsufficientCapacityException(com.cloud.legacymodel.exceptions.InsufficientCapacityException) ConcurrentOperationException(com.cloud.legacymodel.exceptions.ConcurrentOperationException) InsufficientCapacityException(com.cloud.legacymodel.exceptions.InsufficientCapacityException) ResourceUnavailableException(com.cloud.legacymodel.exceptions.ResourceUnavailableException) ConcurrentOperationException(com.cloud.legacymodel.exceptions.ConcurrentOperationException)

Example 77 with ConcurrentOperationException

use of com.cloud.legacymodel.exceptions.ConcurrentOperationException in project cosmic by MissionCriticalCloud.

the class VolumeApiServiceImpl method detachVolumeFromVM.

@Override
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_DETACH, eventDescription = "detaching volume", async = true)
public Volume detachVolumeFromVM(final DetachVolumeCmd cmmd) {
    final Account caller = CallContext.current().getCallingAccount();
    if (cmmd.getId() == null && cmmd.getDeviceId() == null && cmmd.getVirtualMachineId() == null || cmmd.getId() != null && (cmmd.getDeviceId() != null || cmmd.getVirtualMachineId() != null) || cmmd.getId() == null && (cmmd.getDeviceId() == null || cmmd.getVirtualMachineId() == null)) {
        throw new InvalidParameterValueException("Please provide either a volume id, or a tuple(device id, instance id)");
    }
    final Long volumeId = cmmd.getId();
    final VolumeVO volume;
    if (volumeId != null) {
        volume = this._volsDao.findById(volumeId);
    } else {
        volume = this._volsDao.findByInstanceAndDeviceId(cmmd.getVirtualMachineId(), cmmd.getDeviceId()).get(0);
    }
    // Check that the volume ID is valid
    if (volume == null) {
        throw new InvalidParameterValueException("Unable to find volume with ID: " + volumeId);
    }
    final Long vmId;
    if (cmmd.getVirtualMachineId() == null) {
        vmId = volume.getInstanceId();
    } else {
        vmId = cmmd.getVirtualMachineId();
    }
    // Permissions check
    this._accountMgr.checkAccess(caller, null, true, volume);
    // Check that the volume is currently attached to a VM
    if (vmId == null) {
        throw new InvalidParameterValueException("The specified volume is not attached to a VM.");
    }
    // Check that the VM is in the correct state
    final UserVmVO vm = this._userVmDao.findById(vmId);
    if (vm.getState() != State.Running && vm.getState() != State.Stopped && vm.getState() != State.Destroyed) {
        throw new InvalidParameterValueException("Please specify a VM that is either running or stopped.");
    }
    // Check that the volume is a data/root volume
    if (!(volume.getVolumeType() == VolumeType.ROOT || volume.getVolumeType() == VolumeType.DATADISK)) {
        throw new InvalidParameterValueException("Please specify volume of type " + VolumeType.DATADISK.toString() + " or " + VolumeType.ROOT.toString());
    }
    // Root volume detach is allowed for following hypervisors: Xen/KVM/VmWare
    if (volume.getVolumeType() == VolumeType.ROOT) {
        validateRootVolumeDetachAttach(volume, vm);
    }
    // Don't allow detach if target VM has associated VM snapshots
    final List<VMSnapshotVO> vmSnapshots = this._vmSnapshotDao.findByVm(vmId);
    if (vmSnapshots.size() > 0) {
        throw new InvalidParameterValueException("Unable to detach volume, please specify a VM that does not have VM snapshots");
    }
    final AsyncJobExecutionContext asyncExecutionContext = AsyncJobExecutionContext.getCurrentExecutionContext();
    if (asyncExecutionContext != null) {
        final AsyncJob job = asyncExecutionContext.getJob();
        if (s_logger.isInfoEnabled()) {
            s_logger.info("Trying to attaching volume " + volumeId + "to vm instance:" + vm.getId() + ", update async job-" + job.getId() + " progress status");
        }
        this._jobMgr.updateAsyncJobAttachment(job.getId(), "Volume", volumeId);
    }
    final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
    if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
        // avoid re-entrance
        final VmWorkJobVO placeHolder;
        placeHolder = createPlaceHolderWork(vmId);
        try {
            return orchestrateDetachVolumeFromVM(vmId, volumeId);
        } finally {
            this._workJobDao.expunge(placeHolder.getId());
        }
    } else {
        final Outcome<Volume> outcome = detachVolumeFromVmThroughJobQueue(vmId, volumeId);
        Volume vol = null;
        try {
            outcome.get();
        } catch (final InterruptedException e) {
            throw new RuntimeException("Operation is interrupted", e);
        } catch (final java.util.concurrent.ExecutionException e) {
            throw new RuntimeException("Execution excetion", e);
        }
        final Object jobResult = this._jobMgr.unmarshallResultObject(outcome.getJob());
        if (jobResult != null) {
            if (jobResult instanceof ConcurrentOperationException) {
                throw (ConcurrentOperationException) jobResult;
            } else if (jobResult instanceof RuntimeException) {
                throw (RuntimeException) jobResult;
            } else if (jobResult instanceof Throwable) {
                throw new RuntimeException("Unexpected exception", (Throwable) jobResult);
            } else if (jobResult instanceof Long) {
                vol = this._volsDao.findById((Long) jobResult);
            }
        }
        return vol;
    }
}
Also used : Account(com.cloud.legacymodel.user.Account) UserVmVO(com.cloud.vm.UserVmVO) AsyncJobExecutionContext(com.cloud.framework.jobs.AsyncJobExecutionContext) ConcurrentOperationException(com.cloud.legacymodel.exceptions.ConcurrentOperationException) AsyncJob(com.cloud.framework.jobs.AsyncJob) VmWorkJobVO(com.cloud.framework.jobs.impl.VmWorkJobVO) ExecutionException(java.util.concurrent.ExecutionException) VMSnapshotVO(com.cloud.vm.snapshot.VMSnapshotVO) CloudRuntimeException(com.cloud.legacymodel.exceptions.CloudRuntimeException) InvalidParameterValueException(com.cloud.legacymodel.exceptions.InvalidParameterValueException) Volume(com.cloud.legacymodel.storage.Volume) VmWorkDetachVolume(com.cloud.vm.VmWorkDetachVolume) VmWorkMigrateVolume(com.cloud.vm.VmWorkMigrateVolume) VmWorkResizeVolume(com.cloud.vm.VmWorkResizeVolume) VmWorkAttachVolume(com.cloud.vm.VmWorkAttachVolume) VmWorkExtractVolume(com.cloud.vm.VmWorkExtractVolume) DataObject(com.cloud.engine.subsystem.api.storage.DataObject) ActionEvent(com.cloud.event.ActionEvent)

Example 78 with ConcurrentOperationException

use of com.cloud.legacymodel.exceptions.ConcurrentOperationException in project cosmic by MissionCriticalCloud.

the class VolumeApiServiceImpl method migrateVolume.

@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_MIGRATE, eventDescription = "migrating volume", async = true)
public Volume migrateVolume(final MigrateVolumeCmd cmd) {
    final Long volumeId = cmd.getVolumeId();
    final Long storagePoolId = cmd.getStoragePoolId();
    final VolumeVO vol = this._volsDao.findById(volumeId);
    if (vol == null) {
        throw new InvalidParameterValueException("Failed to find the volume id: " + volumeId);
    }
    if (vol.getState() != Volume.State.Ready) {
        throw new InvalidParameterValueException("Volume must be in ready state");
    }
    boolean liveMigrateVolume = false;
    final Long instanceId = vol.getInstanceId();
    Long srcClusterId = null;
    VMInstanceVO vm = null;
    if (instanceId != null) {
        vm = this._vmInstanceDao.findById(instanceId);
    }
    // Check that Vm to which this volume is attached does not have VM Snapshots
    if (vm != null && this._vmSnapshotDao.findByVm(vm.getId()).size() > 0) {
        throw new InvalidParameterValueException("Volume cannot be migrated, please remove all VM snapshots for VM to which this volume is attached");
    }
    if (vm != null && vm.getState() == State.Running) {
        // Check if the VM is GPU enabled.
        if (this._serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
            throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported");
        }
        // Check if the underlying hypervisor supports storage motion.
        final Long hostId = vm.getHostId();
        if (hostId != null) {
            final HostVO host = this._hostDao.findById(hostId);
            HypervisorCapabilitiesVO capabilities = null;
            if (host != null) {
                capabilities = this._hypervisorCapabilitiesDao.findByHypervisorTypeAndVersion(host.getHypervisorType(), host.getHypervisorVersion());
                srcClusterId = host.getClusterId();
            }
            if (capabilities != null) {
                liveMigrateVolume = capabilities.isStorageMotionSupported();
            }
        }
        // If vm is running, and hypervisor doesn't support live migration, then return error
        if (!liveMigrateVolume) {
            throw new InvalidParameterValueException("Volume needs to be detached from VM");
        }
    }
    if (liveMigrateVolume && !cmd.isLiveMigrate()) {
        throw new InvalidParameterValueException("The volume " + vol + "is attached to a vm and for migrating it " + "the parameter livemigrate should be specified");
    }
    final StoragePool destPool = (StoragePool) this.dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary);
    if (destPool == null) {
        throw new InvalidParameterValueException("Failed to find the destination storage pool: " + storagePoolId);
    } else if (destPool.isInMaintenance()) {
        throw new InvalidParameterValueException("Cannot migrate volume " + vol + "to the destination storage pool " + destPool.getName() + " as the storage pool is in maintenance mode.");
    }
    if (vol.getPoolId() == destPool.getId()) {
        throw new InvalidParameterValueException("Cannot migrate to the same storage pool the volume is already residing on.");
    }
    if (this._volumeMgr.volumeOnSharedStoragePool(vol)) {
        if (destPool.isLocal()) {
            throw new InvalidParameterValueException("Migration of volume from shared to local storage pool is not supported");
        } else {
            // to make sure that the destination storage pool is in the same cluster as the vm.
            if (liveMigrateVolume && destPool.getClusterId() != null && srcClusterId != null) {
                if (!srcClusterId.equals(destPool.getClusterId())) {
                    throw new InvalidParameterValueException("Cannot live migrate a volume of a virtual machine to a storage pool in a different cluster." + "You can live migrate the virtual machine itself, rather than the volume.");
                }
            }
        }
    } else {
        throw new InvalidParameterValueException("Migration of volume from local storage pool is not supported");
    }
    if (vm != null) {
        // serialize VM operation
        final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
        if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
            // avoid re-entrance
            final VmWorkJobVO placeHolder;
            placeHolder = createPlaceHolderWork(vm.getId());
            try {
                return orchestrateMigrateVolume(vol.getId(), destPool.getId(), liveMigrateVolume);
            } finally {
                this._workJobDao.expunge(placeHolder.getId());
            }
        } else {
            final Outcome<Volume> outcome = migrateVolumeThroughJobQueue(vm.getId(), vol.getId(), destPool.getId(), liveMigrateVolume);
            try {
                outcome.get();
            } catch (final InterruptedException e) {
                throw new RuntimeException("Operation is interrupted", e);
            } catch (final java.util.concurrent.ExecutionException e) {
                throw new RuntimeException("Execution excetion", e);
            }
            final Object jobResult = this._jobMgr.unmarshallResultObject(outcome.getJob());
            if (jobResult != null) {
                if (jobResult instanceof ConcurrentOperationException) {
                    throw (ConcurrentOperationException) jobResult;
                } else if (jobResult instanceof RuntimeException) {
                    throw (RuntimeException) jobResult;
                } else if (jobResult instanceof Throwable) {
                    throw new RuntimeException("Unexpected exception", (Throwable) jobResult);
                }
            }
            // retrieve the migrated new volume from job result
            if (jobResult != null && jobResult instanceof Long) {
                return this._entityMgr.findById(VolumeVO.class, (Long) jobResult);
            }
            return null;
        }
    }
    return orchestrateMigrateVolume(vol.getId(), destPool.getId(), liveMigrateVolume);
}
Also used : HypervisorCapabilitiesVO(com.cloud.hypervisor.HypervisorCapabilitiesVO) StoragePool(com.cloud.legacymodel.storage.StoragePool) AsyncJobExecutionContext(com.cloud.framework.jobs.AsyncJobExecutionContext) VMInstanceVO(com.cloud.vm.VMInstanceVO) ConcurrentOperationException(com.cloud.legacymodel.exceptions.ConcurrentOperationException) HostVO(com.cloud.host.HostVO) VmWorkJobVO(com.cloud.framework.jobs.impl.VmWorkJobVO) ExecutionException(java.util.concurrent.ExecutionException) CloudRuntimeException(com.cloud.legacymodel.exceptions.CloudRuntimeException) InvalidParameterValueException(com.cloud.legacymodel.exceptions.InvalidParameterValueException) Volume(com.cloud.legacymodel.storage.Volume) VmWorkDetachVolume(com.cloud.vm.VmWorkDetachVolume) VmWorkMigrateVolume(com.cloud.vm.VmWorkMigrateVolume) VmWorkResizeVolume(com.cloud.vm.VmWorkResizeVolume) VmWorkAttachVolume(com.cloud.vm.VmWorkAttachVolume) VmWorkExtractVolume(com.cloud.vm.VmWorkExtractVolume) DataObject(com.cloud.engine.subsystem.api.storage.DataObject) ActionEvent(com.cloud.event.ActionEvent) DB(com.cloud.utils.db.DB)

Example 79 with ConcurrentOperationException

use of com.cloud.legacymodel.exceptions.ConcurrentOperationException in project cosmic by MissionCriticalCloud.

the class VolumeApiServiceImpl method resizeVolume.

@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_RESIZE, eventDescription = "resizing volume", async = true)
public VolumeVO resizeVolume(final ResizeVolumeCmd cmd) throws ResourceAllocationException {
    Long newSize;
    Long newMinIops;
    Long newMaxIops;
    final boolean shrinkOk = cmd.getShrinkOk();
    final VolumeVO volume = this._volsDao.findById(cmd.getEntityId());
    if (volume == null) {
        throw new InvalidParameterValueException("No such volume");
    }
    /* Does the caller have authority to act on this volume? */
    this._accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume);
    if (volume.getInstanceId() != null) {
        // Check that Vm to which this volume is attached does not have VM Snapshots
        if (this._vmSnapshotDao.findByVm(volume.getInstanceId()).size() > 0) {
            throw new InvalidParameterValueException("Volume cannot be resized which is attached to VM with VM Snapshots");
        }
    }
    final DiskOfferingVO diskOffering = this._diskOfferingDao.findById(volume.getDiskOfferingId());
    DiskOfferingVO newDiskOffering = null;
    if (cmd.getNewDiskOfferingId() != null && volume.getDiskOfferingId() != cmd.getNewDiskOfferingId()) {
        newDiskOffering = this._diskOfferingDao.findById(cmd.getNewDiskOfferingId());
    }
    if (newDiskOffering != null && !newDiskOffering.isCustomized()) {
        throw new InvalidParameterValueException("The disk offering for volume " + volume.getName() + " can only be changed to an offering that supports a custom disk size.");
    }
    if (diskOffering.isCustomized() && newDiskOffering != null && !newDiskOffering.isCustomized()) {
        throw new InvalidParameterValueException("Volume " + volume.getName() + " has a custom size disk offering. Cannot change the disk offering." + " Please change the size instead");
    }
    final HypervisorType hypervisorType = this._volsDao.getHypervisorType(volume.getId());
    if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.XenServer && hypervisorType != HypervisorType.Any && hypervisorType != HypervisorType.None) {
        throw new InvalidParameterValueException("CloudStack currently supports volume resize only on KVM, or XenServer.");
    }
    if (volume.getState() != Volume.State.Ready && volume.getState() != Volume.State.Allocated) {
        throw new InvalidParameterValueException("Volume should be in ready or allocated state before attempting a resize. Volume " + volume.getUuid() + " is in state " + volume.getState() + ".");
    }
    // if we are to use the existing disk offering
    if (newDiskOffering == null) {
        newSize = cmd.getSize();
        // if the caller is looking to change the size of the volume
        if (newSize != null) {
            if (!diskOffering.isCustomized() && !volume.getVolumeType().equals(VolumeType.ROOT)) {
                throw new InvalidParameterValueException("To change a volume's size without providing a new disk offering, its current disk offering must be " + "customizable or it must be a root volume (if providing a disk offering, make sure it is different from the current disk offering).");
            }
            // convert from bytes to GiB
            newSize = newSize << 30;
        } else {
            // no parameter provided; just use the original size of the volume
            newSize = volume.getSize();
        }
        newMinIops = cmd.getMinIops();
        if (newMinIops != null) {
            if (diskOffering.isCustomizedIops() == null || !diskOffering.isCustomizedIops()) {
                throw new InvalidParameterValueException("The current disk offering does not support customization of the 'Min IOPS' parameter.");
            }
        } else {
            // no parameter provided; just use the original min IOPS of the volume
            newMinIops = volume.getMinIops();
        }
        newMaxIops = cmd.getMaxIops();
        if (newMaxIops != null) {
            if (diskOffering.isCustomizedIops() == null || !diskOffering.isCustomizedIops()) {
                throw new InvalidParameterValueException("The current disk offering does not support customization of the 'Max IOPS' parameter.");
            }
        } else {
            // no parameter provided; just use the original max IOPS of the volume
            newMaxIops = volume.getMaxIops();
        }
        validateIops(newMinIops, newMaxIops);
    } else {
        if (newDiskOffering.getRemoved() != null) {
            throw new InvalidParameterValueException("Requested disk offering has been removed.");
        }
        if (!DiskOfferingVO.Type.Disk.equals(newDiskOffering.getType())) {
            throw new InvalidParameterValueException("Requested disk offering type is invalid.");
        }
        if (diskOffering.getTags() != null) {
            if (!StringUtils.areTagsEqual(diskOffering.getTags(), newDiskOffering.getTags())) {
                throw new InvalidParameterValueException("The tags on the new and old disk offerings must match.");
            }
        } else if (newDiskOffering.getTags() != null) {
            throw new InvalidParameterValueException("There are no tags on the current disk offering. The new disk offering needs to have no tags, as well.");
        }
        if (!areIntegersEqual(diskOffering.getHypervisorSnapshotReserve(), newDiskOffering.getHypervisorSnapshotReserve())) {
            throw new InvalidParameterValueException("The hypervisor snapshot reverse on the new and old disk offerings must be equal.");
        }
        if (newDiskOffering.getDomainId() != null) {
            // not a public offering; check access
            this._configMgr.checkDiskOfferingAccess(CallContext.current().getCallingAccount(), newDiskOffering);
        }
        if (newDiskOffering.isCustomized()) {
            newSize = cmd.getSize();
            if (newSize == null) {
                throw new InvalidParameterValueException("The new disk offering requires that a size be specified.");
            }
            // convert from bytes to GiB
            newSize = newSize << 30;
        } else {
            newSize = newDiskOffering.getDiskSize();
        }
        if (!volume.getSize().equals(newSize) && !volume.getVolumeType().equals(VolumeType.DATADISK)) {
            throw new InvalidParameterValueException("Only data volumes can be resized via a new disk offering.");
        }
        if (newDiskOffering.isCustomizedIops() != null && newDiskOffering.isCustomizedIops()) {
            newMinIops = cmd.getMinIops() != null ? cmd.getMinIops() : volume.getMinIops();
            newMaxIops = cmd.getMaxIops() != null ? cmd.getMaxIops() : volume.getMaxIops();
            validateIops(newMinIops, newMaxIops);
        } else {
            newMinIops = newDiskOffering.getMinIops();
            newMaxIops = newDiskOffering.getMaxIops();
        }
    }
    final long currentSize = volume.getSize();
    // if the caller is looking to change the size of the volume
    if (currentSize != newSize) {
        if (!validateVolumeSizeRange(newSize)) {
            throw new InvalidParameterValueException("Requested size out of range");
        }
        /*
             * Let's make certain they (think they) know what they're doing if they
             * want to shrink by forcing them to provide the shrinkok parameter.
             * This will be checked again at the hypervisor level where we can see
             * the actual disk size.
             */
        if (currentSize > newSize && !shrinkOk) {
            throw new InvalidParameterValueException("Going from existing size of " + currentSize + " to size of " + newSize + " would shrink the volume." + "Need to sign off by supplying the shrinkok parameter with value of true.");
        }
        if (newSize > currentSize) {
            /* Check resource limit for this account on primary storage resource */
            this._resourceLimitMgr.checkResourceLimit(this._accountMgr.getAccount(volume.getAccountId()), ResourceType.primary_storage, volume.isDisplayVolume(), new Long(newSize - currentSize).longValue());
        }
    }
    /* If this volume has never been beyond allocated state, short circuit everything and simply update the database. */
    if (volume.getState() == Volume.State.Allocated) {
        s_logger.debug("Volume is in the allocated state, but has never been created. Simply updating database with new size and IOPS.");
        volume.setSize(newSize);
        volume.setMinIops(newMinIops);
        volume.setMaxIops(newMaxIops);
        if (newDiskOffering != null) {
            volume.setDiskOfferingId(cmd.getNewDiskOfferingId());
        }
        this._volsDao.update(volume.getId(), volume);
        return volume;
    }
    final UserVmVO userVm = this._userVmDao.findById(volume.getInstanceId());
    if (userVm != null) {
        // serialize VM operation
        final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
        if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
            // avoid re-entrance
            final VmWorkJobVO placeHolder;
            placeHolder = createPlaceHolderWork(userVm.getId());
            try {
                return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
            } finally {
                this._workJobDao.expunge(placeHolder.getId());
            }
        } else {
            final Outcome<Volume> outcome = resizeVolumeThroughJobQueue(userVm.getId(), volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
            try {
                outcome.get();
            } catch (final InterruptedException e) {
                throw new RuntimeException("Operation was interrupted", e);
            } catch (final java.util.concurrent.ExecutionException e) {
                throw new RuntimeException("Execution exception", e);
            }
            final Object jobResult = this._jobMgr.unmarshallResultObject(outcome.getJob());
            if (jobResult != null) {
                if (jobResult instanceof ConcurrentOperationException) {
                    throw (ConcurrentOperationException) jobResult;
                } else if (jobResult instanceof ResourceAllocationException) {
                    throw (ResourceAllocationException) jobResult;
                } else if (jobResult instanceof RuntimeException) {
                    throw (RuntimeException) jobResult;
                } else if (jobResult instanceof Throwable) {
                    throw new RuntimeException("Unexpected exception", (Throwable) jobResult);
                } else if (jobResult instanceof Long) {
                    return this._volsDao.findById((Long) jobResult);
                }
            }
            return volume;
        }
    }
    return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
}
Also used : UserVmVO(com.cloud.vm.UserVmVO) AsyncJobExecutionContext(com.cloud.framework.jobs.AsyncJobExecutionContext) ConcurrentOperationException(com.cloud.legacymodel.exceptions.ConcurrentOperationException) VmWorkJobVO(com.cloud.framework.jobs.impl.VmWorkJobVO) HypervisorType(com.cloud.model.enumeration.HypervisorType) ExecutionException(java.util.concurrent.ExecutionException) CloudRuntimeException(com.cloud.legacymodel.exceptions.CloudRuntimeException) InvalidParameterValueException(com.cloud.legacymodel.exceptions.InvalidParameterValueException) Volume(com.cloud.legacymodel.storage.Volume) VmWorkDetachVolume(com.cloud.vm.VmWorkDetachVolume) VmWorkMigrateVolume(com.cloud.vm.VmWorkMigrateVolume) VmWorkResizeVolume(com.cloud.vm.VmWorkResizeVolume) VmWorkAttachVolume(com.cloud.vm.VmWorkAttachVolume) VmWorkExtractVolume(com.cloud.vm.VmWorkExtractVolume) DataObject(com.cloud.engine.subsystem.api.storage.DataObject) ResourceAllocationException(com.cloud.legacymodel.exceptions.ResourceAllocationException) ActionEvent(com.cloud.event.ActionEvent) DB(com.cloud.utils.db.DB)

Example 80 with ConcurrentOperationException

use of com.cloud.legacymodel.exceptions.ConcurrentOperationException in project cosmic by MissionCriticalCloud.

the class VolumeApiServiceImpl method attachVolumeToVM.

public Volume attachVolumeToVM(final Long vmId, final Long volumeId, final Long deviceId) {
    final Account caller = CallContext.current().getCallingAccount();
    // Check that the volume ID is valid
    final VolumeInfo volumeToAttach = this.volFactory.getVolume(volumeId);
    // Check that the volume is a data volume
    if (volumeToAttach == null || !(volumeToAttach.getVolumeType() == VolumeType.DATADISK || volumeToAttach.getVolumeType() == VolumeType.ROOT)) {
        throw new InvalidParameterValueException("Please specify a volume with the valid type: " + VolumeType.ROOT.toString() + " or " + VolumeType.DATADISK.toString());
    }
    // Check that the volume is not currently attached to any VM
    if (volumeToAttach.getInstanceId() != null) {
        throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
    }
    // Check that the volume is not destroyed
    if (volumeToAttach.getState() == Volume.State.Destroy) {
        throw new InvalidParameterValueException("Please specify a volume that is not destroyed.");
    }
    // Check that the virtual machine ID is valid and it's a user vm
    final UserVmVO vm = this._userVmDao.findById(vmId);
    if (vm == null || vm.getType() != VirtualMachineType.User) {
        throw new InvalidParameterValueException("Please specify a valid User VM.");
    }
    // Check that the VM is in the correct state
    if (vm.getState() != State.Running && vm.getState() != State.Stopped) {
        throw new InvalidParameterValueException("Please specify a VM that is either running or stopped.");
    }
    // Check that the VM and the volume are in the same zone
    if (vm.getDataCenterId() != volumeToAttach.getDataCenterId()) {
        throw new InvalidParameterValueException("Please specify a VM that is in the same zone as the volume.");
    }
    // Check that the device ID is valid
    if (deviceId != null) {
        // validate ROOT volume type
        if (deviceId.longValue() == 0) {
            validateRootVolumeDetachAttach(this._volsDao.findById(volumeToAttach.getId()), vm);
            // vm shouldn't have any volume with deviceId 0
            if (!this._volsDao.findByInstanceAndDeviceId(vm.getId(), 0).isEmpty()) {
                throw new InvalidParameterValueException("Vm already has root volume attached to it");
            }
            // volume can't be in Uploaded state
            if (volumeToAttach.getState() == Volume.State.Uploaded) {
                throw new InvalidParameterValueException("No support for Root volume attach in state " + Volume.State.Uploaded);
            }
        }
    }
    // that supported by hypervisor
    if (deviceId == null || deviceId.longValue() != 0) {
        final List<VolumeVO> existingDataVolumes = this._volsDao.findByInstanceAndType(vmId, VolumeType.DATADISK);
        final int maxDataVolumesSupported = getMaxDataVolumesSupported(vm);
        if (existingDataVolumes.size() >= maxDataVolumesSupported) {
            throw new InvalidParameterValueException("The specified VM already has the maximum number of data disks (" + maxDataVolumesSupported + "). Please specify another" + " VM.");
        }
    }
    // if target VM has associated VM snapshots
    final List<VMSnapshotVO> vmSnapshots = this._vmSnapshotDao.findByVm(vmId);
    if (vmSnapshots.size() > 0) {
        throw new InvalidParameterValueException("Unable to attach volume, please specify a VM that does not have VM snapshots");
    }
    // permission check
    this._accountMgr.checkAccess(caller, null, true, volumeToAttach, vm);
    if (!(Volume.State.Allocated.equals(volumeToAttach.getState()) || Volume.State.Ready.equals(volumeToAttach.getState()) || Volume.State.Uploaded.equals(volumeToAttach.getState()))) {
        throw new InvalidParameterValueException("Volume state must be in Allocated, Ready or in Uploaded state");
    }
    final Account owner = this._accountDao.findById(volumeToAttach.getAccountId());
    if (!(volumeToAttach.getState() == Volume.State.Allocated || volumeToAttach.getState() == Volume.State.Ready)) {
        try {
            this._resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, volumeToAttach.getSize());
        } catch (final ResourceAllocationException e) {
            s_logger.error("primary storage resource limit check failed", e);
            throw new InvalidParameterValueException(e.getMessage());
        }
    }
    final HypervisorType rootDiskHyperType = vm.getHypervisorType();
    final HypervisorType volumeToAttachHyperType = this._volsDao.getHypervisorType(volumeToAttach.getId());
    final StoragePoolVO volumeToAttachStoragePool = this._storagePoolDao.findById(volumeToAttach.getPoolId());
    // only perform this check if the volume's storage pool is not null and not managed
    if (volumeToAttachStoragePool != null && !volumeToAttachStoragePool.isManaged()) {
        if (volumeToAttachHyperType != HypervisorType.None && rootDiskHyperType != volumeToAttachHyperType) {
            throw new InvalidParameterValueException("Can't attach a volume created by: " + volumeToAttachHyperType + " to a " + rootDiskHyperType + " vm");
        }
    }
    final AsyncJobExecutionContext asyncExecutionContext = AsyncJobExecutionContext.getCurrentExecutionContext();
    if (asyncExecutionContext != null) {
        final AsyncJob job = asyncExecutionContext.getJob();
        if (s_logger.isInfoEnabled()) {
            s_logger.info("Trying to attaching volume " + volumeId + " to vm instance:" + vm.getId() + ", update async job-" + job.getId() + " progress status");
        }
        this._jobMgr.updateAsyncJobAttachment(job.getId(), "Volume", volumeId);
    }
    final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
    if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
        // avoid re-entrance
        final VmWorkJobVO placeHolder;
        placeHolder = createPlaceHolderWork(vmId);
        try {
            return orchestrateAttachVolumeToVM(vmId, volumeId, deviceId, volumeToAttach.getDiskController());
        } finally {
            this._workJobDao.expunge(placeHolder.getId());
        }
    } else {
        final Outcome<Volume> outcome = attachVolumeToVmThroughJobQueue(vmId, volumeId, deviceId, volumeToAttach.getDiskController());
        Volume vol = null;
        try {
            outcome.get();
        } catch (final InterruptedException e) {
            throw new RuntimeException("Operation is interrupted", e);
        } catch (final java.util.concurrent.ExecutionException e) {
            throw new RuntimeException("Execution excetion", e);
        }
        final Object jobResult = this._jobMgr.unmarshallResultObject(outcome.getJob());
        if (jobResult != null) {
            if (jobResult instanceof ConcurrentOperationException) {
                throw (ConcurrentOperationException) jobResult;
            } else if (jobResult instanceof InvalidParameterValueException) {
                throw (InvalidParameterValueException) jobResult;
            } else if (jobResult instanceof RuntimeException) {
                throw (RuntimeException) jobResult;
            } else if (jobResult instanceof Throwable) {
                throw new RuntimeException("Unexpected exception", (Throwable) jobResult);
            } else if (jobResult instanceof Long) {
                vol = this._volsDao.findById((Long) jobResult);
            }
        }
        return vol;
    }
}
Also used : Account(com.cloud.legacymodel.user.Account) UserVmVO(com.cloud.vm.UserVmVO) AsyncJobExecutionContext(com.cloud.framework.jobs.AsyncJobExecutionContext) VolumeInfo(com.cloud.engine.subsystem.api.storage.VolumeInfo) AsyncJob(com.cloud.framework.jobs.AsyncJob) CloudRuntimeException(com.cloud.legacymodel.exceptions.CloudRuntimeException) InvalidParameterValueException(com.cloud.legacymodel.exceptions.InvalidParameterValueException) StoragePoolVO(com.cloud.storage.datastore.db.StoragePoolVO) ResourceAllocationException(com.cloud.legacymodel.exceptions.ResourceAllocationException) ConcurrentOperationException(com.cloud.legacymodel.exceptions.ConcurrentOperationException) EndPoint(com.cloud.engine.subsystem.api.storage.EndPoint) VmWorkJobVO(com.cloud.framework.jobs.impl.VmWorkJobVO) HypervisorType(com.cloud.model.enumeration.HypervisorType) ExecutionException(java.util.concurrent.ExecutionException) VMSnapshotVO(com.cloud.vm.snapshot.VMSnapshotVO) Volume(com.cloud.legacymodel.storage.Volume) VmWorkDetachVolume(com.cloud.vm.VmWorkDetachVolume) VmWorkMigrateVolume(com.cloud.vm.VmWorkMigrateVolume) VmWorkResizeVolume(com.cloud.vm.VmWorkResizeVolume) VmWorkAttachVolume(com.cloud.vm.VmWorkAttachVolume) VmWorkExtractVolume(com.cloud.vm.VmWorkExtractVolume) DataObject(com.cloud.engine.subsystem.api.storage.DataObject)

Aggregations

ConcurrentOperationException (com.cloud.legacymodel.exceptions.ConcurrentOperationException)101 ResourceUnavailableException (com.cloud.legacymodel.exceptions.ResourceUnavailableException)63 CloudRuntimeException (com.cloud.legacymodel.exceptions.CloudRuntimeException)58 InsufficientCapacityException (com.cloud.legacymodel.exceptions.InsufficientCapacityException)50 InvalidParameterValueException (com.cloud.legacymodel.exceptions.InvalidParameterValueException)37 ServerApiException (com.cloud.api.ServerApiException)30 ResourceAllocationException (com.cloud.legacymodel.exceptions.ResourceAllocationException)28 Account (com.cloud.legacymodel.user.Account)23 AsyncJobExecutionContext (com.cloud.framework.jobs.AsyncJobExecutionContext)20 VmWorkJobVO (com.cloud.framework.jobs.impl.VmWorkJobVO)20 VirtualMachine (com.cloud.legacymodel.vm.VirtualMachine)20 DB (com.cloud.utils.db.DB)19 InsufficientAddressCapacityException (com.cloud.legacymodel.exceptions.InsufficientAddressCapacityException)17 NoTransitionException (com.cloud.legacymodel.exceptions.NoTransitionException)17 ConfigurationException (javax.naming.ConfigurationException)16 OperationTimedoutException (com.cloud.legacymodel.exceptions.OperationTimedoutException)14 Network (com.cloud.legacymodel.network.Network)14 ActionEvent (com.cloud.event.ActionEvent)13 NetworkVO (com.cloud.network.dao.NetworkVO)13 VirtualMachineMigrationException (com.cloud.legacymodel.exceptions.VirtualMachineMigrationException)12