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 2710405e81df85b357c2fd7dc44743a7354bea73 Author: Harikrishna Patnala <[email protected]> AuthorDate: Tue Jan 30 13:10:04 2024 +0530 Changed repair parameter to accept both leaks/all --- .../user/volume/CheckVolumeAndRepairCmd.java | 21 +++++++++---- .../cloudstack/api/response/VolumeResponse.java | 4 +-- .../api/storage/CheckVolumeAndRepairCommand.java | 6 ++-- .../com/cloud/vm/VmWorkCheckAndRepairVolume.java | 6 ++-- .../storage/volume/VolumeServiceImpl.java | 20 ++++++++----- .../storage/volume/VolumeServiceTest.java | 8 ++--- .../LibvirtCheckVolumeAndRepairCommandWrapper.java | 35 ++++++++++++++++++---- .../org/apache/cloudstack/utils/qemu/QemuImg.java | 6 ++-- ...virtCheckVolumeAndRepairCommandWrapperTest.java | 5 ++-- .../apache/cloudstack/utils/qemu/QemuImgTest.java | 2 +- .../cloud/storage/CheckAndRepairVolumePayload.java | 6 ++-- .../com/cloud/storage/VolumeApiServiceImpl.java | 14 +++++---- .../cloud/storage/VolumeApiServiceImplTest.java | 2 +- 13 files changed, 90 insertions(+), 45 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/CheckVolumeAndRepairCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/CheckVolumeAndRepairCmd.java index 0aa221dd43d..5ac5445fe5f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/CheckVolumeAndRepairCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/CheckVolumeAndRepairCmd.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; +import com.cloud.exception.InvalidParameterValueException; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -52,19 +53,29 @@ public class CheckVolumeAndRepairCmd extends BaseCmd { @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VolumeResponse.class, required = true, description = "The ID of the volume") private Long id; - @Parameter(name = ApiConstants.REPAIR, type = CommandType.BOOLEAN, required = false, description = "true to repair the volume, repairs if it has any leaks") - private Boolean repair; + @Parameter(name = ApiConstants.REPAIR, type = CommandType.STRING, required = false, description = "parameter to repair the volume, leaks or all are the possible values") + private String repair; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// + public enum RepairValues { + leaks, all + } + public Long getId() { return id; } - public boolean getRepair() { - return repair == null ? false : repair; + public String getRepair() { + if (org.apache.commons.lang3.StringUtils.isNotEmpty(repair)) { + RepairValues repairType = Enum.valueOf(RepairValues.class, repair); + if (repairType == null) { + throw new InvalidParameterValueException("repair parameter only takes either leaks or all as value"); + } + } + return repair; } ///////////////////////////////////////////////////// @@ -104,7 +115,7 @@ public class CheckVolumeAndRepairCmd extends BaseCmd { if (result != null) { VolumeResponse response = _responseGenerator.createVolumeResponse(ResponseView.Full, volume); response.setVolumeCheckResult(StringUtils.parseJsonToMap(result.first())); - if (getRepair()) { + if (getRepair() != null) { response.setVolumeRepairResult(StringUtils.parseJsonToMap(result.second())); } response.setResponseName(getCommandName()); diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java index 785284ad46f..daf3cf3950f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java @@ -290,11 +290,11 @@ public class VolumeResponse extends BaseResponseWithTagInformation implements Co private String externalUuid; @SerializedName(ApiConstants.VOLUME_CHECK_RESULT) - @Param(description = "details for the volume check result") + @Param(description = "details for the volume check result, they may vary for different hypervisors") private Map<String, String> volumeCheckResult; @SerializedName(ApiConstants.VOLUME_REPAIR_RESULT) - @Param(description = "details for the volume repair result") + @Param(description = "details for the volume repair result, they may vary for different hypervisors") private Map<String, String> volumeRepairResult; public String getPath() { diff --git a/core/src/main/java/com/cloud/agent/api/storage/CheckVolumeAndRepairCommand.java b/core/src/main/java/com/cloud/agent/api/storage/CheckVolumeAndRepairCommand.java index 040e6ca8608..e6d12aab513 100644 --- a/core/src/main/java/com/cloud/agent/api/storage/CheckVolumeAndRepairCommand.java +++ b/core/src/main/java/com/cloud/agent/api/storage/CheckVolumeAndRepairCommand.java @@ -28,12 +28,12 @@ import java.util.Arrays; public class CheckVolumeAndRepairCommand extends Command { private String path; private StorageFilerTO pool; - private boolean repair; + private String repair; @LogLevel(LogLevel.Log4jLevel.Off) private byte[] passphrase; private String encryptFormat; - public CheckVolumeAndRepairCommand(String path, StorageFilerTO pool, boolean repair, byte[] passphrase, String encryptFormat) { + public CheckVolumeAndRepairCommand(String path, StorageFilerTO pool, String repair, byte[] passphrase, String encryptFormat) { this.path = path; this.pool = pool; this.repair = repair; @@ -53,7 +53,7 @@ public class CheckVolumeAndRepairCommand extends Command { return pool; } - public boolean needRepair() { + public String getRepair() { return repair; } diff --git a/engine/components-api/src/main/java/com/cloud/vm/VmWorkCheckAndRepairVolume.java b/engine/components-api/src/main/java/com/cloud/vm/VmWorkCheckAndRepairVolume.java index 7e62f08fe61..b6b73df959f 100644 --- a/engine/components-api/src/main/java/com/cloud/vm/VmWorkCheckAndRepairVolume.java +++ b/engine/components-api/src/main/java/com/cloud/vm/VmWorkCheckAndRepairVolume.java @@ -23,10 +23,10 @@ public class VmWorkCheckAndRepairVolume extends VmWork { private Long volumeId; - private boolean repair; + private String repair; public VmWorkCheckAndRepairVolume(long userId, long accountId, long vmId, String handlerName, - Long volumeId, boolean repair) { + Long volumeId, String repair) { super(userId, accountId, vmId, handlerName); this.repair = repair; this.volumeId = volumeId; @@ -36,7 +36,7 @@ public class VmWorkCheckAndRepairVolume extends VmWork { return volumeId; } - public boolean needRepair() { + public String getRepair() { return repair; } } diff --git a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index e7c9a7c7a42..553417bf2a0 100644 --- a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -34,6 +34,7 @@ import javax.inject.Inject; import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.annotation.dao.AnnotationDao; +import org.apache.cloudstack.api.command.user.volume.CheckVolumeAndRepairCmd; import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity; import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; @@ -92,6 +93,7 @@ import com.cloud.agent.api.storage.CheckVolumeAndRepairCommand; import com.cloud.agent.api.storage.ListVolumeAnswer; import com.cloud.agent.api.storage.ListVolumeCommand; import com.cloud.agent.api.storage.ResizeVolumeCommand; +import com.cloud.agent.api.to.DataObjectType; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.alert.AlertManager; @@ -252,11 +254,15 @@ public class VolumeServiceImpl implements VolumeService { return ((PrimaryDataStoreDriver)dataStoreDriver).grantAccess(dataObject, host, dataStore); } - if (HypervisorType.KVM.equals(host.getHypervisorType()) && DataObjectType.VOLUME.equals(dataObject.getType())) { - CheckAndRepairVolumePayload payload = new CheckAndRepairVolumePayload(true); - VolumeInfo volumeInfo = volFactory.getVolume(dataObject.getId()); - volumeInfo.addPayload(payload); - checkAndRepairVolume(volumeInfo); + if (com.cloud.storage.VolumeApiServiceImpl.AllowVolumeCheckAndRepair.value()) { + if (HypervisorType.KVM.equals(host.getHypervisorType()) && DataObjectType.VOLUME.equals(dataObject.getType())) { + s_logger.info(String.format("Trying to check and repair the volume %d", dataObject.getId())); + String repair = CheckVolumeAndRepairCmd.RepairValues.leaks.name(); + CheckAndRepairVolumePayload payload = new CheckAndRepairVolumePayload(repair); + VolumeInfo volumeInfo = volFactory.getVolume(dataObject.getId()); + volumeInfo.addPayload(payload); + checkAndRepairVolume(volumeInfo); + } } return false; @@ -2775,7 +2781,7 @@ public class VolumeServiceImpl implements VolumeService { Long poolId = volume.getPoolId(); StoragePool pool = _storageMgr.getStoragePool(poolId); CheckAndRepairVolumePayload payload = (CheckAndRepairVolumePayload) volume.getpayload(); - CheckVolumeAndRepairCommand command = new CheckVolumeAndRepairCommand(volume.getPath(), new StorageFilerTO(pool), payload.isRepair(), + CheckVolumeAndRepairCommand command = new CheckVolumeAndRepairCommand(volume.getPath(), new StorageFilerTO(pool), payload.getRepair(), volume.getPassphrase(), volume.getEncryptFormat()); try { @@ -2783,7 +2789,7 @@ public class VolumeServiceImpl implements VolumeService { if (answer != null && answer.getResult()) { s_logger.debug("Check volume response result: " + answer.getDetails()); payload.setVolumeCheckExecutionResult(answer.getVolumeCheckExecutionResult()); - if (payload.isRepair()) { + if (StringUtils.isNotEmpty(payload.getRepair())) { payload.setVolumeRepairedExecutionResult(answer.getVolumeRepairExecutionResult()); } return new Pair<>(answer.getVolumeCheckExecutionResult(), answer.getVolumeRepairExecutionResult()); diff --git a/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeServiceTest.java b/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeServiceTest.java index ddcfcefc890..23996fda470 100644 --- a/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeServiceTest.java +++ b/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeServiceTest.java @@ -234,7 +234,7 @@ public class VolumeServiceTest extends TestCase{ Mockito.when(volume.getPoolId()).thenReturn(1L); StoragePool pool = Mockito.mock(StoragePool.class); Mockito.when(storageManagerMock.getStoragePool(1L)).thenReturn(pool); - CheckAndRepairVolumePayload payload = new CheckAndRepairVolumePayload(false); + CheckAndRepairVolumePayload payload = new CheckAndRepairVolumePayload(null); Mockito.when(volume.getpayload()).thenReturn(payload); Mockito.when(volume.getPath()).thenReturn("cbac516a-0f1f-4559-921c-1a7c6c408ccf"); Mockito.when(volume.getPassphrase()).thenReturn(new byte[] {3, 1, 2, 3}); @@ -251,7 +251,7 @@ public class VolumeServiceTest extends TestCase{ " \"fragmented-clusters\": 96135\n" + "}"; - CheckVolumeAndRepairCommand command = new CheckVolumeAndRepairCommand(volume.getPath(), new StorageFilerTO(pool), payload.isRepair(), + CheckVolumeAndRepairCommand command = new CheckVolumeAndRepairCommand(volume.getPath(), new StorageFilerTO(pool), payload.getRepair(), volume.getPassphrase(), volume.getEncryptFormat()); CheckVolumeAndRepairAnswer answer = new CheckVolumeAndRepairAnswer(command, true, checkResult); @@ -270,13 +270,13 @@ public class VolumeServiceTest extends TestCase{ Mockito.when(volume.getPoolId()).thenReturn(1L); StoragePool pool = Mockito.mock(StoragePool.class); Mockito.when(storageManagerMock.getStoragePool(1L)).thenReturn(pool); - CheckAndRepairVolumePayload payload = new CheckAndRepairVolumePayload(false); + CheckAndRepairVolumePayload payload = new CheckAndRepairVolumePayload(null); Mockito.when(volume.getpayload()).thenReturn(payload); Mockito.when(volume.getPath()).thenReturn("cbac516a-0f1f-4559-921c-1a7c6c408ccf"); Mockito.when(volume.getPassphrase()).thenReturn(new byte[] {3, 1, 2, 3}); Mockito.when(volume.getEncryptFormat()).thenReturn("LUKS"); - CheckVolumeAndRepairCommand command = new CheckVolumeAndRepairCommand(volume.getPath(), new StorageFilerTO(pool), payload.isRepair(), + CheckVolumeAndRepairCommand command = new CheckVolumeAndRepairCommand(volume.getPath(), new StorageFilerTO(pool), payload.getRepair(), volume.getPassphrase(), volume.getEncryptFormat()); CheckVolumeAndRepairAnswer answer = new CheckVolumeAndRepairAnswer(command, false, "Unable to execute qemu command"); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckVolumeAndRepairCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckVolumeAndRepairCommandWrapper.java index 47c00248f6d..280e2aa14d2 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckVolumeAndRepairCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckVolumeAndRepairCommandWrapper.java @@ -30,6 +30,8 @@ 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.databind.ObjectMapper; +import com.fasterxml.jackson.databind.JsonNode; import org.apache.cloudstack.utils.cryptsetup.KeyFile; import org.apache.cloudstack.utils.qemu.QemuImageOptions; import org.apache.cloudstack.utils.qemu.QemuImg; @@ -37,6 +39,7 @@ import org.apache.cloudstack.utils.qemu.QemuImgException; import org.apache.cloudstack.utils.qemu.QemuImgFile; import org.apache.cloudstack.utils.qemu.QemuObject; import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.libvirt.LibvirtException; @@ -53,7 +56,7 @@ public class LibvirtCheckVolumeAndRepairCommandWrapper extends CommandWrapper<Ch @Override public Answer execute(CheckVolumeAndRepairCommand command, LibvirtComputingResource serverResource) { final String volumeId = command.getPath(); - final boolean repair = command.needRepair(); + final String repair = command.getRepair(); final StorageFilerTO spool = command.getPool(); final KVMStoragePoolManager storagePoolMgr = serverResource.getStoragePoolMgr(); @@ -63,13 +66,35 @@ public class LibvirtCheckVolumeAndRepairCommandWrapper extends CommandWrapper<Ch QemuObject.EncryptFormat encryptFormat = QemuObject.EncryptFormat.enumValue(command.getEncryptFormat()); byte[] passphrase = command.getPassphrase(); try { - String checkVolumeResult = checkVolumeAndRepair(vol, false, encryptFormat, passphrase, serverResource); + String checkVolumeResult = checkVolumeAndRepair(vol, repair, encryptFormat, passphrase, serverResource); s_logger.info(String.format("Check Volume result for the volume %s is %s", vol.getName(), checkVolumeResult)); CheckVolumeAndRepairAnswer answer = new CheckVolumeAndRepairAnswer(command, true, checkVolumeResult); answer.setVolumeCheckExecutionResult(checkVolumeResult); - if (repair) { - String repairVolumeResult = checkVolumeAndRepair(vol, true, encryptFormat, passphrase, serverResource); + 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 = jsonNode.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 CheckVolumeAndRepairAnswer(command, true, finalResult); + answer.setVolumeRepairExecutionResult(jsonStringFormat); + answer.setVolumeCheckExecutionResult(checkVolumeResult); + + return answer; + } + } + + if (StringUtils.isNotEmpty(repair)) { + String repairVolumeResult = checkVolumeAndRepair(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)); @@ -87,7 +112,7 @@ public class LibvirtCheckVolumeAndRepairCommandWrapper extends CommandWrapper<Ch } } - protected String checkVolumeAndRepair(final KVMPhysicalDisk vol, final boolean repair, final QemuObject.EncryptFormat encryptFormat, byte[] passphrase, final LibvirtComputingResource libvirtComputingResource) throws CloudRuntimeException { + protected String checkVolumeAndRepair(final KVMPhysicalDisk vol, final String repair, final QemuObject.EncryptFormat encryptFormat, byte[] passphrase, final LibvirtComputingResource libvirtComputingResource) throws CloudRuntimeException { List<QemuObject> passphraseObjects = new ArrayList<>(); QemuImageOptions imgOptions = null; if (ArrayUtils.isEmpty(passphrase)) { diff --git a/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java b/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java index aff23c85a6d..b8d94ccaef7 100644 --- a/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java +++ b/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java @@ -823,7 +823,7 @@ public class QemuImg { * @param repair * Boolean option whether to repair any leaks */ - public String checkAndRepair(final QemuImgFile file, final QemuImageOptions imageOptions, final List<QemuObject> qemuObjects, final boolean repair) throws QemuImgException { + public String checkAndRepair(final QemuImgFile file, final QemuImageOptions imageOptions, final List<QemuObject> qemuObjects, final String repair) throws QemuImgException { final Script s = new Script(_qemuImgPath); s.add("check"); if (imageOptions == null) { @@ -840,9 +840,9 @@ public class QemuImg { s.add("--output=json"); - if (repair) { + if (StringUtils.isNotEmpty(repair)) { s.add("-r"); - s.add("all"); + s.add(repair); } OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser(); diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckVolumeAndRepairCommandWrapperTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckVolumeAndRepairCommandWrapperTest.java index ae0f75c76ca..dd7b6e0e2f7 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckVolumeAndRepairCommandWrapperTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckVolumeAndRepairCommandWrapperTest.java @@ -62,7 +62,7 @@ public class LibvirtCheckVolumeAndRepairCommandWrapperTest { CheckVolumeAndRepairCommand cmd = Mockito.mock(CheckVolumeAndRepairCommand.class); Mockito.when(cmd.getPath()).thenReturn("cbac516a-0f1f-4559-921c-1a7c6c408ccf"); - Mockito.when(cmd.needRepair()).thenReturn(false); + Mockito.when(cmd.getRepair()).thenReturn(null); StorageFilerTO spool = Mockito.mock(StorageFilerTO.class); Mockito.when(cmd.getPool()).thenReturn(spool); @@ -72,7 +72,6 @@ public class LibvirtCheckVolumeAndRepairCommandWrapperTest { Mockito.when(spool.getType()).thenReturn(Storage.StoragePoolType.PowerFlex); Mockito.when(spool.getUuid()).thenReturn("b6be258b-42b8-49a4-ad51-3634ef8ff76a"); Mockito.when(storagePoolMgr.getStoragePool(Storage.StoragePoolType.PowerFlex, "b6be258b-42b8-49a4-ad51-3634ef8ff76a")).thenReturn(pool); - Mockito.when(pool.connectPhysicalDisk("cbac516a-0f1f-4559-921c-1a7c6c408ccf", null)).thenReturn(true); KVMPhysicalDisk vol = Mockito.mock(KVMPhysicalDisk.class); Mockito.when(pool.getPhysicalDisk("cbac516a-0f1f-4559-921c-1a7c6c408ccf")).thenReturn(vol); @@ -93,7 +92,7 @@ public class LibvirtCheckVolumeAndRepairCommandWrapperTest { "}"; PowerMockito.whenNew(QemuImg.class).withArguments(Mockito.anyInt()).thenReturn(qemuImgMock); - Mockito.when(qemuImgMock.checkAndRepair(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean())).thenReturn(checkResult); // Replace with the desired result + Mockito.when(qemuImgMock.checkAndRepair(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(checkResult); CheckVolumeAndRepairAnswer result = (CheckVolumeAndRepairAnswer) libvirtCheckVolumeAndRepairCommandWrapperSpy.execute(cmd, libvirtComputingResourceMock); diff --git a/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/utils/qemu/QemuImgTest.java b/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/utils/qemu/QemuImgTest.java index aa74df57b24..b0981dde26e 100644 --- a/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/utils/qemu/QemuImgTest.java +++ b/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/utils/qemu/QemuImgTest.java @@ -377,7 +377,7 @@ public class QemuImgTest { try { QemuImg qemu = new QemuImg(0); - qemu.checkAndRepair(file, null, null, false); + qemu.checkAndRepair(file, null, null, null); } catch (QemuImgException e) { fail(e.getMessage()); } diff --git a/server/src/main/java/com/cloud/storage/CheckAndRepairVolumePayload.java b/server/src/main/java/com/cloud/storage/CheckAndRepairVolumePayload.java index 16a1531b1d6..6d06f2a4c36 100644 --- a/server/src/main/java/com/cloud/storage/CheckAndRepairVolumePayload.java +++ b/server/src/main/java/com/cloud/storage/CheckAndRepairVolumePayload.java @@ -19,16 +19,16 @@ package com.cloud.storage; public class CheckAndRepairVolumePayload { - public final boolean repair; + public final String repair; public String result; private String volumeCheckExecutionResult; private String volumeRepairedExecutionResult; - public CheckAndRepairVolumePayload(boolean repair) { + public CheckAndRepairVolumePayload(String repair) { this.repair = repair; } - public boolean isRepair() { + public String getRepair() { return repair; } diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 44b00f87b64..7edca6b6c9d 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -381,6 +381,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic public static ConfigKey<Long> storageTagRuleExecutionTimeout = new ConfigKey<>("Advanced", Long.class, "storage.tag.rule.execution.timeout", "2000", "The maximum runtime," + " in milliseconds, to execute a storage tag rule; if it is reached, a timeout will happen.", true); + public static final ConfigKey<Boolean> AllowVolumeCheckAndRepair = new ConfigKey<Boolean>("Hidden", Boolean.class, "volume.check.and.repair.before.instance.use", "true", + "To check and repair the volume if it has any leaks before performing any volume operation", true); + private final StateMachine2<Volume.State, Volume.Event, Volume> _volStateMachine; private static final Set<Volume.State> STATES_VOLUME_CANNOT_BE_DESTROYED = new HashSet<>(Arrays.asList(Volume.State.Destroy, Volume.State.Expunging, Volume.State.Expunged, Volume.State.Allocated)); @@ -1823,7 +1826,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic @ActionEvent(eventType = EventTypes.EVENT_VOLUME_CHECK, eventDescription = "checking volume and repair if needed", async = true) public Pair<String, String> checkAndRepairVolume(CheckVolumeAndRepairCmd cmd) throws ResourceAllocationException { long volumeId = cmd.getId(); - boolean repair = cmd.getRepair(); + String repair = cmd.getRepair(); final VolumeVO volume = _volsDao.findById(volumeId); validationsForCheckVolumeOperation(volume); @@ -1911,7 +1914,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } } - private Pair<String, String> orchestrateCheckVolumeAndRepair(Long volumeId, boolean repair) { + private Pair<String, String> orchestrateCheckVolumeAndRepair(Long volumeId, String repair) { VolumeInfo volume = volFactory.getVolume(volumeId); @@ -1929,7 +1932,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic return volService.checkAndRepairVolume(volume); } - public Outcome<Pair> checkVolumeAndRepairThroughJobQueue(final Long vmId, final Long volumeId, boolean repair) { + public Outcome<Pair> checkVolumeAndRepairThroughJobQueue(final Long vmId, final Long volumeId, String repair) { final CallContext context = CallContext.current(); final User callingUser = context.getCallingUser(); @@ -4996,7 +4999,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic @ReflectionUse private Pair<JobInfo.Status, String> orchestrateCheckVolumeAndRepair(VmWorkCheckAndRepairVolume work) throws Exception { Account account = _accountDao.findById(work.getAccountId()); - Pair<String, String> result = orchestrateCheckVolumeAndRepair(work.getVolumeId(), work.needRepair()); + Pair<String, String> result = orchestrateCheckVolumeAndRepair(work.getVolumeId(), work.getRepair()); return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(result)); } @@ -5036,7 +5039,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic AllowUserExpungeRecoverVolume, MatchStoragePoolTagsWithDiskOffering, UseHttpsToUpload, - WaitDetachDevice + WaitDetachDevice, + AllowVolumeCheckAndRepair }; } } diff --git a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java index fb3c842e6c0..bab5bdd20a9 100644 --- a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java +++ b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java @@ -1768,7 +1768,7 @@ public class VolumeApiServiceImplTest { CheckVolumeAndRepairCmd cmd = mock(CheckVolumeAndRepairCmd.class); when(cmd.getId()).thenReturn(1L); - when(cmd.getRepair()).thenReturn(false); + when(cmd.getRepair()).thenReturn(null); VolumeVO volume = mock(VolumeVO.class); when(volumeDaoMock.findById(1L)).thenReturn(volume);
