package org.ovirt.engine.core.vdsbroker; import java.util.concurrent.TimeUnit; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.vdscommands.MigrateVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; 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.TransactionScopeOption; import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation; import org.ovirt.engine.core.utils.timer.SchedulerUtilQuartzImpl; import org.ovirt.engine.core.utils.transaction.TransactionMethod; import org.ovirt.engine.core.utils.transaction.TransactionSupport; import org.ovirt.engine.core.vdsbroker.vdsbroker.MigrateBrokerVDSCommand; public class MigrateVDSCommand<P extends MigrateVDSCommandParameters> extends VdsIdVDSCommandBase<P> { public MigrateVDSCommand(P parameters) { super(parameters); } @Override protected void ExecuteVdsIdCommand() { MigrateVDSCommandParameters parameters = getParameters(); if (_vdsManager != null) { VMStatus retval; MigrateBrokerVDSCommand<MigrateVDSCommandParameters> command = new MigrateBrokerVDSCommand<MigrateVDSCommandParameters>(parameters); command.Execute(); VDSReturnValue vdsReturnValue = command.getVDSReturnValue(); if (vdsReturnValue.getSucceeded()) { retval = VMStatus.MigratingFrom; } else { log.error("VDS::migrate:: Failed migration setting vm status to ERROR"); retval = VMStatus.NotResponding; getVDSReturnValue().setSucceeded(false); getVDSReturnValue().setVdsError(vdsReturnValue.getVdsError()); getVDSReturnValue().setExceptionString(vdsReturnValue.getExceptionString()); getVDSReturnValue().setExceptionObject(vdsReturnValue.getExceptionObject()); } // update the db // VM vm = _vdsManager.VmDict[parameters.VmId]; final VM vm = DbFacade.getInstance().getVmDAO().getById(parameters.getVmId()); ResourceManager.getInstance().InternalSetVmStatus(vm, retval); if (retval == VMStatus.MigratingFrom) { vm.setmigrating_to_vds(parameters.getDstVdsId()); // get vdsEventListener from callback channel (if wcf-user backend) or resource manager if (ResourceManager.getInstance().getBackendCallback() != null) { ResourceManager.getInstance().AddAsyncRunningVm(parameters.getVmId(), ResourceManager.getInstance().getBackendCallback()); } } TransactionSupport.executeInNewTransaction(new TransactionMethod<Void>() { @Override public Void runInTransaction() { DbFacade.getInstance().getVmDynamicDAO().update(vm.getDynamicData()); return null; } }); if (retval == VMStatus.MigratingFrom) { UpdateDestinationVdsThreaded(parameters.getDstVdsId(), vm); } getVDSReturnValue().setReturnValue(retval); } else { getVDSReturnValue().setSucceeded(false); } } private void UpdateDestinationVdsThreaded(Guid dstVdsId, VM vm) { VdsManager vdsManager = ResourceManager.getInstance().GetVdsManager(dstVdsId); if (vdsManager != null) { // TODO use thread pool Class<?>[] inputTypes = new Class[] { VdsManager.class, VM.class }; Object[] inputParams = new Object[] { vdsManager, vm }; SchedulerUtilQuartzImpl.getInstance().scheduleAOneTimeJob(this, "UpdateDestinationVdsOnTimer", inputTypes, inputParams, 0, TimeUnit.MILLISECONDS); } } @OnTimerMethodAnnotation("UpdateDestinationVdsOnTimer") public void UpdateDestinationVdsOnTimer(final VdsManager vdsManager, final VM vm) { synchronized (vdsManager.getLockObj()) { TransactionSupport.executeInScope(TransactionScopeOption.Suppress, new TransactionMethod<Object>() { @Override public Object runInTransaction() { VDS vds = null; try { vds = DbFacade.getInstance().getVdsDAO().get(vdsManager.getVdsId()); // VB & C# TO JAVA CONVERTER TODO TASK: // Arithmetic operations involving nullable type // instances are not converted to null-value // logic: vds.setvm_count(vds.getvm_count() + 1); vds.setpending_vcpus_count(vds.getpending_vcpus_count() + vm.getnum_of_cpus()); vds.setpending_vmem_size(vds.getpending_vmem_size() + vm.getMinAllocatedMem()); if (log.isDebugEnabled()) { log.debugFormat( "IncreasePendingVms::MigrateVm Increasing vds {0} pending vcpu count, now {1}, and pending vmem size, now {2}. Vm: {3}", vds.getvds_name(), vds.getpending_vcpus_count(), vds.getpending_vmem_size(), vm.getvm_name()); } vdsManager.UpdateDynamicData(vds.getDynamicData()); } catch (RuntimeException ex) { if (vds == null) { log.fatalFormat( "VDS::migrate:: Could not update destination vds commited memory to db. vds {0} : was not find, error: {1}, {2}", vdsManager.getVdsId(), ex.toString(), ex.getStackTrace()[0]); } else { log.fatalFormat( "VDS::migrate:: Could not update destination vds commited memory to db. vds {0} : {1}, error: {2}, {3}", vds.getvds_id(), vds.getvds_name(), ex.toString(), ex.getStackTrace()[0]); } } return null; } }); } } private static LogCompat log = LogFactoryCompat.getLog(MigrateVDSCommand.class); }