package org.ovirt.engine.core.bll;
import java.util.ArrayList;
import java.util.List;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.job.ExecutionHandler;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.action.ProcessDownVmParameters;
import org.ovirt.engine.core.common.action.VdcActionType;
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.businessentities.VmExitStatus;
import org.ovirt.engine.core.common.vdscommands.DestroyVmVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.SetVmStatusVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase;
import org.ovirt.engine.core.di.Injector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Restart VMs running on Vds, that was stopped using PM or kdump was detected
* on it
*/
public class RestartVdsVmsOperation {
private static final Logger log = LoggerFactory.getLogger(RestartVdsVmsOperation.class);
/**
* Context of command, that instantiates this class
*/
private CommandContext commandContext;
/**
* VDS, that VMs was executed on
*/
private VDS vds;
/**
* Creates instance with specified params
*/
public RestartVdsVmsOperation(
CommandContext commandContext,
VDS vds
) {
this.commandContext = commandContext;
this.vds = vds;
}
/**
* Destroys VM migration to another host
* @param vm vm migrated to another host
*/
protected void destroyVmOnDestination(VM vm) {
if (vm.getStatus() == VMStatus.MigratingFrom) {
try {
if (vm.getMigratingToVds() != null) {
Backend.getInstance().getResourceManager().runVdsCommand(
VDSCommandType.DestroyVm,
new DestroyVmVDSCommandParameters(
new Guid(vm.getMigratingToVds().toString()),
vm.getId(),
false,
0
)
);
log.info(
"Stopped migrating vm '{}' on vds '{}'",
vm.getName(),
vm.getMigratingToVds()
);
}
} catch (RuntimeException ex) {
log.info(
"Could not stop migrating vm '{}' on vds '{}': {}",
vm.getName(),
vm.getMigratingToVds(),
ex.getMessage()
);
// intentionally ignored
}
}
}
/**
* Changes status of specified VMs to Down and starts HA VMs on another hosts
*
* @param vms list of VM to stopped/restarted
*/
public void restartVms(List<VM> vms) {
List<Guid> autoStartVmIdsToRerun = new ArrayList<>();
// restart all running vms of a failed vds.
for (VM vm : vms) {
destroyVmOnDestination(vm);
VDSReturnValue returnValue = Backend.getInstance().getResourceManager().runVdsCommand(
VDSCommandType.SetVmStatus,
new SetVmStatusVDSCommandParameters(
vm.getId(),
VMStatus.Down,
VmExitStatus.Error
)
);
// Write that this VM was shut down by host reboot or manual fence
if (returnValue != null && returnValue.getSucceeded()) {
new AuditLogDirector().log(
Injector.injectMembers(
new AuditLogableBase(
vds.getId(),
vm.getId()
)
),
AuditLogType.VM_WAS_SET_DOWN_DUE_TO_HOST_REBOOT_OR_MANUAL_FENCE
);
}
Backend.getInstance().runInternalAction(
VdcActionType.ProcessDownVm,
new ProcessDownVmParameters(vm.getId(), true),
ExecutionHandler.createDefaultContextForTasks(commandContext)
);
// Handle highly available VMs
if (vm.isAutoStartup()) {
autoStartVmIdsToRerun.add(vm.getId());
}
}
if (!autoStartVmIdsToRerun.isEmpty()) {
Injector.get(HaAutoStartVmsRunner.class).addVmsToRun(autoStartVmIdsToRerun);
}
}
}