Code refactored

This commit is contained in:
Harikrishna Patnala 2024-02-01 12:28:40 +05:30
parent baf02101bb
commit 61a63a9307
3 changed files with 140 additions and 92 deletions

View File

@ -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);
}

View File

@ -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);
CheckAndRepairVolumeAnswer answer = checkVolume(vol, command, serverResource);
String checkVolumeResult = answer.getVolumeCheckExecutionResult();
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 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)) {

View File

@ -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);
}
}
// retrieve the entity url from job result
if (jobResult != null && jobResult instanceof Pair) {
return (Pair<String, String>) jobResult;
}
return null;
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 {
CheckAndRepairVolumePayload payload = new CheckAndRepairVolumePayload(repair);
VolumeInfo volumeInfo = volFactory.getVolume(volumeId);
volumeInfo.addPayload(payload);
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);
}
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);
}
}
// retrieve the entity url from job result
if (jobResult != null && jobResult instanceof Pair) {
return (Pair<String, String>) 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<String, String> orchestrateCheckAndRepairVolume(Long volumeId, String repair) {
VolumeInfo volume = volFactory.getVolume(volumeId);