diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index 4e157303b71..cde997be62b 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -1916,12 +1916,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } } } else { - Host host = _hostDao.findById(vm.getVirtualMachine().getHostId()); - try { - volService.checkAndRepairVolumeBasedOnConfig(volFactory.getVolume(vol.getId()), host); - } catch (Exception e) { - s_logger.debug(String.format("Unable to check and repair volume [%s] on host [%s], due to %s.", volToString, host, e.getMessage())); - } + handleCheckAndRepairVolume(vol, vm.getVirtualMachine().getHostId()); } } else if (task.type == VolumeTaskType.MIGRATE) { pool = (StoragePool)dataStoreMgr.getDataStore(task.pool.getId(), DataStoreRole.Primary); @@ -1964,6 +1959,16 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } } + private void handleCheckAndRepairVolume(Volume vol, Long hostId) { + Host host = _hostDao.findById(hostId); + try { + volService.checkAndRepairVolumeBasedOnConfig(volFactory.getVolume(vol.getId()), host); + } catch (Exception e) { + String volumeToString = getReflectOnlySelectedFields(vol); + s_logger.debug(String.format("Unable to check and repair volume [%s] on host [%s], due to %s.", volumeToString, host, e.getMessage())); + } + } + private boolean stateTransitTo(Volume vol, Volume.Event event) throws NoTransitionException { return _volStateMachine.transitTo(vol, event, null, _volsDao); } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckAndRepairVolumeCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckAndRepairVolumeCommandWrapper.java index a9d9cd948e6..e31a4a0287a 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckAndRepairVolumeCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckAndRepairVolumeCommandWrapper.java @@ -30,6 +30,7 @@ import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager; import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; import com.cloud.utils.exception.CloudRuntimeException; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.JsonNode; import org.apache.cloudstack.utils.cryptsetup.KeyFile; @@ -38,6 +39,7 @@ import org.apache.cloudstack.utils.qemu.QemuImg; import org.apache.cloudstack.utils.qemu.QemuImgException; import org.apache.cloudstack.utils.qemu.QemuImgFile; import org.apache.cloudstack.utils.qemu.QemuObject; +import org.apache.cloudstack.utils.qemu.QemuObject.EncryptFormat; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; @@ -61,47 +63,23 @@ public class LibvirtCheckAndRepairVolumeCommandWrapper extends CommandWrapper passphraseObjects = new ArrayList<>(); QemuImageOptions imgOptions = null; if (ArrayUtils.isEmpty(passphrase)) { diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 36b0aee98c5..6a89ac4d4d9 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -1834,54 +1834,60 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic Long vmId = volume.getInstanceId(); if (vmId != null) { // serialize VM operation - AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext(); - if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) { - // avoid re-entrance + return handleCheckAndRepairVolumeJob(vmId, volumeId, repair); + } else { + return handleCheckAndRepairVolume(volumeId, repair); + } + } - VmWorkJobVO placeHolder = null; - placeHolder = createPlaceHolderWork(vmId); - try { - Pair result = orchestrateCheckAndRepairVolume(volumeId, repair); - return result; - } finally { - _workJobDao.expunge(placeHolder.getId()); - } - } else { - Outcome outcome = checkAndRepairVolumeThroughJobQueue(vmId, volumeId, repair); + private Pair handleCheckAndRepairVolume(Long volumeId, String repair) { + CheckAndRepairVolumePayload payload = new CheckAndRepairVolumePayload(repair); + VolumeInfo volumeInfo = volFactory.getVolume(volumeId); + volumeInfo.addPayload(payload); - try { - outcome.get(); - } catch (InterruptedException e) { - throw new RuntimeException("Operation is interrupted", e); - } catch (ExecutionException e) { - throw new RuntimeException("Execution exception--", e); - } + Pair result = volService.checkAndRepairVolume(volumeInfo); + return result; + } - Object jobResult = _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 Throwable) { - throw new RuntimeException("Unexpected exception", (Throwable)jobResult); - } - } - - // retrieve the entity url from job result - if (jobResult != null && jobResult instanceof Pair) { - return (Pair) jobResult; - } - - return null; + private Pair handleCheckAndRepairVolumeJob(Long vmId, Long volumeId, String repair) throws ResourceAllocationException { + AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext(); + if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) { + // avoid re-entrance + VmWorkJobVO placeHolder = null; + placeHolder = createPlaceHolderWork(vmId); + try { + Pair result = orchestrateCheckAndRepairVolume(volumeId, repair); + return result; + } finally { + _workJobDao.expunge(placeHolder.getId()); } } else { - CheckAndRepairVolumePayload payload = new CheckAndRepairVolumePayload(repair); - VolumeInfo volumeInfo = volFactory.getVolume(volumeId); - volumeInfo.addPayload(payload); + Outcome outcome = checkAndRepairVolumeThroughJobQueue(vmId, volumeId, repair); + try { + outcome.get(); + } catch (InterruptedException e) { + throw new RuntimeException("Operation is interrupted", e); + } catch (ExecutionException e) { + throw new RuntimeException("Execution exception--", e); + } - Pair result = volService.checkAndRepairVolume(volumeInfo); - return result; + Object jobResult = _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 Throwable) { + throw new RuntimeException("Unexpected exception", (Throwable)jobResult); + } + } + + // retrieve the entity url from job result + if (jobResult != null && jobResult instanceof Pair) { + return (Pair) jobResult; + } + + return null; } } @@ -1892,16 +1898,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic Long volumeId = volume.getId(); Long vmId = volume.getInstanceId(); if (vmId != null) { - UserVmVO vm = _userVmDao.findById(vmId); - if (vm == null) { - throw new InvalidParameterValueException(String.format("VM not found, please check the VM to which this volume %d is attached", volumeId)); - } - - _accountMgr.checkAccess(caller, null, true, vm); - - if (vm.getState() != State.Stopped) { - throw new InvalidParameterValueException(String.format("VM to which the volume %d is attached should be in stopped state", volumeId)); - } + validateVMforCheckVolumeOperation(vmId, volumeId); } if (volume.getState() != Volume.State.Ready) { @@ -1914,6 +1911,20 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } } + private void validateVMforCheckVolumeOperation(Long vmId, Long volumeId) { + Account caller = CallContext.current().getCallingAccount(); + UserVmVO vm = _userVmDao.findById(vmId); + if (vm == null) { + throw new InvalidParameterValueException(String.format("VM not found, please check the VM to which this volume %d is attached", volumeId)); + } + + _accountMgr.checkAccess(caller, null, true, vm); + + if (vm.getState() != State.Stopped) { + throw new InvalidParameterValueException(String.format("VM to which the volume %d is attached should be in stopped state", volumeId)); + } + } + private Pair orchestrateCheckAndRepairVolume(Long volumeId, String repair) { VolumeInfo volume = volFactory.getVolume(volumeId);