@Override protected void connectServiceUpIsRunning() { ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); }
@Override public void rebind() { //SERVICE_STATE_ACTUAL might be ON_FIRE due to a temporary condition (problems map non-empty) //Only if the expected state is ON_FIRE then the entity has permanently failed. Lifecycle expectedState = ServiceStateLogic.getExpectedState(this); if (expectedState == null || expectedState != Lifecycle.RUNNING) { LOG.warn("On rebind of {}, not calling software process rebind hooks because expected state is {}", this, expectedState); return; } Lifecycle actualState = ServiceStateLogic.getActualState(this); if (actualState == null || actualState != Lifecycle.RUNNING) { LOG.warn("Rebinding entity {}, even though actual state is {}. Expected state is {}", new Object[] { this, actualState, expectedState }); } // e.g. rebinding to a running instance // FIXME What if location not set? LOG.info("Rebind {} connecting to pre-running service", this); MachineLocation machine = getMachineOrNull(); if (machine != null) { initDriver(machine); driver.rebind(); LOG.debug("On rebind of {}, re-created driver {}", this, driver); } else { LOG.info("On rebind of {}, no MachineLocation found (with locations {}) so not generating driver", this, getLocations()); } callRebindHooks(); }
/** puts the given value into the {@link Attributes#SERVICE_NOT_UP_INDICATORS} map as if the * {@link UpdatingMap} enricher for the given key */ public static void updateNotUpIndicator(Entity entity, String key, Object value) { updateMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, key, value); } /** clears any entry for the given key in the {@link Attributes#SERVICE_NOT_UP_INDICATORS} map */
protected void updateMapSensor(AttributeSensor<Map<String, Object>> sensor, Object value) { if (log.isTraceEnabled()) log.trace("{} updating map sensor {} with {}", new Object[] { this, sensor, value }); if (value!=null) { updateMapSensorEntry(entity, sensor, getKeyForMapSensor(), value); } else { clearMapSensorEntry(entity, sensor, getKeyForMapSensor()); } }
@Override public void restart() { getConfig(LISTENER).onEvent(this, "restart", new Object[0]); if (getConfig(FAIL_ON_RESTART) || (getConfig(FAIL_ON_RESTART_CONDITION) != null && getConfig(FAIL_ON_RESTART_CONDITION).apply(this))) { if (Boolean.TRUE.equals(getConfig(SET_SERVICE_DOWN_ON_FAILURE))) { ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING); sensors().set(SERVICE_UP, false); ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPED); ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); ServiceStateLogic.setExpectedStateRunningWithErrors(this); } callHistory.add("restart"); getConfig(EXEC_ON_FAILURE).apply(this); throw fail("Simulating entity restart failure for test"); } super.restart(); }
@Test public void testDoesNotCreateDriverAfterRebind() throws Exception { MyService origE = origApp.createAndManageChild(EntitySpec.create(MyService.class) .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true)); //the entity skips enricher initialization, do it explicitly origE.enrichers().add(ServiceStateLogic.newEnricherForServiceStateFromProblemsAndUp()); MyProvisioningLocation origLoc = mgmt().getLocationManager().createLocation(LocationSpec.create(MyProvisioningLocation.class) .displayName("mylocname")); origApp.start(ImmutableList.of(origLoc)); assertEquals(origE.getAttribute(Attributes.SERVICE_STATE_EXPECTED).getState(), Lifecycle.RUNNING); EntityAsserts.assertAttributeEqualsEventually(origE, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); ServiceStateLogic.setExpectedState(origE, Lifecycle.ON_FIRE); EntityAsserts.assertAttributeEqualsEventually(origE, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE); newApp = rebind(); MyService newE = (MyService) Iterables.getOnlyElement(newApp.getChildren()); assertNull(newE.getDriver(), "driver should not be initialized because entity is in a permanent failure"); }
@Override public void initEnrichers() { super.initEnrichers(); // Include STARTING members in UP_QUORUM_CHECK as we want all members running and up for quorum enrichers().add(ServiceStateLogic.newEnricherFromChildrenUp() .checkMembersOnly() .requireUpChildren(getConfig(UP_QUORUM_CHECK)) .configure(ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers.IGNORE_ENTITIES_WITH_SERVICE_UP_NULL, false) .configure(ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers.IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES, ImmutableSet.<Lifecycle>of(Lifecycle.STOPPING, Lifecycle.STOPPED, Lifecycle.DESTROYED)) .suppressDuplicates(true)); }
@Override protected void initEnrichers() { super.initEnrichers(); // check states and upness separately so they can be individually replaced if desired // problem if any children or members are on fire enrichers().add(ServiceStateLogic.newEnricherFromChildrenState() .checkChildrenAndMembers() .requireRunningChildren(getConfig(RUNNING_QUORUM_CHECK)) .suppressDuplicates(true)); // defaults to requiring at least one member or child who is up enrichers().add(ServiceStateLogic.newEnricherFromChildrenUp() .checkChildrenAndMembers() .requireUpChildren(getConfig(UP_QUORUM_CHECK)) .suppressDuplicates(true)); }
public static boolean isExpectedState(Entity entity, Lifecycle state) { return getExpectedState(entity)==state; }
/** * By default, adds enrichers to populate {@link Attributes#SERVICE_UP} and {@link Attributes#SERVICE_STATE_ACTUAL} * based on {@link Attributes#SERVICE_NOT_UP_INDICATORS}, * {@link Attributes#SERVICE_STATE_EXPECTED} and {@link Attributes#SERVICE_PROBLEMS} * (doing nothing if these sensors are not used). * <p> * Subclasses may go further and populate the {@link Attributes#SERVICE_NOT_UP_INDICATORS} * and {@link Attributes#SERVICE_PROBLEMS} from children and members or other sources. */ // these enrichers do nothing unless Attributes.SERVICE_NOT_UP_INDICATORS are used // and/or SERVICE_STATE_EXPECTED protected void initEnrichers() { enrichers().add(ServiceNotUpLogic.newEnricherForServiceUpIfNotUpIndicatorsEmpty()); enrichers().add(ServiceStateLogic.newEnricherForServiceStateFromProblemsAndUp()); }
/** as {@link #clearProblemsIndicator(Entity, Sensor)} */ public static void clearProblemsIndicator(Entity entity, String key) { clearMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, key); } }
@Override public void start(Collection<? extends Location> locs) { getConfig(LISTENER).onEvent(this, "start", new Object[] {locs}); if (getConfig(FAIL_ON_START) || (getConfig(FAIL_ON_START_CONDITION) != null && getConfig(FAIL_ON_START_CONDITION).apply(this))) { if (Boolean.TRUE.equals(getConfig(SET_SERVICE_DOWN_ON_FAILURE))) { ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); sensors().set(SERVICE_UP, false); ServiceStateLogic.setExpectedStateRunningWithErrors(this); } callHistory.add("start"); getConfig(EXEC_ON_FAILURE).apply(this); throw fail("Simulating entity start failure for test"); } super.start(locs); }
@Override protected void initEnrichers() { super.initEnrichers(); enrichers().add(ServiceStateLogic.newEnricherFromChildrenUp() .checkChildrenOnly() .requireUpChildren(QuorumCheck.QuorumChecks.all()) .suppressDuplicates(true)); }
@Override public void populateServiceNotUpDiagnostics() { if (getDriver() == null) { ServiceStateLogic.updateMapSensorEntry(this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, "driver", "No driver"); ServiceStateLogic.clearMapSensorEntry(this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, "sshable"); ServiceStateLogic.clearMapSensorEntry(this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, SERVICE_PROCESS_IS_RUNNING.getName()); return; } else { ServiceStateLogic.clearMapSensorEntry(this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, "driver"); if (loc instanceof SshMachineLocation) { if (((SshMachineLocation)loc).isSshable()) { ServiceStateLogic.clearMapSensorEntry(this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, "sshable"); } else { ServiceStateLogic.updateMapSensorEntry( this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, ServiceStateLogic.clearMapSensorEntry( this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, SERVICE_PROCESS_IS_RUNNING.getName()); } else { ServiceStateLogic.updateMapSensorEntry( this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS,
@Override protected void initEnrichers() { super.initEnrichers(); // check states and upness separately so they can be individually replaced if desired // problem if any children or members are on fire enrichers().add(ServiceStateLogic.newEnricherFromChildrenState() .checkChildrenOnly() .requireRunningChildren(getConfig(RUNNING_QUORUM_CHECK)) .suppressDuplicates(true)); // defaults to requiring at least one member or child who is up enrichers().add(ServiceStateLogic.newEnricherFromChildrenUp() .checkChildrenOnly() .requireUpChildren(getConfig(UP_QUORUM_CHECK)) .suppressDuplicates(true)); }
@Override protected void instanceRebind(AbstractBrooklynObject instance) { Preconditions.checkState(instance == entity, "Expected %s and %s to match, but different objects", instance, entity); Lifecycle expectedState = ServiceStateLogic.getExpectedState(entity); boolean isAsync = (entity instanceof AsyncStartable); if ((!isAsync && expectedState == Lifecycle.STARTING) || expectedState == Lifecycle.STOPPING) { // If we were previously "starting" or "stopping", then those tasks will have been // aborted. We don't want to continue showing that state (e.g. the web-console would // then show the it as in-progress with the "spinning" icon). // Therefore we set the entity as on-fire, and add the indicator that says why. markTransitioningEntityOnFireOnRebind(entity, expectedState); } // Clear the provisioning/termination task-state; the task will have been aborted, so wrong to keep this state. entity.sensors().remove(AttributesInternal.INTERNAL_PROVISIONING_TASK_STATE); entity.sensors().remove(AttributesInternal.INTERNAL_TERMINATION_TASK_STATE); super.instanceRebind(instance); }
@BeforeMethod(alwaysRun=true) @Override public void setUp() throws Exception { super.setUp(); events = new CopyOnWriteArrayList<SensorEvent<FailureDescriptor>>(); eventListener = new SensorEventListener<FailureDescriptor>() { @Override public void onEvent(SensorEvent<FailureDescriptor> event) { events.add(event); } }; e1 = app.createAndManageChild(EntitySpec.create(TestEntity.class)); e1.enrichers().add(ServiceStateLogic.newEnricherForServiceStateFromProblemsAndUp()); app.getManagementContext().getSubscriptionManager().subscribe(e1, HASensors.ENTITY_FAILED, eventListener); app.getManagementContext().getSubscriptionManager().subscribe(e1, HASensors.ENTITY_RECOVERED, eventListener); }
/** clears any entry for the given key in the {@link Attributes#SERVICE_NOT_UP_INDICATORS} map */ public static void clearNotUpIndicator(Entity entity, String key) { clearMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, key); } /** as {@link #updateNotUpIndicator(Entity, String, Object)} using the given sensor as the key */
public static void setExpectedStateRunningWithErrors(Entity entity) { setExpectedState(entity, Lifecycle.RUNNING, false); }
/** as {@link #updateProblemsIndicator(Entity, Sensor, Object)} */ public static void updateProblemsIndicator(Entity entity, String key, Object value) { updateMapSensorEntry(entity, Attributes.SERVICE_PROBLEMS, key, value); } /** as {@link #clearProblemsIndicator(Entity, Sensor)} */