mirror of https://github.com/apache/cloudstack.git
Code refactored
This commit is contained in:
parent
baf02101bb
commit
61a63a9307
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue