package io.cattle.platform.process.externalevent; import io.cattle.platform.allocator.constraint.HostAffinityConstraint; import io.cattle.platform.allocator.service.AllocationHelper; import io.cattle.platform.core.constants.ExternalEventConstants; import io.cattle.platform.core.constants.InstanceConstants; import io.cattle.platform.core.dao.InstanceDao; import io.cattle.platform.core.model.ExternalEvent; import io.cattle.platform.core.model.Host; import io.cattle.platform.core.model.Instance; import io.cattle.platform.engine.handler.HandlerResult; import io.cattle.platform.engine.process.ProcessInstance; import io.cattle.platform.engine.process.ProcessState; import io.cattle.platform.engine.process.impl.ProcessCancelException; import io.cattle.platform.object.process.ObjectProcessManager; import io.cattle.platform.object.resource.ResourceMonitor; import io.cattle.platform.object.resource.ResourcePredicate; import io.cattle.platform.object.util.DataAccessor; import io.cattle.platform.process.common.handler.AbstractObjectProcessHandler; import io.cattle.platform.process.common.util.ProcessUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.inject.Named; import org.apache.commons.lang3.StringUtils; @Named public class ExternalHostEventCreate extends AbstractObjectProcessHandler { @Inject AllocationHelper allocationHelper; @Inject InstanceDao instanceDao; @Inject ObjectProcessManager processManager; @Inject ResourceMonitor resourceMonitor; @Override public HandlerResult handle(ProcessState state, ProcessInstance process) { ExternalEvent event = (ExternalEvent)state.getResource(); if (!ExternalEventConstants.KIND_EXTERNAL_HOST_EVENT.equals(event.getKind()) || !ExternalEventConstants.TYPE_HOST_EVACUATE.equals(event.getEventType())) { return null; } boolean delete = DataAccessor.fieldBool(event, ExternalEventConstants.FIELD_DELETE_HOST); List<Long> hosts = getHosts(event); for (long hostId : hosts) { Host host = objectManager.loadResource(Host.class, hostId); if (host == null) { continue; } try { deactivateHost(state, host); } catch (ProcessCancelException e) { } if (delete) { host = objectManager.reload(host); try { remove(host, state.getData()); } catch (ProcessCancelException e) { } host = objectManager.reload(host); purge(host, state.getData()); } } return null; } protected List<Long> getHosts(ExternalEvent event) { List<Long> hosts = new ArrayList<>(); String label = DataAccessor.fieldString(event, ExternalEventConstants.FIELD_HOST_LABEL); if (StringUtils.isNotBlank(label)) { Map<String, String> labels = new HashMap<>(); labels.put(HostAffinityConstraint.LABEL_HEADER_AFFINITY_HOST_LABEL, DataAccessor.fieldString(event, ExternalEventConstants.FIELD_HOST_LABEL)); hosts.addAll(allocationHelper.getAllHostsSatisfyingHostAffinity(event.getAccountId(), labels)); } Long hostId = DataAccessor.fieldLong(event, ExternalEventConstants.FIELD_HOST_ID); if (hostId != null) { hosts.add(hostId); } return hosts; } protected void deactivateHost(ProcessState state, Host host) { deactivate(host, null); List<? extends Instance> instances = instanceDao.getNonRemovedInstanceOn(host.getId()); List<Instance> removed = new ArrayList<>(); for (Instance instance : instances ) { if (InstanceConstants.isSystem(instance)) { continue; } try { processManager.scheduleProcessInstanceAsync(InstanceConstants.PROCESS_STOP, instance, ProcessUtils.chainInData(new HashMap<String, Object>(), InstanceConstants.PROCESS_STOP, InstanceConstants.PROCESS_REMOVE)); } catch (ProcessCancelException e) { } removed.add(instance); } for (Instance instance : removed) { resourceMonitor.waitFor(instance, new ResourcePredicate<Instance>() { @Override public boolean evaluate(Instance obj) { return obj.getRemoved() != null; } @Override public String getMessage() { return "removed"; } }); } } @Override public String[] getProcessNames() { return new String[] {ExternalEventConstants.PROCESS_EXTERNAL_EVENT_CREATE}; } }