Repository: incubator-brooklyn Updated Branches: refs/heads/master 7b97cee1e -> 7a126a140
Ignore non-RUNNING children in SERVICE_UP quorum calculation Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/bc8eb266 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/bc8eb266 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/bc8eb266 Branch: refs/heads/master Commit: bc8eb2664a2170c7e1ebd797e7ba48dda492039d Parents: 2a6d9fd Author: Svetoslav Neykov <[email protected]> Authored: Wed Apr 22 14:41:32 2015 +0300 Committer: Svetoslav Neykov <[email protected]> Committed: Wed Apr 22 14:50:00 2015 +0300 ---------------------------------------------------------------------- .../entity/basic/ServiceStateLogic.java | 13 ++++++--- .../entity/basic/ServiceStateLogicTest.java | 28 +++++++++++++------- 2 files changed, 28 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc8eb266/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java b/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java index d8fc957..cfabf1b 100644 --- a/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java +++ b/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java @@ -180,7 +180,6 @@ public class ServiceStateLogic { /** static only; not for instantiation */ private ServiceNotUpLogic() {} - @SuppressWarnings({ "unchecked", "rawtypes" }) public static final EnricherSpec<?> newEnricherForServiceUpIfNotUpIndicatorsEmpty() { return Enrichers.builder() .transforming(SERVICE_NOT_UP_INDICATORS).<Object>publishing(Attributes.SERVICE_UP) @@ -247,6 +246,7 @@ public class ServiceStateLogic { if (uniqueTag==null) uniqueTag = DEFAULT_ENRICHER_UNIQUE_TAG; } + @Override public void setEntity(EntityLocal entity) { super.setEntity(entity); if (suppressDuplicates==null) { @@ -409,11 +409,13 @@ public class ServiceStateLogic { Preconditions.checkNotNull(getKeyForMapSensor()); } + @Override protected void setEntityLoadingTargetConfig() { if (getConfig(TARGET_SENSOR)!=null) throw new IllegalArgumentException("Must not set "+TARGET_SENSOR+" when using "+this); } + @Override public void setEntity(EntityLocal entity) { super.setEntity(entity); if (suppressDuplicates==null) { @@ -472,19 +474,24 @@ public class ServiceStateLogic { Map<Entity, Boolean> values = getValues(SERVICE_UP); List<Entity> violators = MutableList.of(); boolean ignoreNull = getConfig(IGNORE_ENTITIES_WITH_SERVICE_UP_NULL); + Set<Lifecycle> ignoreStates = getConfig(IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES); int entries=0; + int numUp=0; for (Map.Entry<Entity, Boolean> state: values.entrySet()) { if (ignoreNull && state.getValue()==null) continue; entries++; - if (!Boolean.TRUE.equals(state.getValue())) { + Lifecycle entityState = state.getKey().getAttribute(SERVICE_STATE_ACTUAL); + + if (Boolean.TRUE.equals(state.getValue())) numUp++; + else if (!ignoreStates.contains(entityState)) { violators.add(state.getKey()); } } QuorumCheck qc = getConfig(UP_QUORUM_CHECK); if (qc!=null) { - if (qc.isQuorate(entries-violators.size(), entries)) + if (qc.isQuorate(numUp, violators.size()+numUp)) // quorate return null; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc8eb266/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java b/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java index d30b05a..0c16632 100644 --- a/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java +++ b/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java @@ -24,9 +24,7 @@ import org.testng.annotations.Test; import brooklyn.entity.BrooklynAppUnitTestSupport; import brooklyn.entity.Entity; -import brooklyn.entity.Group; import brooklyn.entity.basic.EntitySubscriptionTest.RecordingSensorEventListener; -import brooklyn.entity.basic.QuorumCheck.QuorumChecks; import brooklyn.entity.basic.ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers; import brooklyn.entity.basic.ServiceStateLogic.ServiceNotUpLogic; import brooklyn.entity.basic.ServiceStateLogic.ServiceProblemsLogic; @@ -40,6 +38,7 @@ import brooklyn.policy.Enricher; import brooklyn.test.EntityTestUtils; import brooklyn.test.entity.TestEntity; import brooklyn.test.entity.TestEntityImpl.TestEntityWithoutEnrichers; +import brooklyn.util.collections.QuorumCheck.QuorumChecks; import brooklyn.util.exceptions.Exceptions; import brooklyn.util.time.Duration; @@ -57,6 +56,7 @@ public class ServiceStateLogicTest extends BrooklynAppUnitTestSupport { protected TestEntity entity; + @Override protected void setUpApp() { super.setUpApp(); entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); @@ -165,13 +165,21 @@ public class ServiceStateLogicTest extends BrooklynAppUnitTestSupport { assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, true); assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); - // if we then put a not-up indicator on the TestEntity, it publishes false, so app also is false, and thus stopped + // if we then put a not-up indicator on the TestEntity, it publishes false, but app is still up. State + // won't propagate due to it's SERVICE_STATE_ACTUAL (null) being in IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES ServiceNotUpLogic.updateNotUpIndicator(entity, INDICATOR_KEY_1, "We're also pretending to block service up"); assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false); + assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, true); + assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); + // the entity still has no opinion about its state + assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, null); + + // switching the entity state to one not in IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES will propagate the up state + ServiceStateLogic.setExpectedState(entity, Lifecycle.RUNNING); + assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false); assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, false); assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED); - // but the entity still has no opinion about its state - assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, null); + // if the entity expects to be stopped, it will report stopped ServiceStateLogic.setExpectedState(entity, Lifecycle.STOPPED); @@ -191,7 +199,7 @@ public class ServiceStateLogicTest extends BrooklynAppUnitTestSupport { // if we change the state quorum check for the app to be "all are healthy and at least one running" *then* it shows stopped // (normally this would be done in `initEnrichers` of course) Enricher appChildrenBasedEnricher = EntityAdjuncts.tryFindWithUniqueTag(app.getEnrichers(), ComputeServiceIndicatorsFromChildrenAndMembers.DEFAULT_UNIQUE_TAG).get(); - appChildrenBasedEnricher.setConfig(ComputeServiceIndicatorsFromChildrenAndMembers.RUNNING_QUORUM_CHECK, QuorumChecks.allAndAtLeastOne()); + appChildrenBasedEnricher.config().set(ComputeServiceIndicatorsFromChildrenAndMembers.RUNNING_QUORUM_CHECK, QuorumChecks.allAndAtLeastOne()); assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE); // if entity is expected running, then it will show running because service is up; this is reflected at app and at entity @@ -207,7 +215,7 @@ public class ServiceStateLogicTest extends BrooklynAppUnitTestSupport { assertAttributeEqualsContinually(app, Attributes.SERVICE_UP, true); // if we change its up-quorum to atLeastOne then state becomes stopped (because there is no expected state; has not been started) - appChildrenBasedEnricher.setConfig(ComputeServiceIndicatorsFromChildrenAndMembers.UP_QUORUM_CHECK, QuorumChecks.atLeastOne()); + appChildrenBasedEnricher.config().set(ComputeServiceIndicatorsFromChildrenAndMembers.UP_QUORUM_CHECK, QuorumChecks.atLeastOne()); assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED); assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, false); @@ -218,7 +226,7 @@ public class ServiceStateLogicTest extends BrooklynAppUnitTestSupport { assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE); // restoring up-quorum to "atLeastOneUnlessEmpty" causes it to become RUNNING, because happy with empty - appChildrenBasedEnricher.setConfig(ComputeServiceIndicatorsFromChildrenAndMembers.UP_QUORUM_CHECK, QuorumChecks.atLeastOneUnlessEmpty()); + appChildrenBasedEnricher.config().set(ComputeServiceIndicatorsFromChildrenAndMembers.UP_QUORUM_CHECK, QuorumChecks.atLeastOneUnlessEmpty()); assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, true); // but running-quorum is still allAndAtLeastOne, so remains on-fire assertAttributeEqualsContinually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE); @@ -229,13 +237,13 @@ public class ServiceStateLogicTest extends BrooklynAppUnitTestSupport { assertAttributeEqualsContinually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE); // tell it not to ignore null values for children states, and it will go onfire (but still be service up) - appChildrenBasedEnricher.setConfig(ComputeServiceIndicatorsFromChildrenAndMembers.IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES, + appChildrenBasedEnricher.config().set(ComputeServiceIndicatorsFromChildrenAndMembers.IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES, ImmutableSet.<Lifecycle>of()); assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE); assertAttributeEquals(app, Attributes.SERVICE_UP, true); // tell it not to ignore null values for service up and it will go service down - appChildrenBasedEnricher.setConfig(ComputeServiceIndicatorsFromChildrenAndMembers.IGNORE_ENTITIES_WITH_SERVICE_UP_NULL, false); + appChildrenBasedEnricher.config().set(ComputeServiceIndicatorsFromChildrenAndMembers.IGNORE_ENTITIES_WITH_SERVICE_UP_NULL, false); assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, false); // set the entity to RUNNING and the app will be healthy again
