package io.cattle.iaas.healthcheck.service.impl; import static io.cattle.platform.core.model.tables.HealthcheckInstanceTable.HEALTHCHECK_INSTANCE; import static io.cattle.platform.core.model.tables.InstanceTable.INSTANCE; import io.cattle.platform.core.addon.InstanceHealthCheck; import io.cattle.platform.core.constants.CommonStatesConstants; import io.cattle.platform.core.constants.HealthcheckConstants; import io.cattle.platform.core.constants.InstanceConstants; import io.cattle.platform.core.model.Instance; import io.cattle.platform.core.model.tables.records.InstanceRecord; import io.cattle.platform.db.jooq.dao.impl.AbstractJooqDao; import io.cattle.platform.engine.process.ProcessInstanceException; import io.cattle.platform.engine.process.impl.ProcessCancelException; import io.cattle.platform.json.JsonMapper; import io.cattle.platform.object.process.ObjectProcessManager; import io.cattle.platform.object.process.StandardProcess; import io.cattle.platform.object.util.DataAccessor; import io.cattle.platform.process.common.util.ProcessUtils; import io.cattle.platform.task.Task; import java.util.HashMap; import java.util.List; import javax.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HealthcheckCleanupMonitorImpl extends AbstractJooqDao implements Task { private static final Logger log = LoggerFactory.getLogger(HealthcheckCleanupMonitorImpl.class); @Inject ObjectProcessManager objectProcessManager; @Inject JsonMapper jsonMapper; @Override public void run() { List<? extends Instance> instances = create() .select(INSTANCE.fields()) .from(INSTANCE) .join(HEALTHCHECK_INSTANCE) .on(HEALTHCHECK_INSTANCE.INSTANCE_ID.eq(INSTANCE.ID)) .where(INSTANCE.REMOVED.isNull()) .and(INSTANCE.STATE.notIn(CommonStatesConstants.REMOVING)) .and(INSTANCE.HEALTH_STATE.in(HealthcheckConstants.HEALTH_STATE_INITIALIZING, HealthcheckConstants.HEALTH_STATE_REINITIALIZING)) .fetchInto(InstanceRecord.class); for (Instance instance : instances) { boolean remove = needToRemove(instance); if (!remove) { continue; } try { try { objectProcessManager.scheduleStandardProcessAsync(StandardProcess.REMOVE, instance, null); } catch (ProcessCancelException e) { if (instance.getState().equalsIgnoreCase(InstanceConstants.STATE_STOPPING)) { continue; } objectProcessManager.scheduleProcessInstanceAsync(InstanceConstants.PROCESS_STOP, instance, ProcessUtils.chainInData(new HashMap<String, Object>(), InstanceConstants.PROCESS_STOP, InstanceConstants.PROCESS_REMOVE)); } log.info("Scheduled remove for instance id [{}]", instance.getId()); } catch (ProcessInstanceException e) { // don't error out so we have a chance to schedule remove for the rest of the instances log.info("Failed to schedule remove for instance id [{}]", instance.getId(), e); } } } protected boolean needToRemove(Instance instance) { boolean remove = false; InstanceHealthCheck healthCheck = DataAccessor.field(instance, InstanceConstants.FIELD_HEALTH_CHECK, jsonMapper, InstanceHealthCheck.class); Integer timeout; if (instance.getHealthState().equalsIgnoreCase(HealthcheckConstants.HEALTH_STATE_INITIALIZING)) { timeout = healthCheck.getInitializingTimeout(); } else { timeout = healthCheck.getReinitializingTimeout(); } if (timeout != null && instance.getHealthUpdated() != null) { long createdTimeAgo = System.currentTimeMillis() - instance.getHealthUpdated().getTime(); if (createdTimeAgo >= timeout) { remove = true; } } return remove; } @Override public String getName() { return "healthcheck.cleanup"; } }