package org.ovirt.engine.core.bll; import java.util.List; import javax.ejb.Local; import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import org.ovirt.engine.core.bll.storage.StoragePoolStatusHandler; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.action.FenceVdsActionParameters; import org.ovirt.engine.core.common.action.MigrateVmToServerParameters; import org.ovirt.engine.core.common.action.PowerClientMigrateOnConnectCheckParameters; import org.ovirt.engine.core.common.action.ReconstructMasterParameters; import org.ovirt.engine.core.common.action.RunVmParams; import org.ovirt.engine.core.common.action.SetNonOperationalVdsParameters; import org.ovirt.engine.core.common.action.SetStoragePoolStatusParameters; import org.ovirt.engine.core.common.action.StorageDomainPoolParametersBase; import org.ovirt.engine.core.common.action.StoragePoolParametersBase; import org.ovirt.engine.core.common.action.VdcActionParametersBase; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdsActionParameters; import org.ovirt.engine.core.common.businessentities.FenceActionType; import org.ovirt.engine.core.common.businessentities.IVdsAsyncCommand; import org.ovirt.engine.core.common.businessentities.IVdsEventListener; import org.ovirt.engine.core.common.businessentities.NonOperationalReason; import org.ovirt.engine.core.common.businessentities.StoragePoolStatus; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VmDynamic; import org.ovirt.engine.core.common.businessentities.VmStatic; import org.ovirt.engine.core.common.businessentities.storage_pool; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.errors.VdcBllErrors; import org.ovirt.engine.core.common.vdscommands.SetVmTicketVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.StartSpiceVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; 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.compat.TransactionScopeOption; import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.utils.Helper; import org.ovirt.engine.core.utils.ThreadUtils; import org.ovirt.engine.core.utils.Ticketing; import org.ovirt.engine.core.utils.linq.Function; import org.ovirt.engine.core.utils.linq.LinqUtils; import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil; @Stateless(name = "VdsEventListener") @TransactionAttribute(TransactionAttributeType.SUPPORTS) @Local(IVdsEventListener.class) public class VdsEventListener implements IVdsEventListener { @Override public void VdsMovedToMaintanance(Guid vdsId) { //VDS vds = DbFacade.getInstance().getVdsDAO().get(vdsId); //MaintananceVdsCommand.ProcessStorageOnVdsInactive(vds); } @Override public void StorageDomainNotOperational(Guid storageDomainId, Guid storagePoolId) { Backend.getInstance().runInternalAction(VdcActionType.HandleFailedStorageDomain, new StorageDomainPoolParametersBase(storageDomainId, storagePoolId)); } @Override public void MasterDomainNotOperational(Guid storageDomainId, Guid storagePoolId) { VdcActionParametersBase parameters = new ReconstructMasterParameters(storagePoolId, storageDomainId, false); parameters.setTransactionScopeOption(TransactionScopeOption.RequiresNew); Backend.getInstance().runInternalAction(VdcActionType.ReconstructMasterDomain, parameters); } @Override public void ProcessOnVmStop(Guid vmId) { VmPoolHandler.ProcessVmPoolOnStopVm(vmId); /** * Vitaly wating for Vm.ExitStatus in DB. * //HighAvailableVmsDirector.TryRunHighAvailableVmsOnVmDown(vmId); */ } @Override public void VdsNonOperational(Guid vdsId, NonOperationalReason reason, boolean logCommand, boolean saveToDb, Guid domainId) { SetNonOperationalVdsParameters tempVar = new SetNonOperationalVdsParameters(vdsId, reason); tempVar.setSaveToDb(saveToDb); tempVar.setStorageDomainId(domainId); tempVar.setShouldBeLogged(logCommand); Backend.getInstance().runInternalAction(VdcActionType.SetNonOperationalVds, tempVar); } @Override public void VdsNotResponding(final VDS vds) { ThreadPoolUtil.execute(new Runnable() { @Override public void run() { log.infoFormat("ResourceManager::vdsNotResponding entered for Host {0}, {1}", vds.getvds_id(), vds.gethost_name()); Backend.getInstance().runInternalAction(VdcActionType.VdsNotRespondingTreatment, new FenceVdsActionParameters(vds.getvds_id(), FenceActionType.Restart)); } }); } @Override public void VdsUpEvent(final Guid vdsId) { StoragePoolParametersBase tempVar = new StoragePoolParametersBase(Guid.Empty); tempVar.setVdsId(vdsId); if (Backend.getInstance().runInternalAction(VdcActionType.InitVdsOnUp, tempVar).getSucceeded()) { ThreadPoolUtil.execute(new Runnable() { @Override public void run() { try { // migrate vms that its their default vds and failback // is on List<VmStatic> vmsToMigrate = DbFacade.getInstance().getVmStaticDAO().getAllWithFailbackByVds(vdsId); java.util.ArrayList<VdcActionParametersBase> vmToServerParametersList = Helper.ToList(LinqUtils .foreach(vmsToMigrate, new Function<VmStatic, VdcActionParametersBase>() { @Override public VdcActionParametersBase eval(VmStatic vm) { MigrateVmToServerParameters parameters = new MigrateVmToServerParameters(false, vm.getId(), vdsId); parameters.setShouldBeLogged(false); return parameters; } })); Backend.getInstance().runInternalMultipleActions(VdcActionType.MigrateVmToServer, vmToServerParametersList); // LINQ 29456 // Backend.getInstance().RunMultipleActions(VdcActionType.MigrateVmToServer, // vmsToMigrate.Select<VmStatic, // VdcActionParametersBase>( // a => new MigrateVmToServerParameters(a.vm_guid, // vdsId)).ToList()); // run dedicated vm logic // not passing clientinfo will cause to launch on a VDS // instead of power client. this is a possible use case // to fasten the inital boot, then live migrate to power // client on spice connect. /** * Vitaly wating for Vm.ExitStatus in DB. * //HighAvailableVmsDirector * .TryRunHighAvailableVdsUp(vdsId); */ List<VM> vms = DbFacade.getInstance().getVmDAO().getAllForDedicatedPowerClientByVds(vdsId); if (vms.size() != 0) { if (Config .<Boolean> GetValue(ConfigValues.PowerClientDedicatedVmLaunchOnVdsWhilePowerClientStarts)) { Backend.getInstance().runInternalAction(VdcActionType.RunVmOnDedicatedVds, new RunVmParams(vms.get(0).getvm_guid(), vdsId)); } else { ThreadUtils.sleep(10000); Backend.getInstance().runInternalAction(VdcActionType.RunVmOnPowerClient, new RunVmParams(vms.get(0).getvm_guid(), vdsId)); } } } catch (RuntimeException e) { log.errorFormat("Failed to initialize Vds on up. Error: {0}", e); } } }); } } @Override public void ProcessOnClientIpChange(final VDS vds, final Guid vmId) { final VmDynamic vmDynamic = DbFacade.getInstance().getVmDynamicDAO().get(vmId); // when a spice client connects to the VM, we need to check if the // client is local or remote to adjust compression and migration aspects // we first check if we need to disable/enable compression for power // clients, so we won't need to handle migration errors if (!StringHelper.isNullOrEmpty(vmDynamic.getclient_ip())) { ThreadPoolUtil.execute(new Runnable() { @Override public void run() { RunVmCommandBase.DoCompressionCheck(vds, vmDynamic); // Run PowerClientMigrateOnConnectCheck if configured. if (Config.<Boolean> GetValue(ConfigValues.PowerClientAutoMigrateToPowerClientOnConnect) || Config.<Boolean> GetValue(ConfigValues.PowerClientAutoMigrateFromPowerClientToVdsWhenConnectingFromRegularClient)) { Backend.getInstance().runInternalAction( VdcActionType.PowerClientMigrateOnConnectCheck, new PowerClientMigrateOnConnectCheckParameters(false, vmDynamic.getId(), vmDynamic .getclient_ip(), vds.getvds_id())); } } }); } // in case of empty clientIp we clear the logged in user. // (this happened when user close the console to spice/vnc) else { vmDynamic.setguest_cur_user_id(null); vmDynamic.setguest_cur_user_name(null); DbFacade.getInstance().getVmDynamicDAO().update(vmDynamic); } } @Override public void ProcessOnCpuFlagsChange(Guid vdsId) { // Backend.getInstance().runInternalAction(VdcActionType.HandleVdsCpuFlagsOrClusterChanged, // new VdsActionParameters(vdsId)); Backend.getInstance().runInternalAction(VdcActionType.HandleVdsVersion, new VdsActionParameters(vdsId)); } @Override public void ProcessOnVmPoweringUp(Guid vds_id, Guid vmid, String display_ip, int display_port) { IVdsAsyncCommand command = Backend.getInstance().getResourceManager().GetAsyncCommandForVm(vmid); if (command != null && command.getAutoStart() && command.getAutoStartVdsId() != null) { try { String otp64 = Ticketing.GenerateOTP(); Backend.getInstance() .getResourceManager() .RunVdsCommand(VDSCommandType.SetVmTicket, new SetVmTicketVDSCommandParameters(vds_id, vmid, otp64, 60)); log.infoFormat( "VdsEventListener.ProcessOnVmPoweringUp - Auto start logic, starting spice to vm - {0} ", vmid); Backend.getInstance() .getResourceManager() .RunVdsCommand( VDSCommandType.StartSpice, new StartSpiceVDSCommandParameters(command.getAutoStartVdsId(), display_ip, display_port, otp64)); } catch (RuntimeException ex) { log.errorFormat( "VdsEventListener.ProcessOnVmPoweringUp - failed to start spice on VM - {0} - {1} - {2}", vmid, ex.getMessage(), ex.getStackTrace()); } } } @Override public void StoragePoolUpEvent(storage_pool storagePool, boolean isNewSpm) { if (isNewSpm) { AsyncTaskManager.getInstance().StopStoragePoolTasks(storagePool); } { AsyncTaskManager.getInstance().AddStoragePoolExistingTasks(storagePool); } } @Override public void StoragePoolStatusChange(Guid storagePoolId, StoragePoolStatus status, AuditLogType auditLogType, VdcBllErrors error) { StoragePoolStatusChange(storagePoolId, status, auditLogType, error, null); } @Override public void StoragePoolStatusChange(Guid storagePoolId, StoragePoolStatus status, AuditLogType auditLogType, VdcBllErrors error, TransactionScopeOption transactionScopeOption) { SetStoragePoolStatusParameters tempVar = new SetStoragePoolStatusParameters(storagePoolId, status, auditLogType); tempVar.setError(error); if (transactionScopeOption != null) { tempVar.setTransactionScopeOption(transactionScopeOption); } Backend.getInstance().runInternalAction(VdcActionType.SetStoragePoolStatus, tempVar); } @Override public void StoragePoolStatusChanged(Guid storagePoolId, StoragePoolStatus status) { StoragePoolStatusHandler.PoolStatusChanged(storagePoolId, status); } @Override public void RunFailedAutoStartVM(Guid vmId) { Backend.getInstance().runInternalAction(VdcActionType.RunVm, new RunVmParams(vmId)); } @Override public boolean RestartVds(Guid vdsId) { return Backend .getInstance() .runInternalAction(VdcActionType.RestartVds, new FenceVdsActionParameters(vdsId, FenceActionType.Restart)).getSucceeded(); } @Override public void Rerun(Guid vmId) { IVdsAsyncCommand command = Backend.getInstance().getResourceManager().GetAsyncCommandForVm(vmId); if (command != null) { command.Rerun(); } } @Override public void RunningSucceded(Guid vmId) { IVdsAsyncCommand command = Backend.getInstance().getResourceManager().GetAsyncCommandForVm(vmId); if (command != null) { command.RunningSucceded(); } } @Override public void RemoveAsyncRunningCommand(Guid vmId) { Backend.getInstance().getResourceManager().RemoveAsyncRunningCommand(vmId); } private static LogCompat log = LogFactoryCompat.getLog(VdsEventListener.class); }