You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/08/30 01:01:23 UTC

[23/26] git commit: convert SERVICE_STATE to _ACTUAL or _EXPECTED in many more places, and force recompute of _ACTUAL whenever _EXPECTED is changed

convert SERVICE_STATE to _ACTUAL or _EXPECTED in many more places, and force recompute of _ACTUAL whenever _EXPECTED is changed


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/099a5496
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/099a5496
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/099a5496

Branch: refs/heads/master
Commit: 099a5496e4ec48bb31d11a3be82c92831aef2ceb
Parents: 31c5a0c
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Aug 27 01:10:08 2014 -0400
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Aug 27 02:21:23 2014 -0400

----------------------------------------------------------------------
 .../brooklyn/entity/basic/AbstractEntity.java   |  2 +-
 .../entity/basic/ServiceStateLogic.java         |  5 +++++
 .../policy/ha/MemberFailureDetectionPolicy.java |  8 ++++---
 .../brooklyn/policy/ha/ServiceReplacer.java     |  5 ++---
 .../brooklyn/policy/ha/ServiceRestarter.java    |  5 +++--
 .../brooklyn/policy/ha/ServiceReplacerTest.java |  4 ++--
 .../policy/ha/ServiceRestarterTest.java         |  4 ++--
 .../entity/chef/ChefLifecycleEffectorTasks.java |  8 +++----
 .../brooklyn/entity/pool/ServerPoolImpl.java    |  4 ++--
 .../software/MachineLifecycleEffectorTasks.java |  2 +-
 .../mysql/AbstractToyMySqlEntityTest.java       |  4 ++--
 .../cassandra/CassandraDatacenterImpl.java      | 17 +++++++++++----
 .../nosql/cassandra/CassandraFabricImpl.java    |  2 +-
 .../sharding/MongoDBShardedDeploymentImpl.java  | 22 +++++++++++++-------
 .../nosql/cassandra/CassandraFabricTest.java    |  5 +++--
 .../entity/dns/AbstractGeoDnsService.java       |  2 +-
 .../entity/dns/AbstractGeoDnsServiceImpl.java   |  9 ++++++--
 .../geoscaling/GeoscalingDnsServiceImpl.java    |  5 +++--
 .../brooklyn/JavaWebAppsIntegrationTest.java    |  5 +++--
 .../brooklyn/VanillaBashNetcatYamlTest.java     | 10 ++++-----
 .../BrooklynEntityMirrorIntegrationTest.java    |  4 ++--
 .../rest/resources/ApplicationResource.java     |  2 +-
 22 files changed, 82 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
index a612b0c..5e21fd7 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
@@ -1047,7 +1047,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     }
     
     /**
-     * By default, adds enrichers to populate {@link Attributes#SERVICE_UP} and {@link Attributes#SERVICE_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).

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/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 388f80d..5154bff 100644
--- a/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
+++ b/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
@@ -114,6 +114,11 @@ public class ServiceStateLogic {
     
     public static void setExpectedState(Entity entity, Lifecycle state) {
         ((EntityInternal)entity).setAttribute(Attributes.SERVICE_STATE_EXPECTED, new Lifecycle.Transition(state, new Date()));
+        
+        Enricher enricher = EntityAdjuncts.findWithUniqueTag(entity.getEnrichers(), ComputeServiceState.DEFAULT_ENRICHER_UNIQUE_TAG);
+        if (enricher instanceof ComputeServiceState) {
+            ((ComputeServiceState)enricher).onEvent(null);
+        }
     }
     public static Lifecycle getExpectedState(Entity entity) {
         Transition expected = entity.getAttribute(Attributes.SERVICE_STATE_EXPECTED);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/policy/src/main/java/brooklyn/policy/ha/MemberFailureDetectionPolicy.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/MemberFailureDetectionPolicy.java b/policy/src/main/java/brooklyn/policy/ha/MemberFailureDetectionPolicy.java
index d1423a4..5a6fa0a 100644
--- a/policy/src/main/java/brooklyn/policy/ha/MemberFailureDetectionPolicy.java
+++ b/policy/src/main/java/brooklyn/policy/ha/MemberFailureDetectionPolicy.java
@@ -43,6 +43,7 @@ import com.google.common.base.Objects;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Maps;
+import com.google.common.reflect.TypeToken;
 
 /**
  * Detects when members of a group have failed/recovered, and emits ENTITY_FAILED or 
@@ -83,8 +84,9 @@ public class MemberFailureDetectionPolicy extends AbstractPolicy {
     @SetFromFlag("useServiceStateRunning")
     public static final ConfigKey<Boolean> USE_SERVICE_STATE_RUNNING = ConfigKeys.newBooleanConfigKey("useServiceStateRunning", "", true);
 
+    @SuppressWarnings("serial")
     @SetFromFlag("memberFilter")
-    public static final ConfigKey<Predicate<? super Entity>> MEMBER_FILTER = (ConfigKey) ConfigKeys.newConfigKey(Predicate.class, "memberFilter", "", Predicates.alwaysTrue());
+    public static final ConfigKey<Predicate<? super Entity>> MEMBER_FILTER = ConfigKeys.newConfigKey(new TypeToken<Predicate<? super Entity>>() {}, "memberFilter", "", Predicates.<Entity>alwaysTrue());
     
     private final Map<Entity, Long> memberFailures = Maps.newLinkedHashMap();
     private final Map<Entity, Long> memberLastUps = Maps.newLinkedHashMap();
@@ -108,7 +110,7 @@ public class MemberFailureDetectionPolicy extends AbstractPolicy {
         super.setEntity(entity);
         
         if (getConfig(USE_SERVICE_STATE_RUNNING)) {
-            subscribeToMembers((Group)entity, Attributes.SERVICE_STATE, new SensorEventListener<Lifecycle>() {
+            subscribeToMembers((Group)entity, Attributes.SERVICE_STATE_ACTUAL, new SensorEventListener<Lifecycle>() {
                 @Override public void onEvent(SensorEvent<Lifecycle> event) {
                     if (!acceptsMember(event.getSource())) return;
                     onMemberStatus(event.getSource(), event.getValue());
@@ -165,7 +167,7 @@ public class MemberFailureDetectionPolicy extends AbstractPolicy {
     
     private synchronized void onMemberAdded(Entity member) {
         if (getConfig(USE_SERVICE_STATE_RUNNING)) {
-            Lifecycle status = member.getAttribute(Attributes.SERVICE_STATE);
+            Lifecycle status = member.getAttribute(Attributes.SERVICE_STATE_ACTUAL);
             onMemberStatus(member, status);
         }
         

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java b/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java
index 18c6f53..9142c78 100644
--- a/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java
+++ b/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java
@@ -32,12 +32,11 @@ import org.slf4j.LoggerFactory;
 import brooklyn.config.ConfigKey;
 import brooklyn.entity.Entity;
 import brooklyn.entity.Group;
-import brooklyn.entity.basic.Attributes;
 import brooklyn.entity.basic.ConfigKeys;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.basic.EntityLocal;
-import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.basic.ServiceStateLogic.ServiceProblemsLogic;
 import brooklyn.entity.group.StopFailedRuntimeException;
 import brooklyn.entity.trait.MemberReplaceable;
 import brooklyn.event.Sensor;
@@ -206,7 +205,7 @@ public class ServiceReplacer extends AbstractPolicy {
         consecutiveReplacementFailureTimes.add(currentTimeMillis());
         
         if (getConfig(SET_ON_FIRE_ON_FAILURE)) {
-            entity.setAttribute(Attributes.SERVICE_STATE, Lifecycle.ON_FIRE);
+            ServiceProblemsLogic.updateProblemsIndicator(entity, "ServiceReplacer", "replacement failed: "+msg);
         }
         entity.emit(ENTITY_REPLACEMENT_FAILED, new FailureDescriptor(entity, msg));
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java b/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java
index cc86be0..06e6c77 100644
--- a/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java
+++ b/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java
@@ -31,6 +31,7 @@ import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.basic.EntityLocal;
 import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.basic.ServiceStateLogic;
 import brooklyn.entity.trait.Startable;
 import brooklyn.event.Sensor;
 import brooklyn.event.SensorEvent;
@@ -141,7 +142,7 @@ public class ServiceRestarter extends AbstractPolicy {
             return;
         }
         try {
-            entity.setAttribute(Attributes.SERVICE_STATE, Lifecycle.STARTING);
+            ServiceStateLogic.setExpectedState(entity, Lifecycle.STARTING);
             Entities.invokeEffector(entity, entity, Startable.RESTART).get();
         } catch (Exception e) {
             onRestartFailed("Restart failure (error "+e+") at "+entity+": "+event.getValue());
@@ -151,7 +152,7 @@ public class ServiceRestarter extends AbstractPolicy {
     protected void onRestartFailed(String msg) {
         LOG.warn("ServiceRestarter failed for "+entity+": "+msg);
         if (getConfig(SET_ON_FIRE_ON_FAILURE)) {
-            entity.setAttribute(Attributes.SERVICE_STATE, Lifecycle.ON_FIRE);
+            ServiceStateLogic.setExpectedState(entity, Lifecycle.ON_FIRE);
         }
         entity.emit(ENTITY_RESTART_FAILED, new FailureDescriptor(entity, msg));
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/policy/src/test/java/brooklyn/policy/ha/ServiceReplacerTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/ha/ServiceReplacerTest.java b/policy/src/test/java/brooklyn/policy/ha/ServiceReplacerTest.java
index 8d1a683..900405b 100644
--- a/policy/src/test/java/brooklyn/policy/ha/ServiceReplacerTest.java
+++ b/policy/src/test/java/brooklyn/policy/ha/ServiceReplacerTest.java
@@ -177,7 +177,7 @@ public class ServiceReplacerTest {
         // Configured to not mark cluster as on fire
         Asserts.succeedsContinually(new Runnable() {
             @Override public void run() {
-                assertNotEquals(cluster.getAttribute(Attributes.SERVICE_STATE), Lifecycle.ON_FIRE);
+                assertNotEquals(cluster.getAttribute(Attributes.SERVICE_STATE_ACTUAL), Lifecycle.ON_FIRE);
             }});
         
         // And will have received notification event about it
@@ -217,7 +217,7 @@ public class ServiceReplacerTest {
         // Failure to stop the failed member should not cause "on-fire" of cluster
         Asserts.succeedsContinually(new Runnable() {
             @Override public void run() {
-                assertNotEquals(cluster.getAttribute(Attributes.SERVICE_STATE), Lifecycle.ON_FIRE);
+                assertNotEquals(cluster.getAttribute(Attributes.SERVICE_STATE_ACTUAL), Lifecycle.ON_FIRE);
             }});
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/policy/src/test/java/brooklyn/policy/ha/ServiceRestarterTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/ha/ServiceRestarterTest.java b/policy/src/test/java/brooklyn/policy/ha/ServiceRestarterTest.java
index 17df8c6..0d27b0c 100644
--- a/policy/src/test/java/brooklyn/policy/ha/ServiceRestarterTest.java
+++ b/policy/src/test/java/brooklyn/policy/ha/ServiceRestarterTest.java
@@ -126,7 +126,7 @@ public class ServiceRestarterTest {
                 assertEquals(((FailureDescriptor)Iterables.getOnlyElement(events).getValue()).getComponent(), e2, "events="+events);
             }});
         
-        assertEquals(e2.getAttribute(Attributes.SERVICE_STATE), Lifecycle.ON_FIRE);
+        assertEquals(e2.getAttribute(Attributes.SERVICE_STATE_ACTUAL), Lifecycle.ON_FIRE);
     }
     
     @Test
@@ -144,7 +144,7 @@ public class ServiceRestarterTest {
         
         Asserts.succeedsContinually(new Runnable() {
             @Override public void run() {
-                assertNotEquals(e2.getAttribute(Attributes.SERVICE_STATE), Lifecycle.ON_FIRE);
+                assertNotEquals(e2.getAttribute(Attributes.SERVICE_STATE_ACTUAL), Lifecycle.ON_FIRE);
             }});
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java
index 16a9bed..f257989 100644
--- a/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java
@@ -288,7 +288,7 @@ public class ChefLifecycleEffectorTasks extends MachineLifecycleEffectorTasks im
         if (getServiceName()==null) return false;
         int result = DynamicTasks.queue(SshEffectorTasks.ssh("/etc/init.d/"+getServiceName()+" stop").runAsRoot()).get();
         if (0==result) return true;
-        if (entity().getAttribute(Attributes.SERVICE_STATE)!=Lifecycle.RUNNING)
+        if (entity().getAttribute(Attributes.SERVICE_STATE_ACTUAL)!=Lifecycle.RUNNING)
             return true;
         
         throw new IllegalStateException("The process for "+entity()+" appears could not be stopped (exit code "+result+" to service stop)");
@@ -298,7 +298,7 @@ public class ChefLifecycleEffectorTasks extends MachineLifecycleEffectorTasks im
         if (getWindowsServiceName()==null) return false;
                 int result = DynamicTasks.queue(SshEffectorTasks.ssh("sc query \""+getWindowsServiceName()+"\"").runAsCommand()).get();
         if (0==result) return true;
-        if (entity().getAttribute(Attributes.SERVICE_STATE)!=Lifecycle.RUNNING)
+        if (entity().getAttribute(Attributes.SERVICE_STATE_ACTUAL)!=Lifecycle.RUNNING)
             return true;
 
         throw new IllegalStateException("The process for "+entity()+" appears could not be stopped (exit code "+result+" to service stop)");
@@ -307,11 +307,11 @@ public class ChefLifecycleEffectorTasks extends MachineLifecycleEffectorTasks im
     protected boolean tryStopPid() {
         Integer pid = entity().getAttribute(Attributes.PID);
         if (pid==null) {
-            if (entity().getAttribute(Attributes.SERVICE_STATE)==Lifecycle.RUNNING && getPidFile()==null)
+            if (entity().getAttribute(Attributes.SERVICE_STATE_ACTUAL)==Lifecycle.RUNNING && getPidFile()==null)
                 log.warn("No PID recorded for "+entity()+" when running, with PID file "+getPidFile()+"; skipping kill in "+Tasks.current());
             else 
                 if (log.isDebugEnabled())
-                    log.debug("No PID recorded for "+entity()+"; skipping ("+entity().getAttribute(Attributes.SERVICE_STATE)+" / "+getPidFile()+")");
+                    log.debug("No PID recorded for "+entity()+"; skipping ("+entity().getAttribute(Attributes.SERVICE_STATE_ACTUAL)+" / "+getPidFile()+")");
             return false;
         }
         

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/software/base/src/main/java/brooklyn/entity/pool/ServerPoolImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/pool/ServerPoolImpl.java b/software/base/src/main/java/brooklyn/entity/pool/ServerPoolImpl.java
index 7e4f907..ddc9add 100644
--- a/software/base/src/main/java/brooklyn/entity/pool/ServerPoolImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/pool/ServerPoolImpl.java
@@ -282,7 +282,7 @@ public class ServerPoolImpl extends DynamicClusterImpl implements ServerPool {
      */
     @Override
     protected Collection<Entity> shrink(int delta) {
-        if (Lifecycle.STOPPING.equals(getAttribute(Attributes.SERVICE_STATE))) {
+        if (Lifecycle.STOPPING.equals(getAttribute(Attributes.SERVICE_STATE_ACTUAL))) {
             return super.shrink(delta);
         }
 
@@ -327,7 +327,7 @@ public class ServerPoolImpl extends DynamicClusterImpl implements ServerPool {
         public Entity apply(Collection<Entity> members) {
             synchronized (mutex) {
                 Optional<Entity> choice;
-                if (Lifecycle.STOPPING.equals(getAttribute(Attributes.SERVICE_STATE))) {
+                if (Lifecycle.STOPPING.equals(getAttribute(Attributes.SERVICE_STATE_ACTUAL))) {
                     choice = Optional.of(members.iterator().next());
                 } else {
                     // Otherwise should only choose between removable + unusable or available

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
index b708b61..746a2be 100644
--- a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
@@ -90,7 +90,7 @@ import com.google.common.collect.Iterables;
  *  <li> {@link #postStartCustom()}
  *  <li> {@link #preStopCustom()}
  * </ul>
- * Note methods at this level typically look after the {@link Attributes#SERVICE_STATE} sensor.
+ * Note methods at this level typically look after the {@link Attributes#SERVICE_STATE_EXPECTED} sensor.
  *  
  * @since 0.6.0
  **/

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/software/base/src/test/java/brooklyn/entity/software/mysql/AbstractToyMySqlEntityTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/software/mysql/AbstractToyMySqlEntityTest.java b/software/base/src/test/java/brooklyn/entity/software/mysql/AbstractToyMySqlEntityTest.java
index 231ea8b..bbc1a69 100644
--- a/software/base/src/test/java/brooklyn/entity/software/mysql/AbstractToyMySqlEntityTest.java
+++ b/software/base/src/test/java/brooklyn/entity/software/mysql/AbstractToyMySqlEntityTest.java
@@ -81,11 +81,11 @@ public abstract class AbstractToyMySqlEntityTest extends BrooklynAppLiveTestSupp
     protected void checkStartsRunning(Entity mysql) {
         // should be starting within a few seconds (and almost certainly won't complete in that time) 
         Asserts.eventually(MutableMap.of("timeout", Duration.FIVE_SECONDS),
-                Entities.attributeSupplier(mysql, Attributes.SERVICE_STATE),
+                Entities.attributeSupplier(mysql, Attributes.SERVICE_STATE_ACTUAL),
                 Predicates.or(Predicates.equalTo(Lifecycle.STARTING), Predicates.equalTo(Lifecycle.RUNNING)));
         // should be up and running within 5m 
         Asserts.eventually(MutableMap.of("timeout", Duration.FIVE_MINUTES),
-                Entities.attributeSupplier(mysql, Attributes.SERVICE_STATE),
+                Entities.attributeSupplier(mysql, Attributes.SERVICE_STATE_ACTUAL),
                 Predicates.equalTo(Lifecycle.RUNNING));
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
index b04e362..603fb6d 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
@@ -146,7 +146,6 @@ public class CassandraDatacenterImpl extends DynamicClusterImpl implements Cassa
     
     protected SeedTracker seedTracker = new SeedTracker();
     protected TokenGenerator tokenGenerator = null;
-    private MemberTrackingPolicy policy;
 
     public CassandraDatacenterImpl() {
     }
@@ -176,6 +175,15 @@ public class CassandraDatacenterImpl extends DynamicClusterImpl implements Cassa
                 seedTracker.onServiceUpChanged(event.getSource(), event.getValue());
             }
         });
+        subscribeToMembers(this, Attributes.SERVICE_STATE_ACTUAL, new SensorEventListener<Lifecycle>() {
+            @Override
+            public void onEvent(SensorEvent<Lifecycle> event) {
+                // trigger a recomputation also when lifecycle state changes, 
+                // because it might not have ruled a seed as inviable when service up went true 
+                // because service state was not yet running
+                seedTracker.onServiceUpChanged(event.getSource(), Lifecycle.RUNNING==event.getValue());
+            }
+        });
         
         // Track the datacenters for this cluster
         subscribeToMembers(this, CassandraNode.DATACENTER_NAME, new SensorEventListener<String>() {
@@ -296,6 +304,7 @@ public class CassandraDatacenterImpl extends DynamicClusterImpl implements Cassa
         return super.grow(delta);
     }
     
+    @SuppressWarnings("deprecation")
     @Override
     protected Entity createNode(@Nullable Location loc, Map<?,?> flags) {
         Map<Object, Object> allflags = MutableMap.copyOf(flags);
@@ -357,7 +366,7 @@ public class CassandraDatacenterImpl extends DynamicClusterImpl implements Cassa
     protected void connectSensors() {
         connectEnrichers();
         
-        policy = addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+        addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
                 .displayName("Cassandra Cluster Tracker")
                 .configure("sensorsToTrack", ImmutableSet.of(Attributes.SERVICE_UP, Attributes.HOSTNAME, CassandraNode.THRIFT_PORT))
                 .configure("group", this));
@@ -587,7 +596,7 @@ public class CassandraDatacenterImpl extends DynamicClusterImpl implements Cassa
             boolean managed = Entities.isManaged(member);
             String hostname = member.getAttribute(Attributes.HOSTNAME);
             boolean serviceUp = Boolean.TRUE.equals(member.getAttribute(Attributes.SERVICE_UP));
-            Lifecycle serviceState = member.getAttribute(Attributes.SERVICE_STATE);
+            Lifecycle serviceState = member.getAttribute(Attributes.SERVICE_STATE_ACTUAL);
             boolean hasFailed = !managed || (serviceState == Lifecycle.ON_FIRE) || (serviceState == Lifecycle.RUNNING && !serviceUp) || (serviceState == Lifecycle.STOPPED);
             boolean result = (hostname != null && !hasFailed);
             if (log.isTraceEnabled()) log.trace("Node {} in Cluster {}: viableSeed={}; hostname={}; serviceUp={}; serviceState={}; hasFailed={}", new Object[] {member, this, result, hostname, serviceUp, serviceState, hasFailed});
@@ -596,7 +605,7 @@ public class CassandraDatacenterImpl extends DynamicClusterImpl implements Cassa
         public boolean isRunningSeed(Entity member) {
             boolean viableSeed = isViableSeed(member);
             boolean serviceUp = Boolean.TRUE.equals(member.getAttribute(Attributes.SERVICE_UP));
-            Lifecycle serviceState = member.getAttribute(Attributes.SERVICE_STATE);
+            Lifecycle serviceState = member.getAttribute(Attributes.SERVICE_STATE_ACTUAL);
             boolean result = viableSeed && serviceUp && serviceState == Lifecycle.RUNNING;
             if (log.isTraceEnabled()) log.trace("Node {} in Cluster {}: runningSeed={}; viableSeed={}; serviceUp={}; serviceState={}", new Object[] {member, this, result, viableSeed, serviceUp, serviceState});
             return result;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraFabricImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraFabricImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraFabricImpl.java
index fe0b503..2f874e6 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraFabricImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/cassandra/CassandraFabricImpl.java
@@ -190,7 +190,7 @@ public class CassandraFabricImpl extends DynamicFabricImpl implements CassandraF
             boolean managed = Entities.isManaged(member);
             String hostname = member.getAttribute(Attributes.HOSTNAME);
             boolean serviceUp = Boolean.TRUE.equals(member.getAttribute(Attributes.SERVICE_UP));
-            Lifecycle serviceState = member.getAttribute(Attributes.SERVICE_STATE);
+            Lifecycle serviceState = member.getAttribute(Attributes.SERVICE_STATE_ACTUAL);
             boolean hasFailed = !managed || (serviceState == Lifecycle.ON_FIRE) || (serviceState == Lifecycle.RUNNING && !serviceUp) || (serviceState == Lifecycle.STOPPED);
             boolean result = (hostname != null && !hasFailed);
             if (log.isTraceEnabled()) log.trace("Node {} in Fabric {}: viableSeed={}; hostname={}; serviceUp={}; serviceState={}; hasFailed={}", new Object[] {member, CassandraFabricImpl.this, result, hostname, serviceUp, serviceState, hasFailed});

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java b/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
index 944e99e..9c9cd62 100644
--- a/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
+++ b/software/nosql/src/main/java/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentImpl.java
@@ -33,6 +33,8 @@ import brooklyn.entity.basic.AbstractEntity;
 import brooklyn.entity.basic.Attributes;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.basic.ServiceStateLogic;
+import brooklyn.entity.basic.ServiceStateLogic.ServiceNotUpLogic;
 import brooklyn.entity.group.AbstractMembershipTrackingPolicy;
 import brooklyn.entity.group.DynamicCluster;
 import brooklyn.entity.proxying.EntitySpec;
@@ -51,6 +53,8 @@ public class MongoDBShardedDeploymentImpl extends AbstractEntity implements Mong
     
     @Override
     public void init() {
+        super.init();
+        
         setAttribute(CONFIG_SERVER_CLUSTER, addChild(EntitySpec.create(MongoDBConfigServerCluster.class)
                 .configure(DynamicCluster.INITIAL_SIZE, getConfig(CONFIG_CLUSTER_SIZE))));
         setAttribute(ROUTER_CLUSTER, addChild(EntitySpec.create(MongoDBRouterCluster.class)
@@ -62,11 +66,13 @@ public class MongoDBShardedDeploymentImpl extends AbstractEntity implements Mong
                 .propagating(MongoDBConfigServerCluster.CONFIG_SERVER_ADDRESSES)
                 .from(getAttribute(CONFIG_SERVER_CLUSTER))
                 .build());
+        
+        ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL, "stopped");
     }
 
     @Override
     public void start(Collection<? extends Location> locations) {
-        setAttribute(Attributes.SERVICE_STATE, Lifecycle.STARTING);
+        ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING);
         try {
             final MongoDBRouterCluster routers = getAttribute(ROUTER_CLUSTER);
             final MongoDBShardCluster shards = getAttribute(SHARD_CLUSTER);
@@ -79,10 +85,10 @@ public class MongoDBShardedDeploymentImpl extends AbstractEntity implements Mong
                         .displayName("Co-located router tracker")
                         .configure("group", (Group)getConfig(MongoDBShardedDeployment.CO_LOCATED_ROUTER_GROUP)));
             }
-            setAttribute(SERVICE_UP, true);
-            setAttribute(Attributes.SERVICE_STATE, Lifecycle.RUNNING);
+            ServiceNotUpLogic.clearNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL);
+            ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING);
         } catch (Exception e) {
-            setAttribute(Attributes.SERVICE_STATE, Lifecycle.ON_FIRE);
+            ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
             // no need to log here; the effector invocation should do that
             throw Exceptions.propagate(e);
         }
@@ -103,16 +109,16 @@ public class MongoDBShardedDeploymentImpl extends AbstractEntity implements Mong
 
     @Override
     public void stop() {
-        setAttribute(Attributes.SERVICE_STATE, Lifecycle.STOPPING);
+        ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING);
         try {
             Entities.invokeEffectorList(this, ImmutableList.of(getAttribute(CONFIG_SERVER_CLUSTER), getAttribute(ROUTER_CLUSTER), 
                     getAttribute(SHARD_CLUSTER)), Startable.STOP).get();
         } catch (Exception e) {
-            setAttribute(Attributes.SERVICE_STATE, Lifecycle.ON_FIRE);
+            ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
             throw Exceptions.propagate(e);
         }
-        setAttribute(Attributes.SERVICE_STATE, Lifecycle.STOPPED);
-        setAttribute(SERVICE_UP, false);
+        ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPED);
+        ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL, "stopped");
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/software/nosql/src/test/java/brooklyn/entity/nosql/cassandra/CassandraFabricTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/brooklyn/entity/nosql/cassandra/CassandraFabricTest.java b/software/nosql/src/test/java/brooklyn/entity/nosql/cassandra/CassandraFabricTest.java
index 4437faf..f4a786a 100644
--- a/software/nosql/src/test/java/brooklyn/entity/nosql/cassandra/CassandraFabricTest.java
+++ b/software/nosql/src/test/java/brooklyn/entity/nosql/cassandra/CassandraFabricTest.java
@@ -36,6 +36,7 @@ import brooklyn.entity.basic.EmptySoftwareProcess;
 import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.basic.EntityLocal;
 import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.basic.ServiceStateLogic;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.proxying.ImplementedBy;
 import brooklyn.entity.trait.Startable;
@@ -168,12 +169,12 @@ public class CassandraFabricTest extends BrooklynAppUnitTestSupport {
 
         @Override
         public void start(Collection<? extends Location> locations) {
-            setAttribute(Attributes.SERVICE_STATE, Lifecycle.STARTING);
+            ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING);
         }
 
         @Override
         public void stop() {
-            setAttribute(Attributes.SERVICE_STATE, Lifecycle.STOPPING);
+            ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING);
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsService.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsService.java b/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsService.java
index 2b70f7c..0f053bc 100644
--- a/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsService.java
+++ b/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsService.java
@@ -38,7 +38,7 @@ public interface AbstractGeoDnsService extends Entity {
     public static final ConfigKey<Boolean> INCLUDE_HOMELESS_ENTITIES = ConfigKeys.newBooleanConfigKey("geodns.includeHomeless", "Whether to include entities whose geo-coordinates cannot be inferred", false);
     public static final ConfigKey<Boolean> USE_HOSTNAMES = ConfigKeys.newBooleanConfigKey("geodns.useHostnames", "Whether to use the hostname for the returned value for routing, rather than IP address (defaults to true)", true);
     
-    public static final AttributeSensor<Lifecycle> SERVICE_STATE = Attributes.SERVICE_STATE;
+    public static final AttributeSensor<Lifecycle> SERVICE_STATE_ACTUAL = Attributes.SERVICE_STATE_ACTUAL;
     public static final AttributeSensor<Boolean> SERVICE_UP = Startable.SERVICE_UP;
     public static final AttributeSensor<String> HOSTNAME = Attributes.HOSTNAME;
     public static final AttributeSensor<String> ADDRESS = Attributes.ADDRESS;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java b/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
index 3d632aa..f931bb1 100644
--- a/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
@@ -41,6 +41,8 @@ import brooklyn.entity.basic.AbstractEntity;
 import brooklyn.entity.basic.Attributes;
 import brooklyn.entity.basic.DynamicGroup;
 import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.basic.ServiceStateLogic;
+import brooklyn.entity.basic.ServiceStateLogic.ServiceNotUpLogic;
 import brooklyn.entity.group.AbstractMembershipTrackingPolicy;
 import brooklyn.entity.webapp.WebAppService;
 import brooklyn.location.geo.HostGeoInfo;
@@ -104,8 +106,11 @@ public abstract class AbstractGeoDnsServiceImpl extends AbstractEntity implement
     @Override
     public void setServiceState(Lifecycle state) {
         setAttribute(HOSTNAME, getHostname());
-        setAttribute(SERVICE_STATE, state);
-        setAttribute(SERVICE_UP, state==Lifecycle.RUNNING);
+        ServiceStateLogic.setExpectedState(this, state);
+        if (state==Lifecycle.RUNNING)
+            ServiceNotUpLogic.clearNotUpIndicator(this, SERVICE_STATE_ACTUAL);
+        else
+            ServiceNotUpLogic.updateNotUpIndicator(this, SERVICE_STATE_ACTUAL, "Not in RUNNING state");
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/software/webapp/src/main/java/brooklyn/entity/dns/geoscaling/GeoscalingDnsServiceImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/dns/geoscaling/GeoscalingDnsServiceImpl.java b/software/webapp/src/main/java/brooklyn/entity/dns/geoscaling/GeoscalingDnsServiceImpl.java
index 024d01b..7e470ca 100644
--- a/software/webapp/src/main/java/brooklyn/entity/dns/geoscaling/GeoscalingDnsServiceImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/dns/geoscaling/GeoscalingDnsServiceImpl.java
@@ -28,6 +28,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.basic.ServiceStateLogic;
 import brooklyn.entity.dns.AbstractGeoDnsServiceImpl;
 import brooklyn.entity.dns.geoscaling.GeoscalingWebClient.Domain;
 import brooklyn.entity.dns.geoscaling.GeoscalingWebClient.SmartSubdomain;
@@ -69,9 +70,9 @@ public class GeoscalingDnsServiceImpl extends AbstractGeoDnsServiceImpl implemen
         try {
             applyConfig();
         } catch (Exception e) {
-            // don't prevent management coming up
+            // don't prevent management coming up, but do mark it as on fire
             log.error("Geoscaling did not come up correctly: "+e, e);
-            setAttribute(SERVICE_STATE, Lifecycle.ON_FIRE);
+            ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE);
         }
         super.onManagementBecomingMaster();
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java
index df0fd6a..bda6bd9 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java
@@ -52,6 +52,7 @@ import brooklyn.management.Task;
 import brooklyn.policy.Policy;
 import brooklyn.policy.autoscaling.AutoScalerPolicy;
 import brooklyn.test.Asserts;
+import brooklyn.test.EntityTestUtils;
 import brooklyn.util.ResourceUtils;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;
@@ -167,7 +168,7 @@ public class JavaWebAppsIntegrationTest {
             log.info("App started:");
             Entities.dumpInfo(app);
 
-            Assert.assertEquals(app.getAttribute(Attributes.SERVICE_STATE), Lifecycle.RUNNING);
+            EntityTestUtils.assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
             Assert.assertEquals(app.getAttribute(Attributes.SERVICE_UP), Boolean.TRUE);
             
             final String url = Asserts.succeedsEventually(MutableMap.of("timeout", Duration.TEN_SECONDS), new Callable<String>() {
@@ -240,7 +241,7 @@ public class JavaWebAppsIntegrationTest {
             Assert.assertEquals(policy.getConfig(AutoScalerPolicy.METRIC_UPPER_BOUND), (Integer)100);
             Assert.assertTrue(policy.isRunning());
 
-            Assert.assertEquals(app.getAttribute(Attributes.SERVICE_STATE), Lifecycle.RUNNING);
+            EntityTestUtils.assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
             Assert.assertEquals(app.getAttribute(Attributes.SERVICE_UP), Boolean.TRUE);
             
             final String url = Asserts.succeedsEventually(MutableMap.of("timeout", Duration.TEN_SECONDS), new Callable<String>() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/VanillaBashNetcatYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/VanillaBashNetcatYamlTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/VanillaBashNetcatYamlTest.java
index 950c465..336b5fc 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/VanillaBashNetcatYamlTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/VanillaBashNetcatYamlTest.java
@@ -68,7 +68,7 @@ public class VanillaBashNetcatYamlTest extends AbstractYamlTest {
         Entity netcat = Iterables.getOnlyElement(netcatI);
         
         // make sure netcat is running
-        EntityTestUtils.assertAttributeEventually(netcat, Attributes.SERVICE_STATE, Predicates.equalTo(Lifecycle.RUNNING));
+        EntityTestUtils.assertAttributeEventually(netcat, Attributes.SERVICE_STATE_ACTUAL, Predicates.equalTo(Lifecycle.RUNNING));
         
         // find the pinger, now comparing by name
         Iterable<Entity> pingerI = Iterables.filter(app.getChildren(), EntityPredicates.displayNameEqualTo("Simple Pinger"));
@@ -85,10 +85,10 @@ public class VanillaBashNetcatYamlTest extends AbstractYamlTest {
             netcat.getAttribute(SENSOR_OUTPUT_ALL));
 
         // netcat should now fail and restart
-        EntityTestUtils.assertAttributeEventually(netcat, Attributes.SERVICE_STATE, Predicates.not(Predicates.equalTo(Lifecycle.RUNNING)));
-        log.info("detected failure, state is: "+netcat.getAttribute(Attributes.SERVICE_STATE));
-        EntityTestUtils.assertAttributeEventually(netcat, Attributes.SERVICE_STATE, Predicates.equalTo(Lifecycle.RUNNING));
-        log.info("detected recovery, state is: "+netcat.getAttribute(Attributes.SERVICE_STATE));
+        EntityTestUtils.assertAttributeEventually(netcat, Attributes.SERVICE_STATE_ACTUAL, Predicates.not(Predicates.equalTo(Lifecycle.RUNNING)));
+        log.info("detected failure, state is: "+netcat.getAttribute(Attributes.SERVICE_STATE_ACTUAL));
+        EntityTestUtils.assertAttributeEventually(netcat, Attributes.SERVICE_STATE_ACTUAL, Predicates.equalTo(Lifecycle.RUNNING));
+        log.info("detected recovery, state is: "+netcat.getAttribute(Attributes.SERVICE_STATE_ACTUAL));
 
         // invoke effector again, now with a parameter
         ping = pinger.invoke(EFFECTOR_SAY_HI, MutableMap.<String,Object>of("message", "yo yo yo"));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java b/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java
index bb54d06..93b69f2 100644
--- a/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java
+++ b/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java
@@ -121,7 +121,7 @@ public class BrooklynEntityMirrorIntegrationTest {
         EntityTestUtils.assertAttributeEqualsEventually(mirror, TestApplication.MY_ATTRIBUTE, "bermuda");
 
         serverApp.stop();
-        EntityTestUtils.assertAttributeEqualsEventually(mirror, Attributes.SERVICE_STATE, Lifecycle.ON_FIRE);
+        EntityTestUtils.assertAttributeEqualsEventually(mirror, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
     }
 
     
@@ -156,7 +156,7 @@ public class BrooklynEntityMirrorIntegrationTest {
         EntityTestUtils.assertAttributeEqualsEventually(mirror, TestApplication.MY_ATTRIBUTE, "bermuda");
 
         serverApp.stop();
-        EntityTestUtils.assertAttributeEqualsEventually(mirror, Attributes.SERVICE_STATE, Lifecycle.ON_FIRE);
+        EntityTestUtils.assertAttributeEqualsEventually(mirror, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/099a5496/usage/rest-server/src/main/java/brooklyn/rest/resources/ApplicationResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/ApplicationResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/ApplicationResource.java
index e4314fc..d6554e4 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/ApplicationResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/ApplicationResource.java
@@ -111,7 +111,7 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements
         Boolean serviceUp = entity.getAttribute(Attributes.SERVICE_UP);
         if (serviceUp!=null) aRoot.put("serviceUp", serviceUp);
 
-        Lifecycle serviceState = entity.getAttribute(Attributes.SERVICE_STATE);
+        Lifecycle serviceState = entity.getAttribute(Attributes.SERVICE_STATE_ACTUAL);
         if (serviceState!=null) aRoot.put("serviceState", serviceState.toString());
 
         String iconUrl = entity.getIconUrl();