package org.ovirt.engine.core.bll.hostdeploy; import java.util.Collections; import java.util.Map; import javax.inject.Inject; import org.ovirt.engine.core.bll.LockMessagesMatchUtil; import org.ovirt.engine.core.bll.NonTransactiveCommandAttribute; import org.ovirt.engine.core.bll.VdsCommand; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.host.HostConnectivityChecker; import org.ovirt.engine.core.bll.host.HostUpgradeManager; import org.ovirt.engine.core.bll.host.Updateable; import org.ovirt.engine.core.bll.hostedengine.HostedEngineHelper; import org.ovirt.engine.core.bll.job.ExecutionHandler; import org.ovirt.engine.core.bll.validator.UpgradeHostValidator; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.action.VdsActionParameters; import org.ovirt.engine.core.common.action.hostdeploy.InstallVdsParameters; import org.ovirt.engine.core.common.action.hostdeploy.UpgradeHostParameters; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.VDSType; import org.ovirt.engine.core.common.businessentities.VdsDynamic; import org.ovirt.engine.core.common.errors.EngineMessage; import org.ovirt.engine.core.common.locks.LockingGroup; import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dao.VdsDynamicDao; @NonTransactiveCommandAttribute public class UpgradeHostInternalCommand<T extends UpgradeHostParameters> extends VdsCommand<T> { @Inject private HostedEngineHelper hostedEngineHelper; @Inject private VdsDynamicDao vdsDynamicDao; private boolean haMaintenanceFailed; /** * C'tor for compensation purposes * * @param commandId * the command id */ public UpgradeHostInternalCommand(Guid commandId) { super(commandId); } public UpgradeHostInternalCommand(T parameters, CommandContext cmdContext) { super(parameters, cmdContext); } @Override protected boolean validate() { UpgradeHostValidator validator = new UpgradeHostValidator(getVds()); return validate(validator.hostExists()) && validate(validator.statusSupportedForHostUpgradeInternal()); } @Override protected void executeCommand() { getCompensationContext().snapshotEntityStatus(getVds().getDynamicData(), getParameters().getInitialStatus()); getCompensationContext().stateChanged(); VDSType vdsType = getVds().getVdsType(); if (vdsType == VDSType.VDS || vdsType == VDSType.oVirtNode) { try { setVdsStatus(VDSStatus.Installing); Updateable upgradeManager = new HostUpgradeManager(); upgradeManager.update(getVds()); if (vdsType == VDSType.oVirtNode) { VdsActionParameters params = new VdsActionParameters(getVds().getId()); params.setPrevVdsStatus(getParameters().getInitialStatus()); VdcReturnValueBase returnValue = runInternalAction(VdcActionType.SshHostReboot, params, ExecutionHandler.createInternalJobContext()); if (!returnValue.getSucceeded()) { setVdsStatus(VDSStatus.InstallFailed); log.error("Engine failed to restart via ssh ovirt-node host '{}' ('{}') after upgrade", getVds().getName(), getVds().getId()); return; } } else { // letting the host a chance to recover from restarting the VDSM service after the upgrade if (!new HostConnectivityChecker().check(getVds())) { log.warn( "Engine failed to communicate with VDSM agent on host '{}' with address '{}' ('{}') " + "after upgrade", getVds().getName(), getVds().getHostName(), getVds().getId()); } } } catch (Exception e) { setVdsStatus(VDSStatus.InstallFailed); return; } } else if (getVds().isOvirtVintageNode()) { InstallVdsParameters parameters = new InstallVdsParameters(getVdsId()); parameters.setIsReinstallOrUpgrade(true); parameters.setoVirtIsoFile(getParameters().getoVirtIsoFile()); parameters.setActivateHost(getParameters().getInitialStatus() == VDSStatus.Up); VdcReturnValueBase result = runInternalAction(VdcActionType.UpgradeOvirtNodeInternal, parameters); if (!result.getSucceeded()) { setVdsStatus(VDSStatus.InstallFailed); propagateFailure(result); return; } } try { updateHostStatusAfterSuccessfulUpgrade(); setSucceeded(true); } catch (Exception e) { log.error("Failed to set new status for host '{}' after upgrade has ended.", getVdsName()); log.error("Exception", e); setVdsStatus(VDSStatus.InstallFailed); } } public void updateHostStatusAfterSuccessfulUpgrade() { VdsDynamic dynamicHostData = vdsDynamicDao.get(getVdsId()); dynamicHostData.setUpdateAvailable(false); vdsDynamicDao.update(dynamicHostData); if (getVds().getVdsType() == VDSType.VDS) { if (getParameters().getInitialStatus() == VDSStatus.Maintenance) { setVdsStatus(VDSStatus.Maintenance); } else { if (getVds().getHighlyAvailableIsConfigured()) { haMaintenanceFailed = !hostedEngineHelper.updateHaLocalMaintenanceMode(getVds(), false); } setVdsStatus(VDSStatus.Initializing); } } } @Override protected Map<String, Pair<String, String>> getExclusiveLocks() { return Collections.singletonMap(getVdsId().toString(), LockMessagesMatchUtil.makeLockingPair(LockingGroup.VDS, EngineMessage.ACTION_TYPE_FAILED_OBJECT_LOCKED)); } @Override protected void setActionMessageParameters() { addValidationMessage(EngineMessage.VAR__ACTION__UPGRADE); addValidationMessage(EngineMessage.VAR__TYPE__HOST); } @Override public AuditLogType getAuditLogTypeValue() { if(getSucceeded()){ return haMaintenanceFailed ? AuditLogType.HOST_UPGRADE_FINISHED_MANUAL_HA : AuditLogType.HOST_UPGRADE_FINISHED; } return AuditLogType.HOST_UPGRADE_FAILED; } }