Search in sources :

Example 6 with AsyncJob

use of org.apache.cloudstack.framework.jobs.AsyncJob in project cloudstack by apache.

the class ApiServer method getBaseAsyncResponse.

private String getBaseAsyncResponse(final long jobId, final BaseAsyncCmd cmd) {
    final AsyncJobResponse response = new AsyncJobResponse();
    final AsyncJob job = entityMgr.findById(AsyncJob.class, jobId);
    response.setJobId(job.getUuid());
    response.setResponseName(cmd.getCommandName());
    return ApiResponseSerializer.toSerializedString(response, cmd.getResponseType());
}
Also used : AsyncJobResponse(org.apache.cloudstack.api.response.AsyncJobResponse) AsyncJob(org.apache.cloudstack.framework.jobs.AsyncJob)

Example 7 with AsyncJob

use of org.apache.cloudstack.framework.jobs.AsyncJob in project cloudstack by apache.

the class VolumeApiServiceImpl method attachVolumeToVM.

public Volume attachVolumeToVM(Long vmId, Long volumeId, Long deviceId) {
    Account caller = CallContext.current().getCallingAccount();
    // Check that the volume ID is valid
    VolumeInfo volumeToAttach = volFactory.getVolume(volumeId);
    // Check that the volume is a data volume
    if (volumeToAttach == null || !(volumeToAttach.getVolumeType() == Volume.Type.DATADISK || volumeToAttach.getVolumeType() == Volume.Type.ROOT)) {
        throw new InvalidParameterValueException("Please specify a volume with the valid type: " + Volume.Type.ROOT.toString() + " or " + Volume.Type.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
    UserVmVO vm = _userVmDao.findById(vmId);
    if (vm == null || vm.getType() != VirtualMachine.Type.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(_volsDao.findById(volumeToAttach.getId()), vm);
            // vm shouldn't have any volume with deviceId 0
            if (!_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) {
        List<VolumeVO> existingDataVolumes = _volsDao.findByInstanceAndType(vmId, Volume.Type.DATADISK);
        int maxAttachableDataVolumesSupported = getMaxDataVolumesSupported(vm);
        if (existingDataVolumes.size() >= maxAttachableDataVolumesSupported) {
            throw new InvalidParameterValueException("The specified VM already has the maximum number of data disks (" + maxAttachableDataVolumesSupported + ") attached. Please specify another VM.");
        }
    }
    // If local storage is disabled then attaching a volume with local disk
    // offering not allowed
    DataCenterVO dataCenter = _dcDao.findById(volumeToAttach.getDataCenterId());
    if (!dataCenter.isLocalStorageEnabled()) {
        DiskOfferingVO diskOffering = _diskOfferingDao.findById(volumeToAttach.getDiskOfferingId());
        if (diskOffering.isUseLocalStorage()) {
            throw new InvalidParameterValueException("Zone is not configured to use local storage but volume's disk offering " + diskOffering.getName() + " uses it");
        }
    }
    // if target VM has associated VM snapshots
    List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
    if (vmSnapshots.size() > 0) {
        throw new InvalidParameterValueException("Unable to attach volume, please specify a VM that does not have VM snapshots");
    }
    // if target VM has backups
    if (vm.getBackupOfferingId() != null || vm.getBackupVolumeList().size() > 0) {
        throw new InvalidParameterValueException("Unable to attach volume, please specify a VM that does not have any backups");
    }
    // permission check
    _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");
    }
    Account owner = _accountDao.findById(volumeToAttach.getAccountId());
    if (!(volumeToAttach.getState() == Volume.State.Allocated || volumeToAttach.getState() == Volume.State.Ready)) {
        try {
            _resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, volumeToAttach.getSize());
        } catch (ResourceAllocationException e) {
            s_logger.error("primary storage resource limit check failed", e);
            throw new InvalidParameterValueException(e.getMessage());
        }
    }
    HypervisorType rootDiskHyperType = vm.getHypervisorType();
    HypervisorType volumeToAttachHyperType = _volsDao.getHypervisorType(volumeToAttach.getId());
    StoragePoolVO volumeToAttachStoragePool = _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");
        }
    }
    AsyncJobExecutionContext asyncExecutionContext = AsyncJobExecutionContext.getCurrentExecutionContext();
    if (asyncExecutionContext != null) {
        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");
        }
        _jobMgr.updateAsyncJobAttachment(job.getId(), "Volume", volumeId);
    }
    AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
    if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
        // avoid re-entrance
        VmWorkJobVO placeHolder = null;
        placeHolder = createPlaceHolderWork(vmId);
        try {
            return orchestrateAttachVolumeToVM(vmId, volumeId, deviceId);
        } finally {
            _workJobDao.expunge(placeHolder.getId());
        }
    } else {
        Outcome<Volume> outcome = attachVolumeToVmThroughJobQueue(vmId, volumeId, deviceId);
        Volume vol = null;
        try {
            outcome.get();
        } catch (InterruptedException e) {
            throw new RuntimeException("Operation is interrupted", e);
        } catch (java.util.concurrent.ExecutionException e) {
            throw new RuntimeException("Execution excetion", e);
        }
        Object jobResult = _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 = _volsDao.findById((Long) jobResult);
            }
        }
        return vol;
    }
}
Also used : Account(com.cloud.user.Account) UserVmVO(com.cloud.vm.UserVmVO) AsyncJobExecutionContext(org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext) VolumeInfo(org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo) AsyncJob(org.apache.cloudstack.framework.jobs.AsyncJob) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) InvalidParameterValueException(com.cloud.exception.InvalidParameterValueException) StoragePoolVO(org.apache.cloudstack.storage.datastore.db.StoragePoolVO) ResourceAllocationException(com.cloud.exception.ResourceAllocationException) DataCenterVO(com.cloud.dc.DataCenterVO) ConcurrentOperationException(com.cloud.exception.ConcurrentOperationException) EndPoint(org.apache.cloudstack.engine.subsystem.api.storage.EndPoint) VmWorkJobVO(org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO) HypervisorType(com.cloud.hypervisor.Hypervisor.HypervisorType) ExecutionException(java.util.concurrent.ExecutionException) VMSnapshotVO(com.cloud.vm.snapshot.VMSnapshotVO) 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(org.apache.cloudstack.engine.subsystem.api.storage.DataObject)

Example 8 with AsyncJob

use of org.apache.cloudstack.framework.jobs.AsyncJob in project cloudstack by apache.

the class ApiServer method handleAsyncJobPublishEvent.

@MessageHandler(topic = AsyncJob.Topics.JOB_EVENT_PUBLISH)
public void handleAsyncJobPublishEvent(String subject, String senderAddress, Object args) {
    assert (args != null);
    @SuppressWarnings("unchecked") Pair<AsyncJob, String> eventInfo = (Pair<AsyncJob, String>) args;
    AsyncJob job = eventInfo.first();
    String jobEvent = eventInfo.second();
    if (s_logger.isTraceEnabled())
        s_logger.trace("Handle asyjob publish event " + jobEvent);
    EventBus eventBus = null;
    try {
        eventBus = ComponentContext.getComponent(EventBus.class);
    } catch (NoSuchBeanDefinitionException nbe) {
        // no provider is configured to provide events bus, so just return
        return;
    }
    if (!job.getDispatcher().equalsIgnoreCase("ApiAsyncJobDispatcher")) {
        return;
    }
    User userJobOwner = accountMgr.getUserIncludingRemoved(job.getUserId());
    Account jobOwner = accountMgr.getAccount(userJobOwner.getAccountId());
    // Get the event type from the cmdInfo json string
    String info = job.getCmdInfo();
    String cmdEventType = "unknown";
    Map<String, Object> cmdInfoObj = new HashMap<String, Object>();
    if (info != null) {
        Type type = new TypeToken<Map<String, String>>() {
        }.getType();
        Map<String, String> cmdInfo = ApiGsonHelper.getBuilder().create().fromJson(info, type);
        cmdInfoObj.putAll(cmdInfo);
        String eventTypeObj = cmdInfo.get("cmdEventType");
        if (eventTypeObj != null) {
            cmdEventType = eventTypeObj;
            if (s_logger.isDebugEnabled())
                s_logger.debug("Retrieved cmdEventType from job info: " + cmdEventType);
        } else {
            if (s_logger.isDebugEnabled())
                s_logger.debug("Unable to locate cmdEventType marker in job info. publish as unknown event");
        }
        String contextDetails = cmdInfo.get("ctxDetails");
        if (contextDetails != null) {
            Type objectMapType = new TypeToken<Map<Object, Object>>() {
            }.getType();
            Map<Object, Object> ctxDetails = ApiGsonHelper.getBuilder().create().fromJson(contextDetails, objectMapType);
            cmdInfoObj.put("ctxDetails", ctxDetails);
        }
    }
    // For some reason, the instanceType / instanceId are not abstract, which means we may get null values.
    String instanceType = job.getInstanceType() != null ? job.getInstanceType() : "unknown";
    String instanceUuid = job.getInstanceId() != null ? ApiDBUtils.findJobInstanceUuid(job) : "";
    org.apache.cloudstack.framework.events.Event event = new org.apache.cloudstack.framework.events.Event("management-server", EventCategory.ASYNC_JOB_CHANGE_EVENT.getName(), jobEvent, instanceType, instanceUuid);
    Map<String, Object> eventDescription = new HashMap<String, Object>();
    eventDescription.put("command", job.getCmd());
    eventDescription.put("user", userJobOwner.getUuid());
    eventDescription.put("account", jobOwner.getUuid());
    eventDescription.put("processStatus", "" + job.getProcessStatus());
    eventDescription.put("resultCode", "" + job.getResultCode());
    eventDescription.put("instanceUuid", instanceUuid);
    eventDescription.put("instanceType", instanceType);
    eventDescription.put("commandEventType", cmdEventType);
    eventDescription.put("jobId", job.getUuid());
    eventDescription.put("jobResult", ApiSerializerHelper.fromSerializedStringToMap(job.getResult()));
    eventDescription.put("cmdInfo", cmdInfoObj);
    eventDescription.put("status", "" + job.getStatus());
    // If the event.accountinfo boolean value is set, get the human readable value for the username / domainname
    if (UseEventAccountInfo.value()) {
        DomainVO domain = domainDao.findById(jobOwner.getDomainId());
        eventDescription.put("username", userJobOwner.getUsername());
        eventDescription.put("accountname", jobOwner.getAccountName());
        eventDescription.put("domainname", domain.getName());
    }
    event.setDescription(eventDescription);
    try {
        eventBus.publish(event);
    } catch (EventBusException evx) {
        String errMsg = "Failed to publish async job event on the the event bus.";
        s_logger.warn(errMsg, evx);
    }
}
Also used : UserAccount(com.cloud.user.UserAccount) Account(com.cloud.user.Account) User(com.cloud.user.User) HashMap(java.util.HashMap) EventBus(org.apache.cloudstack.framework.events.EventBus) AsyncJob(org.apache.cloudstack.framework.jobs.AsyncJob) EventBusException(org.apache.cloudstack.framework.events.EventBusException) Pair(com.cloud.utils.Pair) NameValuePair(org.apache.http.NameValuePair) DomainVO(com.cloud.domain.DomainVO) Type(java.lang.reflect.Type) ExceptionProxyObject(com.cloud.utils.exception.ExceptionProxyObject) ResponseObject(org.apache.cloudstack.api.ResponseObject) NoSuchBeanDefinitionException(org.springframework.beans.factory.NoSuchBeanDefinitionException) Map(java.util.Map) HashMap(java.util.HashMap) MessageHandler(org.apache.cloudstack.framework.messagebus.MessageHandler)

Example 9 with AsyncJob

use of org.apache.cloudstack.framework.jobs.AsyncJob in project cloudstack by apache.

the class ApiServer method getBaseAsyncCreateResponse.

private String getBaseAsyncCreateResponse(final long jobId, final BaseAsyncCreateCmd cmd, final String objectUuid) {
    final CreateCmdResponse response = new CreateCmdResponse();
    final AsyncJob job = entityMgr.findById(AsyncJob.class, jobId);
    response.setJobId(job.getUuid());
    response.setId(objectUuid);
    response.setResponseName(cmd.getCommandName());
    return ApiResponseSerializer.toSerializedString(response, cmd.getResponseType());
}
Also used : CreateCmdResponse(org.apache.cloudstack.api.response.CreateCmdResponse) AsyncJob(org.apache.cloudstack.framework.jobs.AsyncJob)

Example 10 with AsyncJob

use of org.apache.cloudstack.framework.jobs.AsyncJob in project cloudstack by apache.

the class VolumeApiServiceImpl method detachVolumeFromVM.

@Override
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_DETACH, eventDescription = "detaching volume", async = true)
public Volume detachVolumeFromVM(DetachVolumeCmd cmmd) {
    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)");
    }
    Long volumeId = cmmd.getId();
    VolumeVO volume = null;
    if (volumeId != null) {
        volume = _volsDao.findById(volumeId);
    } else {
        volume = _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);
    }
    Long vmId = null;
    if (cmmd.getVirtualMachineId() == null) {
        vmId = volume.getInstanceId();
    } else {
        vmId = cmmd.getVirtualMachineId();
    }
    // Permissions check
    _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
    UserVmVO vm = _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() == Volume.Type.ROOT || volume.getVolumeType() == Volume.Type.DATADISK)) {
        throw new InvalidParameterValueException("Please specify volume of type " + Volume.Type.DATADISK.toString() + " or " + Volume.Type.ROOT.toString());
    }
    // Root volume detach is allowed for following hypervisors: Xen/KVM/VmWare
    if (volume.getVolumeType() == Volume.Type.ROOT) {
        validateRootVolumeDetachAttach(volume, vm);
    }
    // Don't allow detach if target VM has associated VM snapshots
    List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
    if (vmSnapshots.size() > 0) {
        throw new InvalidParameterValueException("Unable to detach volume, please specify a VM that does not have VM snapshots");
    }
    if (vm.getBackupOfferingId() != null || vm.getBackupVolumeList().size() > 0) {
        throw new InvalidParameterValueException("Unable to detach volume, cannot detach volume from a VM that has backups. First remove the VM from the backup offering.");
    }
    AsyncJobExecutionContext asyncExecutionContext = AsyncJobExecutionContext.getCurrentExecutionContext();
    if (asyncExecutionContext != null) {
        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");
        }
        _jobMgr.updateAsyncJobAttachment(job.getId(), "Volume", volumeId);
    }
    AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
    if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
        // avoid re-entrance
        VmWorkJobVO placeHolder = null;
        placeHolder = createPlaceHolderWork(vmId);
        try {
            return orchestrateDetachVolumeFromVM(vmId, volumeId);
        } finally {
            _workJobDao.expunge(placeHolder.getId());
        }
    } else {
        Outcome<Volume> outcome = detachVolumeFromVmThroughJobQueue(vmId, volumeId);
        Volume vol = null;
        try {
            outcome.get();
        } catch (InterruptedException e) {
            throw new RuntimeException("Operation is interrupted", e);
        } catch (java.util.concurrent.ExecutionException e) {
            throw new RuntimeException("Execution excetion", e);
        }
        Object jobResult = _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 = _volsDao.findById((Long) jobResult);
            }
        }
        return vol;
    }
}
Also used : Account(com.cloud.user.Account) UserVmVO(com.cloud.vm.UserVmVO) AsyncJobExecutionContext(org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext) ConcurrentOperationException(com.cloud.exception.ConcurrentOperationException) AsyncJob(org.apache.cloudstack.framework.jobs.AsyncJob) VmWorkJobVO(org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO) ExecutionException(java.util.concurrent.ExecutionException) VMSnapshotVO(com.cloud.vm.snapshot.VMSnapshotVO) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) InvalidParameterValueException(com.cloud.exception.InvalidParameterValueException) 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(org.apache.cloudstack.engine.subsystem.api.storage.DataObject) ActionEvent(com.cloud.event.ActionEvent)

Aggregations

AsyncJob (org.apache.cloudstack.framework.jobs.AsyncJob)10 Account (com.cloud.user.Account)4 AsyncJobExecutionContext (org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext)4 InvalidParameterValueException (com.cloud.exception.InvalidParameterValueException)3 CloudRuntimeException (com.cloud.utils.exception.CloudRuntimeException)3 ConcurrentOperationException (com.cloud.exception.ConcurrentOperationException)2 User (com.cloud.user.User)2 UserAccount (com.cloud.user.UserAccount)2 UserVmVO (com.cloud.vm.UserVmVO)2 VmWorkAttachVolume (com.cloud.vm.VmWorkAttachVolume)2 VmWorkDetachVolume (com.cloud.vm.VmWorkDetachVolume)2 VmWorkExtractVolume (com.cloud.vm.VmWorkExtractVolume)2 VmWorkMigrateVolume (com.cloud.vm.VmWorkMigrateVolume)2 VmWorkResizeVolume (com.cloud.vm.VmWorkResizeVolume)2 VMSnapshotVO (com.cloud.vm.snapshot.VMSnapshotVO)2 HashMap (java.util.HashMap)2 ExecutionException (java.util.concurrent.ExecutionException)2 ResponseObject (org.apache.cloudstack.api.ResponseObject)2 ListResponse (org.apache.cloudstack.api.response.ListResponse)2 DataObject (org.apache.cloudstack.engine.subsystem.api.storage.DataObject)2