This is an automated email from the ASF dual-hosted git repository.

harikrishna pushed a commit to branch CheckVolumeAPI
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit 61a63a9307d72e635afd8677da1ae4b1905ff46a
Author: Harikrishna Patnala <harikrishna.patn...@gmail.com>
AuthorDate: Thu Feb 1 12:28:40 2024 +0530

    Code refactored
---
 .../engine/orchestration/VolumeOrchestrator.java   |  17 ++--
 .../LibvirtCheckAndRepairVolumeCommandWrapper.java | 102 ++++++++++++-------
 .../com/cloud/storage/VolumeApiServiceImpl.java    | 111 +++++++++++----------
 3 files changed, 139 insertions(+), 91 deletions(-)

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<Ch
 
         final KVMStoragePoolManager storagePoolMgr = 
serverResource.getStoragePoolMgr();
         KVMStoragePool pool = storagePoolMgr.getStoragePool(spool.getType(), 
spool.getUuid());
-
         final KVMPhysicalDisk vol = pool.getPhysicalDisk(volumeId);
-        QemuObject.EncryptFormat encryptFormat = 
QemuObject.EncryptFormat.enumValue(command.getEncryptFormat());
         byte[] passphrase = command.getPassphrase();
+
         try {
-            String checkVolumeResult = checkAndRepairVolume(vol, null, 
encryptFormat, passphrase, serverResource);
-            s_logger.info(String.format("Check Volume result for the volume %s 
is %s", vol.getName(), checkVolumeResult));
-            CheckAndRepairVolumeAnswer answer = new 
CheckAndRepairVolumeAnswer(command, true, checkVolumeResult);
-            answer.setVolumeCheckExecutionResult(checkVolumeResult);
-
-            int leaks = 0;
-            if (StringUtils.isNotEmpty(checkVolumeResult) && 
StringUtils.isNotEmpty(repair) && repair.equals("leaks")) {
-                ObjectMapper objectMapper = new ObjectMapper();
-                JsonNode jsonNode = objectMapper.readTree(checkVolumeResult);
-                JsonNode leaksNode = jsonNode.get("leaks");
-                if (leaksNode != null) {
-                    leaks = leaksNode.asInt();
-                }
-
-                if (leaks == 0) {
-                    String msg = String.format("no leaks found while checking 
for the volume %s, so skipping repair", vol.getName());
-                    s_logger.info(msg);
-                    String jsonStringFormat = String.format("{ \"message\": 
\"%s\" }", msg);
-                    String finalResult = (checkVolumeResult != null ? 
checkVolumeResult.concat(",") : "") + jsonStringFormat;
-                    answer = new CheckAndRepairVolumeAnswer(command, true, 
finalResult);
-                    answer.setVolumeRepairExecutionResult(jsonStringFormat);
-                    answer.setVolumeCheckExecutionResult(checkVolumeResult);
-
-                    return answer;
-                }
+            CheckAndRepairVolumeAnswer answer = checkVolume(vol, command, 
serverResource);
+            String checkVolumeResult =  answer.getVolumeCheckExecutionResult();
+
+            CheckAndRepairVolumeAnswer resultAnswer = 
checkIfRepairLeaksIsRequired(command, checkVolumeResult, vol.getName());
+            // resultAnswer is not null when repair is not required, so return 
from here
+            if (resultAnswer != null) {
+                return resultAnswer;
             }
 
             if (StringUtils.isNotEmpty(repair)) {
-                String repairVolumeResult = checkAndRepairVolume(vol, repair, 
encryptFormat, passphrase, serverResource);
-                String finalResult = (checkVolumeResult != null ? 
checkVolumeResult.concat(",") : "") + repairVolumeResult;
-                s_logger.info(String.format("Repair Volume result for the 
volume %s is %s", vol.getName(), repairVolumeResult));
-
-                answer = new CheckAndRepairVolumeAnswer(command, true, 
finalResult);
-                answer.setVolumeRepairExecutionResult(repairVolumeResult);
-                answer.setVolumeCheckExecutionResult(checkVolumeResult);
+                answer = repairVolume(vol, command, serverResource, 
checkVolumeResult);
             }
+
             return answer;
         } catch (Exception e) {
             return new CheckAndRepairVolumeAnswer(command, false, 
e.toString());
@@ -112,7 +90,61 @@ public class LibvirtCheckAndRepairVolumeCommandWrapper 
extends CommandWrapper<Ch
         }
     }
 
-    protected String checkAndRepairVolume(final KVMPhysicalDisk vol, final 
String repair, final QemuObject.EncryptFormat encryptFormat, byte[] passphrase, 
final LibvirtComputingResource libvirtComputingResource) throws 
CloudRuntimeException {
+    private CheckAndRepairVolumeAnswer checkVolume(KVMPhysicalDisk vol, 
CheckAndRepairVolumeCommand command, LibvirtComputingResource serverResource) {
+        EncryptFormat encryptFormat = 
EncryptFormat.enumValue(command.getEncryptFormat());
+        byte[] passphrase = command.getPassphrase();
+        String checkVolumeResult = checkAndRepairVolume(vol, null, 
encryptFormat, passphrase, serverResource);
+        s_logger.info(String.format("Check Volume result for the volume %s is 
%s", vol.getName(), checkVolumeResult));
+        CheckAndRepairVolumeAnswer answer = new 
CheckAndRepairVolumeAnswer(command, true, checkVolumeResult);
+        answer.setVolumeCheckExecutionResult(checkVolumeResult);
+
+        return answer;
+    }
+
+    private CheckAndRepairVolumeAnswer repairVolume(KVMPhysicalDisk vol, 
CheckAndRepairVolumeCommand command, LibvirtComputingResource serverResource, 
String checkVolumeResult) {
+        EncryptFormat encryptFormat = 
EncryptFormat.enumValue(command.getEncryptFormat());
+        byte[] passphrase = command.getPassphrase();
+        final String repair = command.getRepair();
+
+        String repairVolumeResult = checkAndRepairVolume(vol, repair, 
encryptFormat, passphrase, serverResource);
+        String finalResult = (checkVolumeResult != null ? 
checkVolumeResult.concat(",") : "") + repairVolumeResult;
+        s_logger.info(String.format("Repair Volume result for the volume %s is 
%s", vol.getName(), repairVolumeResult));
+
+        CheckAndRepairVolumeAnswer answer = new 
CheckAndRepairVolumeAnswer(command, true, finalResult);
+        answer.setVolumeRepairExecutionResult(repairVolumeResult);
+        answer.setVolumeCheckExecutionResult(checkVolumeResult);
+
+        return answer;
+    }
+
+    private CheckAndRepairVolumeAnswer 
checkIfRepairLeaksIsRequired(CheckAndRepairVolumeCommand command, String 
checkVolumeResult, String volumeName) throws JsonProcessingException {
+        final String repair = command.getRepair();
+        int leaks = 0;
+        if (StringUtils.isNotEmpty(checkVolumeResult) && 
StringUtils.isNotEmpty(repair) && repair.equals("leaks")) {
+            ObjectMapper objectMapper = new ObjectMapper();
+            JsonNode jsonNode = objectMapper.readTree(checkVolumeResult);
+            JsonNode leaksNode = jsonNode.get("leaks");
+            if (leaksNode != null) {
+                leaks = leaksNode.asInt();
+            }
+
+            if (leaks == 0) {
+                String msg = String.format("no leaks found while checking for 
the volume %s, so skipping repair", volumeName);
+                s_logger.info(msg);
+                String jsonStringFormat = String.format("{ \"message\": \"%s\" 
}", msg);
+                String finalResult = (checkVolumeResult != null ? 
checkVolumeResult.concat(",") : "") + jsonStringFormat;
+                CheckAndRepairVolumeAnswer answer = new 
CheckAndRepairVolumeAnswer(command, true, finalResult);
+                answer.setVolumeRepairExecutionResult(jsonStringFormat);
+                answer.setVolumeCheckExecutionResult(checkVolumeResult);
+
+                return answer;
+            }
+        }
+
+        return null;
+    }
+
+    protected String checkAndRepairVolume(final KVMPhysicalDisk vol, final 
String repair, final EncryptFormat encryptFormat, byte[] passphrase, final 
LibvirtComputingResource libvirtComputingResource) throws CloudRuntimeException 
{
         List<QemuObject> 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<String, String> result = 
orchestrateCheckAndRepairVolume(volumeId, repair);
-                    return result;
-                } finally {
-                    _workJobDao.expunge(placeHolder.getId());
-                }
-            } else {
-                Outcome<Pair> outcome = 
checkAndRepairVolumeThroughJobQueue(vmId, volumeId, repair);
+    private Pair<String, String> 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<String, String> 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);
-                    }
-                }
+    private Pair<String, String> 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<String, String> result = 
orchestrateCheckAndRepairVolume(volumeId, repair);
+                return result;
+            } finally {
+                _workJobDao.expunge(placeHolder.getId());
+            }
+        } else {
+            Outcome<Pair> 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);
+            }
 
-                // retrieve the entity url from job result
-                if (jobResult != null && jobResult instanceof Pair) {
-                    return (Pair<String, String>) jobResult;
+            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);
                 }
+            }
 
-                return null;
+            // retrieve the entity url from job result
+            if (jobResult != null && jobResult instanceof Pair) {
+                return (Pair<String, String>) jobResult;
             }
-        } else {
-            CheckAndRepairVolumePayload payload = new 
CheckAndRepairVolumePayload(repair);
-            VolumeInfo volumeInfo = volFactory.getVolume(volumeId);
-            volumeInfo.addPayload(payload);
 
-            Pair<String, String> result = 
volService.checkAndRepairVolume(volumeInfo);
-            return result;
+            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<String, String> orchestrateCheckAndRepairVolume(Long 
volumeId, String repair) {
 
         VolumeInfo volume = volFactory.getVolume(volumeId);

Reply via email to