package io.cattle.platform.process.agent; import static io.cattle.platform.core.model.tables.HostTable.*; import io.cattle.platform.core.constants.AccountConstants; import io.cattle.platform.core.constants.HostConstants; import io.cattle.platform.core.dao.HostDao; import io.cattle.platform.core.model.Account; import io.cattle.platform.core.model.Agent; import io.cattle.platform.core.model.Host; import io.cattle.platform.engine.handler.HandlerResult; import io.cattle.platform.engine.process.ProcessDefinition; import io.cattle.platform.engine.process.ProcessInstance; import io.cattle.platform.engine.process.ProcessState; import io.cattle.platform.engine.process.StateTransition; import io.cattle.platform.eventing.EventService; import io.cattle.platform.eventing.model.Event; import io.cattle.platform.eventing.model.EventVO; import io.cattle.platform.framework.event.FrameworkEvents; import io.cattle.platform.object.meta.ObjectMetaDataManager; import io.cattle.platform.object.util.DataAccessor; import io.cattle.platform.process.common.handler.AbstractObjectProcessPrePostListener; import io.cattle.platform.util.type.InitializationTask; import io.cattle.platform.util.type.Priority; import io.github.ibuildthecloud.gdapi.factory.SchemaFactory; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.inject.Named; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class AgentHostStateUpdate extends AbstractObjectProcessPrePostListener implements InitializationTask, Priority { private static final Logger log = LoggerFactory.getLogger(AgentHostStateUpdate.class); @Inject @Named("CoreSchemaFactory") SchemaFactory schemaFactory; @Inject List<ProcessDefinition> processDefinitions; @Inject EventService eventService; Map<String, String> transitioningToDone = new HashMap<>(); @Override public String[] getProcessNames() { return new String[] {"agent.*"}; } @Override protected HandlerResult preHandle(ProcessState state, ProcessInstance process) { for (Host host : objectManager.children(state.getResource(), Host.class)) { log.debug("Setting host [{}] agentState to [{}] on pre", host.getId(), state.getState()); setState(host, state.getState()); } return null; } @Override protected HandlerResult postHandle(ProcessState state, ProcessInstance process) { Agent agent = (Agent)state.getResource(); String newState = transitioningToDone.get(state.getState()); if (newState == null) { return null; } for (Host host : objectManager.children(agent, Host.class)) { log.debug("Setting host [{}] agentState to [{}] on post", host.getId(), newState); setState(host, newState); } return null; } protected void setState(Host host, String newState) { Map<Object, Object> props = new HashMap<>(); props.put(HOST.AGENT_STATE, newState); Account account = objectManager.loadResource(Account.class, host.getAccountId()); Long delay = DataAccessor.fieldLong(account, AccountConstants.FIELD_HOST_REMOVE_DELAY); if (delay == null && HostDao.HOST_REMOVE_DELAY.get() > -1) { delay = HostDao.HOST_REMOVE_DELAY.get(); } if (delay != null && delay > -1) { props.put(HOST.REMOVE_AFTER, new Date(System.currentTimeMillis() + delay * 1000)); } else { props.put(HOST.REMOVE_AFTER, null); } objectManager.setFields(host, objectManager.convertToPropertiesFor(host, props)); trigger(host); } protected void trigger(Host host) { Map<String, Object> data = new HashMap<>(); data.put(ObjectMetaDataManager.ACCOUNT_FIELD, host.getAccountId()); Event event = EventVO.newEvent(FrameworkEvents.STATE_CHANGE) .withData(data) .withResourceType(HostConstants.TYPE) .withResourceId(host.getId().toString()); eventService.publish(event); } @Override public void start() { String type = schemaFactory.getSchemaName(Agent.class); if (type == null) { return; } for (ProcessDefinition def : processDefinitions) { if (!type.equals(def.getResourceType())) { continue; } for (StateTransition transition : def.getStateTransitions()) { if (transition.getType() == StateTransition.Style.DONE) { transitioningToDone.put(transition.getFromState(), transition.getToState()); } } } } @Override public int getPriority() { return Integer.MAX_VALUE; } public List<ProcessDefinition> getProcessDefinitions() { return processDefinitions; } @Inject public void setProcessDefinitions(List<ProcessDefinition> processDefinitions) { this.processDefinitions = processDefinitions; } }