package org.ovirt.engine.core.vdsbroker;
import java.util.concurrent.TimeUnit;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.VMStatus;
import org.ovirt.engine.core.common.businessentities.VmDynamic;
import org.ovirt.engine.core.common.vdscommands.CreateVmVDSCommandParameters;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.compat.LogCompat;
import org.ovirt.engine.core.compat.LogFactoryCompat;
import org.ovirt.engine.core.compat.StringHelper;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.utils.ThreadUtils;
import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation;
import org.ovirt.engine.core.utils.timer.SchedulerUtilQuartzImpl;
import org.ovirt.engine.core.vdsbroker.vdsbroker.CreateVDSCommand;
import org.ovirt.engine.core.vdsbroker.vdsbroker.CreateVmFromSysPrepVDSCommand;
import org.ovirt.engine.core.vdsbroker.vdsbroker.CreateVmFromSysPrepVDSCommandParameters;
import org.ovirt.engine.core.vdsbroker.vdsbroker.VDSGenericException;
public class CreateVmVDSCommand<P extends CreateVmVDSCommandParameters> extends VdsIdVDSCommandBase<P> {
public CreateVmVDSCommand(P parameters) {
super(parameters);
}
@Override
protected void ExecuteVdsIdCommand() {
CreateVDSCommand<?> command = null;
try {
if (_vdsManager != null) {
VM vm = getParameters().getVm();
if (CanExecute()) {
boolean canExecute = true;
if (ResourceManager.getInstance().getBackendCallback() != null) {
canExecute = ResourceManager.getInstance().AddAsyncRunningVm(
vm.getvm_guid(),
ResourceManager.getInstance().getBackendCallback());
}
if (canExecute) {
if (vm.useSysPrep() && vm.getvm_os().isWindows()
&& StringHelper.isNullOrEmpty(vm.getFloppyPath())) {
// use answer file to run after sysprep.
CreateVmFromSysPrepVDSCommandParameters createVmFromSysPrepParam =
new CreateVmFromSysPrepVDSCommandParameters(
getVdsId(),
vm,
vm.getvm_name(),
vm.getvm_domain());
createVmFromSysPrepParam.setSysPrepParams(getParameters().getSysPrepParams());
command =
new CreateVmFromSysPrepVDSCommand<CreateVmFromSysPrepVDSCommandParameters>(createVmFromSysPrepParam);
command.Execute();
if (command.getVDSReturnValue().getSucceeded()) {
vm.setis_initialized(true);
saveSetInitializedToDbThreaded();
} else {
HandleCommandResult(command);
}
} else {
// normal run.
command = new CreateVDSCommand<CreateVmVDSCommandParameters>(getParameters());
command.Execute();
HandleCommandResult(command);
vm.setis_initialized(true);
saveSetInitializedToDbThreaded();
}
if (command.getVDSReturnValue().getSucceeded()) {
HandleVdsInformation();
vm.setrun_on_vds(getVdsId());
DbFacade.getInstance().getVmDynamicDAO().update(vm.getDynamicData());
} else {
ResourceManager.getInstance().RemoveAsyncRunningVm(getParameters().getVmId());
}
}
}
getVDSReturnValue().setReturnValue(vm.getstatus());
} else {
getVDSReturnValue().setSucceeded(false);
}
} catch (java.lang.Exception e) {
log.error("Error in excuting CreateVmVDSCommand", e);
if (command == null || !command.getVDSReturnValue().getSucceeded()) {
ResourceManager.getInstance().RemoveAsyncRunningVm(getParameters().getVmId());
}
throw new RuntimeException(e);
}
}
private void HandleVdsInformation() {
// VB & C# TO JAVA CONVERTER TODO TASK: Arithmetic operations involving
// nullable type instances are not converted to null-value logic:
getVds().setmem_commited(getVds().getmem_commited() + getParameters().getVm().getvm_mem_size_mb());
// VB & C# TO JAVA CONVERTER TODO TASK: Arithmetic operations involving
// nullable type instances are not converted to null-value logic:
getVds().setmem_commited(getVds().getmem_commited() + getVds().getguest_overhead());
// VB & C# TO JAVA CONVERTER TODO TASK: Arithmetic operations involving
// nullable type instances are not converted to null-value logic:
getVds().setvm_count(getVds().getvm_count() + 1);
// VB & C# TO JAVA CONVERTER TODO TASK: Arithmetic operations involving
// nullable type instances are not converted to null-value logic:
getVds().setvms_cores_count(getVds().getvms_cores_count() + getParameters().getVm().getnum_of_cpus());
// VB & C# TO JAVA CONVERTER TODO TASK: Arithmetic operations involving
// nullable type instances are not converted to null-value logic:
getVds().setpending_vcpus_count(
getVds().getpending_vcpus_count() + getParameters().getVm().getnum_of_cpus());
getVds().setpending_vmem_size(
getVds().getpending_vmem_size() + getParameters().getVm().getMinAllocatedMem());
log.infoFormat("IncreasePendingVms::CreateVmIncreasing vds {0} pending vcpu count, now {1}. Vm: {2}", getVds()
.getvds_name(), getVds().getpending_vcpus_count(), getParameters().getVm().getvm_name());
SaveVdsDynamicToDBThreaded(getVds(), getParameters().getVm());
_vdsManager.UpdateDynamicData(getVds().getDynamicData());
}
private boolean CanExecute() {
Guid guid = getParameters().getVm().getvm_guid();
String vmName = getParameters().getVm().getvm_name();
if (ResourceManager.getInstance().IsVmDuringInitiating(getParameters().getVm().getvm_guid())) {
log.infoFormat("Vm Running failed - vm {0}:{1} already running", guid, vmName);
getVDSReturnValue().setReturnValue(VMStatus.Up);
return false;
} else {
VmDynamic vmDynamicFromDb = DbFacade.getInstance().getVmDynamicDAO().get(guid);
VMStatus vmStatus = vmDynamicFromDb.getstatus();
if (vmStatus == VMStatus.ImageLocked) {
log.infoFormat("Vm Running failed - vm {0}:{1} - cannot run vm when image is locked", guid, vmName);
return false;
}
if (vmDynamicFromDb.getstatus() != VMStatus.Down && vmDynamicFromDb.getstatus() != VMStatus.Suspended) {
log.infoFormat("Vm Running failed - vm {0}:{1} already running, status {2}", guid, vmName, vmStatus);
getVDSReturnValue().setReturnValue(vmDynamicFromDb.getstatus());
return false;
}
}
// if (_vdsManager.VmDict.ContainsKey(CreateVmParameters.Vm.vm_guid))
// {
// VDSReturnValue.ReturnValue =
// _vdsManager.VmDict[CreateVmParameters.Vm.vm_guid].status;
// return false;
// }
return true;
}
private void HandleCommandResult(CreateVDSCommand<?> command) {
if (!command.getVDSReturnValue().getSucceeded() && command.getVDSReturnValue().getExceptionObject() != null) {
if (command.getVDSReturnValue().getExceptionObject() instanceof VDSGenericException) {
log.errorFormat("VDS::create Failed creating vm '{0}' in vds = {1} : {2} error = {3}",
getParameters().getVm().getvm_name(), getVds().getvds_id(), getVds().getvds_name(),
command.getVDSReturnValue().getExceptionString());
getVDSReturnValue().setReturnValue(VMStatus.Down);
getVDSReturnValue().setSucceeded(false);
getVDSReturnValue().setVdsError(command.getVDSReturnValue().getVdsError());
} else {
throw command.getVDSReturnValue().getExceptionObject();
}
}
}
private void saveSetInitializedToDbThreaded() {
// TODO use thread pool
SchedulerUtilQuartzImpl.getInstance().scheduleAOneTimeJob(this, "saveSetInitializedToDbOnTimer", new Class[0],
new Object[0], 0, TimeUnit.MILLISECONDS);
}
@OnTimerMethodAnnotation("saveSetInitializedToDbOnTimer")
public void saveSetInitializedToDbOnTimer() {
for (int i = 1; i < 6; i++) {
try {
DbFacade.getInstance().SaveIsInitialized(getParameters().getVm().getStaticData().getId(),
getParameters().getVm().getStaticData().getis_initialized());
return;
} catch (RuntimeException ex) {
log.infoFormat(
"VDS::Failed save vm static to DB, try number {4}. vm: {0} in vds = {1} : {2} error = {3}",
getParameters().getVm().getvm_name(), getVds().getvds_id(), getVds().getvds_name(),
ex.getMessage(), i);
ThreadUtils.sleep(1000);
}
}
log.errorFormat("VDS::Failed save vm static to DB. vm: {0} in vds = {1} : {2}.", getParameters()
.getVm().getvm_name(), getVds().getvds_id(), getVds().getvds_name());
}
private static LogCompat log = LogFactoryCompat.getLog(CreateVmVDSCommand.class);
}