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 2016/02/01 18:51:29 UTC

[47/51] [abbrv] [partial] brooklyn-server git commit: move subdir from incubator up a level as it is promoted to its own repo (first non-incubator commit!)

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementPlaneSyncRecordPersister.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementPlaneSyncRecordPersister.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementPlaneSyncRecordPersister.java
new file mode 100644
index 0000000..16ff913
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementPlaneSyncRecordPersister.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.ha;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoPersister;
+import org.apache.brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Controls the persisting and reading back of mementos relating to the management plane.
+ * This state does not relate to the entities being managed.
+ * 
+ * @see {@link HighAvailabilityManager#setPersister(ManagementPlaneSyncRecordPersister)} for its use in management-node failover
+ * 
+ * @since 0.7.0
+ */
+@Beta
+public interface ManagementPlaneSyncRecordPersister {
+
+    /**
+     * Analogue to {@link BrooklynMementoPersister#loadMemento(org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoPersister.LookupContext)}
+     * <p>
+     * Note that this method is *not* thread safe.
+     */
+    ManagementPlaneSyncRecord loadSyncRecord() throws IOException;
+    
+    void delta(Delta delta);
+
+    void stop();
+
+    @VisibleForTesting
+    void waitForWritesCompleted(Duration timeout) throws InterruptedException, TimeoutException;
+    
+    public interface Delta {
+        public enum MasterChange {
+            NO_CHANGE,
+            SET_MASTER,
+            CLEAR_MASTER
+        }
+        Collection<ManagementNodeSyncRecord> getNodes();
+        Collection<String> getRemovedNodeIds();
+        MasterChange getMasterChange();
+        String getNewMasterOrNull();
+        String getExpectedMasterToClear();
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/MementoCopyMode.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/MementoCopyMode.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/MementoCopyMode.java
new file mode 100644
index 0000000..320c264
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/MementoCopyMode.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.ha;
+
+public enum MementoCopyMode {
+    /** Use items currently managed at this node */ 
+    LOCAL,
+    /** Use items as stored in the remote persistence store */ 
+    REMOTE, 
+    /** Auto-detect whether to use {@link #LOCAL} or {@link #REMOTE} depending on the
+     * HA mode of this management node (usually {@link #LOCAL} for master and {@link #REMOTE} otherwise)*/ 
+    AUTO 
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/ChangeListener.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/ChangeListener.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/ChangeListener.java
new file mode 100644
index 0000000..ce26a82
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/ChangeListener.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind;
+
+import org.apache.brooklyn.api.objs.BrooklynObject;
+
+/**
+ * Listener to be notified of changes within brooklyn, so that the new state
+ * of the entity/location/policy can be persisted.
+ * 
+ * Users are not expected to implement this class. It is for use by the {@link RebindManager}.
+ * 
+ * @author aled
+ */
+public interface ChangeListener {
+
+    public static final ChangeListener NOOP = new ChangeListener() {
+        @Override public void onChanged(BrooklynObject instance) {}
+        @Override public void onManaged(BrooklynObject instance) {}
+        @Override public void onUnmanaged(BrooklynObject instance) {}
+    };
+
+    void onManaged(BrooklynObject instance);
+    
+    void onUnmanaged(BrooklynObject instance);
+    
+    void onChanged(BrooklynObject instance);
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/PersistenceExceptionHandler.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/PersistenceExceptionHandler.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/PersistenceExceptionHandler.java
new file mode 100644
index 0000000..759bca6
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/PersistenceExceptionHandler.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind;
+
+import org.apache.brooklyn.api.mgmt.rebind.mementos.Memento;
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.objs.BrooklynObjectType;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Handler called on all exceptions to do with persistence.
+ * 
+ * @author aled
+ */
+@Beta
+public interface PersistenceExceptionHandler {
+
+    void stop();
+
+    void onGenerateMementoFailed(BrooklynObjectType type, BrooklynObject instance, Exception e);
+    
+    void onPersistMementoFailed(Memento memento, Exception e);
+    
+    void onPersistRawMementoFailed(BrooklynObjectType type, String id, Exception e);
+
+    void onDeleteMementoFailed(String id, Exception e);
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindContext.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindContext.java
new file mode 100644
index 0000000..d928da0
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindContext.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoPersister.LookupContext;
+import org.apache.brooklyn.api.objs.BrooklynObject;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Gives access to things that are being currently rebinding. This is used during a
+ * rebind to wire everything back together again, e.g. to find the necessary entity 
+ * instances even before they are available through 
+ * {@code managementContext.getEntityManager().getEnties()}.
+ * <p>
+ * Users are not expected to implement this class. It is for use by {@link Rebindable} 
+ * instances, and will generally be created by the {@link RebindManager}.
+ * <p>
+ */
+@Beta
+public interface RebindContext {
+
+    /** Returns an unmodifiable view of all objects by ID */ 
+    Map<String,BrooklynObject> getAllBrooklynObjects();
+    
+    Class<?> loadClass(String typeName) throws ClassNotFoundException;
+    
+    RebindExceptionHandler getExceptionHandler();
+    
+    boolean isReadOnly(BrooklynObject item);
+    
+    LookupContext lookup();
+    
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java
new file mode 100644
index 0000000..574a680
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind;
+
+import java.util.List;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntityLocal;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.mgmt.rebind.mementos.EntityMemento;
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.objs.BrooklynObjectType;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.sensor.Enricher;
+import org.apache.brooklyn.api.sensor.Feed;
+
+import com.google.common.annotations.Beta;
+import org.apache.brooklyn.config.ConfigKey;
+
+/**
+ * Handler called on all exceptions to do with rebind.
+ * A handler instance is linked to a single rebind pass;
+ * it should not be invoked after {@link #onDone()}.
+ * <p>
+ * {@link #onStart()} must be invoked before the run.
+ * {@link #onDone()} must be invoked after a successful run, and it may throw.
+ * <p>
+ * Implementations may propagate errors or may catch them until {@link #onDone()} is invoked,
+ * and that may throw or report elsewhere, as appropriate.
+ * 
+ * @author aled
+ */
+@Beta
+public interface RebindExceptionHandler {
+
+    void onLoadMementoFailed(BrooklynObjectType type, String msg, Exception e);
+    
+    /**
+     * @return the entity to use in place of the missing one, or null (if hasn't thrown an exception)
+     */
+    Entity onDanglingEntityRef(String id);
+
+    /**
+     * @return the location to use in place of the missing one, or null (if hasn't thrown an exception)
+     */
+    Location onDanglingLocationRef(String id);
+
+    /**
+     * @return the policy to use in place of the missing one, or null (if hasn't thrown an exception)
+     */
+    Policy onDanglingPolicyRef(String id);
+
+    /**
+     * @return the enricher to use in place of the missing one, or null (if hasn't thrown an exception)
+     */
+    Enricher onDanglingEnricherRef(String id);
+
+    /**
+     * @return the feed to use in place of the missing one, or null (if hasn't thrown an exception)
+     */
+    Feed onDanglingFeedRef(String id);
+    
+    /**
+     * @return the catalog item to use in place of the missing one
+     */
+    CatalogItem<?, ?> onDanglingCatalogItemRef(String id);
+
+    /**
+     * @return the item to use in place of the missing one
+     */
+    BrooklynObject onDanglingUntypedItemRef(String id);
+
+    void onCreateFailed(BrooklynObjectType type, String id, String instanceType, Exception e);
+
+    void onNotFound(BrooklynObjectType type, String id);
+
+    void onRebindFailed(BrooklynObjectType type, BrooklynObject instance, Exception e);
+
+    void onAddConfigFailed(EntityMemento type, ConfigKey<?> value, Exception e);
+
+    void onAddPolicyFailed(EntityLocal entity, Policy policy, Exception e);
+
+    void onAddEnricherFailed(EntityLocal entity, Enricher enricher, Exception e);
+
+    void onAddFeedFailed(EntityLocal entity, Feed feed, Exception e);
+
+    void onManageFailed(BrooklynObjectType type, BrooklynObject instance, Exception e);
+
+    /** invoked for any high-level, unexpected, or otherwise uncaught failure;
+     * may be invoked on catching above errors */
+    RuntimeException onFailed(Exception e);
+
+    /** invoked before the rebind pass */
+    void onStart(RebindContext context);
+    
+    /** invoked after the complete rebind pass, always on success and possibly on failure */
+    void onDone();
+    
+    List<Exception> getExceptions();
+    List<String> getWarnings();
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindManager.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindManager.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindManager.java
new file mode 100644
index 0000000..c1441db
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindManager.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeoutException;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.mgmt.ha.ManagementNodeState;
+import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoPersister;
+import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoRawData;
+import org.apache.brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Manages the persisting of brooklyn's state, and recreating that state, e.g. on
+ * brooklyn restart.
+ * 
+ * Users are not expected to implement this class, or to call methods on it directly.
+ */
+public interface RebindManager {
+    
+    // FIXME Should we be calling managementContext.getRebindManager().rebind, using a
+    // new empty instance of managementContext?
+    //
+    // Or is that a risky API because you could call it on a non-empty managementContext?
+    
+    public enum RebindFailureMode {
+        FAIL_FAST,
+        FAIL_AT_END,
+        CONTINUE;
+    }
+    
+    public void setPersister(BrooklynMementoPersister persister);
+
+    public void setPersister(BrooklynMementoPersister persister, PersistenceExceptionHandler exceptionHandler);
+
+    @VisibleForTesting
+    public BrooklynMementoPersister getPersister();
+
+    /** @deprecated since 0.7; use {@link #rebind(ClassLoader, RebindExceptionHandler, ManagementNodeState)} */ @Deprecated
+    public List<Application> rebind();
+    
+    /** @deprecated since 0.7; use {@link #rebind(ClassLoader, RebindExceptionHandler, ManagementNodeState)} */ @Deprecated
+    public List<Application> rebind(ClassLoader classLoader);
+    /** @deprecated since 0.7; use {@link #rebind(ClassLoader, RebindExceptionHandler, ManagementNodeState)} */ @Deprecated
+    public List<Application> rebind(ClassLoader classLoader, RebindExceptionHandler exceptionHandler);
+    /** Causes this management context to rebind, loading data from the given backing store.
+     * use wisely, as this can cause local entities to be completely lost, or will throw in many other situations.
+     * in general it may be invoked for a new node becoming {@link ManagementNodeState#MASTER} 
+     * or periodically for a node in {@link ManagementNodeState#HOT_STANDBY} or {@link ManagementNodeState#HOT_BACKUP}. */
+    @Beta
+    public List<Application> rebind(ClassLoader classLoader, RebindExceptionHandler exceptionHandler, ManagementNodeState mode);
+
+    public BrooklynMementoRawData retrieveMementoRawData();
+
+    public ChangeListener getChangeListener();
+
+    /**
+     * Starts the background persisting of state
+     * (if persister is set; otherwise will start persisting as soon as persister is set). 
+     * Until this is called, no data will be persisted although entities can be rebinded.
+     */
+    public void startPersistence();
+
+    /** Stops the background persistence of state. 
+     * Waits for any current persistence to complete. */
+    public void stopPersistence();
+
+    /**
+     * Perform an initial load of state read-only and starts a background process 
+     * reading (mirroring) state periodically.
+     */
+    public void startReadOnly(ManagementNodeState mode);
+    /** Stops the background reading (mirroring) of state. 
+     * Interrupts any current activity and waits for it to cease. */
+    public void stopReadOnly();
+    
+    /** Starts the appropriate background processes, {@link #startPersistence()} if {@link ManagementNodeState#MASTER},
+     * {@link #startReadOnly()} if {@link ManagementNodeState#HOT_STANDBY} or {@link ManagementNodeState#HOT_BACKUP} */
+    public void start();
+    /** Stops the appropriate background processes, {@link #stopPersistence()} or {@link #stopReadOnly()},
+     * waiting for activity there to cease (interrupting in the case of {@link #stopReadOnly()}). */
+    public void stop();
+    
+    @VisibleForTesting
+    /** waits for any needed or pending writes to complete */
+    public void waitForPendingComplete(Duration duration, boolean canTrigger) throws InterruptedException, TimeoutException;
+    /** Forcibly performs persistence, in the foreground 
+     * @deprecated since 0.7.0; use {@link #forcePersistNow(boolean, PersistenceExceptionHandler)}, 
+     * default parameter here is false to mean incremental, with null/default exception handler */
+    @VisibleForTesting
+    public void forcePersistNow();
+    /** Forcibly performs persistence, in the foreground, either full (all entities) or incremental;
+     * if no exception handler specified, the default one from the persister is used.
+     * <p>
+     * Note that full persistence does *not* delete items; incremental should normally be sufficient.
+     * (A clear then full persistence would have the same effect, but that is risky in a production
+     * setting if the process fails after the clear!) */
+    @VisibleForTesting
+    public void forcePersistNow(boolean full, @Nullable PersistenceExceptionHandler exceptionHandler);
+    
+    /** Whether the management state has changed to a state where a rebind is needed
+     * but we are still awaiting the first run; 
+     * ie state is master or hot, but list of apps is not yet accurate */
+    public boolean isAwaitingInitialRebind();
+
+    /** Metrics about rebind, last success, etc. */
+    public Map<String,Object> getMetrics();
+    
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindSupport.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindSupport.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindSupport.java
new file mode 100644
index 0000000..2e8fdbf
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindSupport.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind;
+
+import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoPersister;
+import org.apache.brooklyn.api.mgmt.rebind.mementos.Memento;
+
+/**
+ * Supporter instance for behaviour related to rebinding a given entity/location/policy.
+ * 
+ * For example, the brooklyn framework may call {@code entity.getRebindSupport().getMemento()}
+ * and persist this using a {@link BrooklynMementoPersister}. Later (e.g. after a brooklyn
+ * restart) a new entity instance may be created and populated by the framework calling 
+ * {@code entity.getRebindSupport().reconstruct(rebindContext, memento)}.
+ * 
+ * @author aled
+ */
+public interface RebindSupport<T extends Memento> {
+
+    /**
+     * Creates a memento representing this entity's current state. This is useful for when restarting brooklyn.
+     */
+    T getMemento();
+
+    /**
+     * Reconstructs this entity, given a memento of its state. Sets the internal state 
+     * (including id and config keys), and sets the parent/children/locations of this entity.
+     * 
+     * Implementations should be very careful to not invoke or inspect these other entities/locations,
+     * as they may also be being reconstructed at this time.
+     * 
+     * Called during rebind, after creation and before the call to start management.
+     */
+    void reconstruct(RebindContext rebindContext, T memento);
+
+    void addPolicies(RebindContext rebindContext, T Memento);
+    
+    void addEnrichers(RebindContext rebindContext, T Memento);
+    
+    void addFeeds(RebindContext rebindContext, T Memento);
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/Rebindable.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/Rebindable.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/Rebindable.java
new file mode 100644
index 0000000..301e8e0
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/Rebindable.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind;
+
+import org.apache.brooklyn.api.mgmt.rebind.mementos.Memento;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Indicates that this can be recreated, e.g. after a brooklyn restart, and by
+ * using a {@link Memento} it can repopulate the brooklyn objects. The purpose
+ * of the rebind is to reconstruct and reconnect the brooklyn objects, including
+ * binding them to external resources.
+ * 
+ * Users are strongly discouraged to call or use this interface.
+ * It is for internal use only, relating to persisting/rebinding entities.
+ * This interface may change (or be removed) in a future release without notice.
+ */
+@Beta
+public interface Rebindable {
+
+    public RebindSupport<?> getRebindSupport();
+    
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMemento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMemento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMemento.java
new file mode 100644
index 0000000..1c66c70
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMemento.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind.mementos;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Represents an entire persisted Brooklyn management context, with all its entities and locations.
+ * 
+ * The referential integrity of this memento is not guaranteed. For example, an entity memento might
+ * reference a child entity that does not exist. This is an inevitable consequence of not using a
+ * stop-the-world persistence strategy, and is essential for a distributed brooklyn to be performant.
+ * 
+ * Code using this memento should be tolerant of such inconsistencies (e.g. log a warning about the 
+ * missing entity, and then ignore dangling references when constructing the entities/locations, so
+ * that code will not subsequently get NPEs when iterating over children for example).
+ * 
+ * @author aled
+ */
+public interface BrooklynMemento extends Serializable {
+
+    public EntityMemento getEntityMemento(String id);
+    public LocationMemento getLocationMemento(String id);
+    public PolicyMemento getPolicyMemento(String id);
+    public EnricherMemento getEnricherMemento(String id);
+    public FeedMemento getFeedMemento(String id);
+    public CatalogItemMemento getCatalogItemMemento(String id);
+
+    public Collection<String> getApplicationIds();
+    public Collection<String> getTopLevelLocationIds();
+
+    public Collection<String> getEntityIds();
+    public Collection<String> getLocationIds();
+    public Collection<String> getPolicyIds();
+    public Collection<String> getEnricherIds();
+    public Collection<String> getFeedIds();
+    public Collection<String> getCatalogItemIds();
+
+    public Map<String, EntityMemento> getEntityMementos();
+    public Map<String, LocationMemento> getLocationMementos();
+    public Map<String, PolicyMemento> getPolicyMementos();
+    public Map<String, EnricherMemento> getEnricherMementos();
+    public Map<String, FeedMemento> getFeedMementos();
+    public Map<String, CatalogItemMemento> getCatalogItemMementos();
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoManifest.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoManifest.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoManifest.java
new file mode 100644
index 0000000..2efc6f6
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoManifest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind.mementos;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.brooklyn.api.objs.Identifiable;
+
+/**
+ * Represents a manifest of the entities etc in the overall memento.
+ * 
+ * @author aled
+ */
+public interface BrooklynMementoManifest extends Serializable {
+    public interface EntityMementoManifest extends Identifiable{
+        public String getId();
+        public String getType();
+        public String getParent();
+        public String getCatalogItemId();
+    }
+
+    public Map<String, EntityMementoManifest> getEntityIdToManifest();
+
+    public Map<String, String> getLocationIdToType();
+
+    public Map<String, String> getPolicyIdToType();
+
+    public Map<String, String> getEnricherIdToType();
+
+    public Map<String, String> getFeedIdToType();
+    
+    public CatalogItemMemento getCatalogItemMemento(String id);
+
+    public Collection<String> getCatalogItemIds();
+
+    public Map<String, CatalogItemMemento> getCatalogItemMementos();
+
+    public boolean isEmpty();
+    
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java
new file mode 100644
index 0000000..03673fd
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind.mementos;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.TimeoutException;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.rebind.PersistenceExceptionHandler;
+import org.apache.brooklyn.api.mgmt.rebind.RebindExceptionHandler;
+import org.apache.brooklyn.api.mgmt.rebind.RebindManager;
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.objs.BrooklynObjectType;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.sensor.Enricher;
+import org.apache.brooklyn.api.sensor.Feed;
+import org.apache.brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Controls the persisting and reading back of mementos. Used by {@link RebindManager} 
+ * to support brooklyn restart.
+ */
+public interface BrooklynMementoPersister {
+
+    public static interface LookupContext {
+        ManagementContext lookupManagementContext();
+        Entity lookupEntity(String id);
+        Location lookupLocation(String id);
+        Policy lookupPolicy(String id);
+        Enricher lookupEnricher(String id);
+        Feed lookupFeed(String id);
+        CatalogItem<?, ?> lookupCatalogItem(String id);
+        
+        /** retrieve the item with the given ID, optionally ensuring it is of the indicated type; null if not found */
+        BrooklynObject lookup(@Nullable BrooklynObjectType type, String objectId);
+        /** like {@link #lookup(BrooklynObjectType, String)} but doesn't record an exception if not found */
+        BrooklynObject peek(@Nullable BrooklynObjectType type, String objectId);
+    }
+    
+    /**
+     * Loads raw data contents of the mementos.
+     * <p>
+     * Some classes (esp deprecated ones) may return null here,
+     * meaning that the {@link #loadMementoManifest(BrooklynMementoRawData, RebindExceptionHandler)}
+     * and {@link #loadMemento(BrooklynMementoRawData, LookupContext, RebindExceptionHandler)} methods
+     * will populate the raw data via another source.
+     */
+    BrooklynMementoRawData loadMementoRawData(RebindExceptionHandler exceptionHandler);
+
+    /**
+     * Loads minimal manifest information (almost entirely *not* deserialized).
+     * Implementations should load the raw data if {@link BrooklynMementoRawData} is not supplied,
+     * but callers are encouraged to supply that for optimal performance.
+     */
+    BrooklynMementoManifest loadMementoManifest(@Nullable BrooklynMementoRawData mementoData, RebindExceptionHandler exceptionHandler) throws IOException;
+
+     /**
+      * Retrieves the memento class, containing deserialized objects (but not the {@link BrooklynObject} class).
+      * Implementations should load the raw data if {@link BrooklynMementoRawData} is not supplied,
+      * but callers are encouraged to supply that for optimal performance.
+      * <p>
+      * Note that this method is *not* thread safe.
+      */
+    BrooklynMemento loadMemento(@Nullable BrooklynMementoRawData mementoData, LookupContext lookupContext, RebindExceptionHandler exceptionHandler) throws IOException;
+
+    /** applies a full checkpoint (write) of all state */  
+    void checkpoint(BrooklynMementoRawData newMemento, PersistenceExceptionHandler exceptionHandler);
+    /** applies a partial write of state delta */  
+    void delta(Delta delta, PersistenceExceptionHandler exceptionHandler);
+    /** inserts an additional delta to be written on the next delta request */
+    @Beta
+    void queueDelta(Delta delta);
+
+    void enableWriteAccess();
+    void disableWriteAccess(boolean graceful);
+    /** permanently shuts down all access to the remote store */
+    void stop(boolean graceful);
+
+    @VisibleForTesting
+    void waitForWritesCompleted(Duration timeout) throws InterruptedException, TimeoutException;
+
+    String getBackingStoreDescription();
+    
+    /** All methods on this interface are unmodifiable by the caller. Sub-interfaces may introduce modifiers. */
+    // NB: the type-specific methods aren't actually used anymore; we could remove them to simplify the impl (and use a multiset there)
+    public interface Delta {
+        Collection<LocationMemento> locations();
+        Collection<EntityMemento> entities();
+        Collection<PolicyMemento> policies();
+        Collection<EnricherMemento> enrichers();
+        Collection<FeedMemento> feeds();
+        Collection<CatalogItemMemento> catalogItems();
+        
+        Collection<String> removedLocationIds();
+        Collection<String> removedEntityIds();
+        Collection<String> removedPolicyIds();
+        Collection<String> removedEnricherIds();
+        Collection<String> removedFeedIds();
+        Collection<String> removedCatalogItemIds();
+        
+        Collection<? extends Memento> getObjectsOfType(BrooklynObjectType type);
+        Collection<String> getRemovedIdsOfType(BrooklynObjectType type);
+    }
+    
+    @Beta
+    public interface MutableDelta extends Delta {
+        void add(BrooklynObjectType type, Memento memento);
+        void addAll(BrooklynObjectType type, Iterable<? extends Memento> memento);
+        void removed(BrooklynObjectType type, Set<String> removedIdsOfType);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoRawData.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoRawData.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoRawData.java
new file mode 100644
index 0000000..804304d
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoRawData.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind.mementos;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.brooklyn.api.objs.BrooklynObjectType;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Maps;
+
+/**
+ * Represents the raw persisted data.
+ */
+@Beta
+public class BrooklynMementoRawData {
+
+    // TODO Should this be on an interface?
+    // The file-based (or object-store based) structure for storing data may well change; is this representation sufficient?
+
+    public static Builder builder() {
+        return new Builder();
+    }
+    
+    public static class Builder {
+        protected String brooklynVersion;
+        protected final Map<String, String> entities = Maps.newConcurrentMap();
+        protected final Map<String, String> locations = Maps.newConcurrentMap();
+        protected final Map<String, String> policies = Maps.newConcurrentMap();
+        protected final Map<String, String> enrichers = Maps.newConcurrentMap();
+        protected final Map<String, String> feeds = Maps.newConcurrentMap();
+        protected final Map<String, String> catalogItems = Maps.newConcurrentMap();
+        
+        public Builder brooklynVersion(String val) {
+            brooklynVersion = val; return this;
+        }
+        public Builder entity(String id, String val) {
+            entities.put(id, val); return this;
+        }
+        public Builder entities(Map<String, String> vals) {
+            entities.putAll(vals); return this;
+        }
+        public Builder location(String id, String val) {
+            locations.put(id, val); return this;
+        }
+        public Builder locations(Map<String, String> vals) {
+            locations.putAll(vals); return this;
+        }
+        public Builder policy(String id, String val) {
+            policies.put(id, val); return this;
+        }
+        public Builder policies(Map<String, String> vals) {
+            policies.putAll(vals); return this;
+        }
+        public Builder enricher(String id, String val) {
+            enrichers.put(id, val); return this;
+        }
+        public Builder enrichers(Map<String, String> vals) {
+            enrichers.putAll(vals); return this;
+        }
+        public Builder feed(String id, String val) {
+            feeds.put(id, val); return this;
+        }
+        public Builder feeds(Map<String, String> vals) {
+            feeds.putAll(vals); return this;
+        }
+        public Builder catalogItem(String id, String val) {
+            catalogItems.put(id, val); return this;
+        }
+        public Builder catalogItems(Map<String, String> vals) {
+            catalogItems.putAll(vals); return this;
+        }
+        
+        public Builder put(BrooklynObjectType type, String id, String val) {
+            switch (type) {
+            case ENTITY: return entity(id, val);
+            case LOCATION: return location(id, val);
+            case POLICY: return policy(id, val);
+            case ENRICHER: return enricher(id, val);
+            case FEED: return feed(id, val);
+            case CATALOG_ITEM: return catalogItem(id, val);
+            case UNKNOWN:
+            default:
+                throw new IllegalArgumentException(type+" not supported");
+            }
+        }
+        public Builder putAll(BrooklynObjectType type, Map<String,String> vals) {
+            switch (type) {
+            case ENTITY: return entities(vals);
+            case LOCATION: return locations(vals);
+            case POLICY: return policies(vals);
+            case ENRICHER: return enrichers(vals);
+            case FEED: return feeds(vals);
+            case CATALOG_ITEM: return catalogItems(vals);
+            case UNKNOWN:
+            default:
+                throw new IllegalArgumentException(type+" not supported");
+            }
+        }
+
+        public BrooklynMementoRawData build() {
+            return new BrooklynMementoRawData(this);
+        }
+    }
+
+    private final Map<String, String> entities;
+    private final Map<String, String> locations;
+    private final Map<String, String> policies;
+    private final Map<String, String> enrichers;
+    private final Map<String, String> feeds;
+    private final Map<String, String> catalogItems;
+    
+    private BrooklynMementoRawData(Builder builder) {
+        entities = builder.entities;
+        locations = builder.locations;
+        policies = builder.policies;
+        enrichers = builder.enrichers;
+        feeds = builder.feeds;
+        catalogItems = builder.catalogItems;
+    }
+
+    public Map<String, String> getEntities() {
+        return Collections.unmodifiableMap(entities);
+    }
+
+    public Map<String, String> getLocations() {
+        return Collections.unmodifiableMap(locations);
+    }
+
+    public Map<String, String> getPolicies() {
+        return Collections.unmodifiableMap(policies);
+    }
+
+    public Map<String, String> getEnrichers() {
+        return Collections.unmodifiableMap(enrichers);
+    }
+    
+    public Map<String, String> getFeeds() {
+        return Collections.unmodifiableMap(feeds);
+    }
+    
+    public Map<String, String> getCatalogItems() {
+        return Collections.unmodifiableMap(catalogItems);
+    }
+    
+    // to handle reset catalog
+    @Beta
+    public void clearCatalogItems() {
+        catalogItems.clear();
+    }
+    
+    public boolean isEmpty() {
+        return entities.isEmpty() && locations.isEmpty() && policies.isEmpty() && enrichers.isEmpty() && feeds.isEmpty() && catalogItems.isEmpty();
+    }
+    
+    public Map<String, String> getObjectsOfType(BrooklynObjectType type) {
+        switch (type) {
+        case ENTITY: return getEntities();
+        case LOCATION: return getLocations();
+        case POLICY: return getPolicies();
+        case ENRICHER: return getEnrichers();
+        case FEED: return getFeeds();
+        case CATALOG_ITEM: return getCatalogItems();
+        default:
+            throw new IllegalArgumentException("Type "+type+" not supported");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/CatalogItemMemento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/CatalogItemMemento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/CatalogItemMemento.java
new file mode 100644
index 0000000..57fbb8d
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/CatalogItemMemento.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind.mementos;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.objs.SpecParameter;
+
+public interface CatalogItemMemento extends Memento {
+
+    String getDescription();
+
+    String getSymbolicName();
+
+    String getIconUrl();
+
+    String getVersion();
+
+    String getPlanYaml();
+
+    String getJavaType();
+
+    List<SpecParameter<?>> getParameters();
+
+    Collection<CatalogItem.CatalogBundle> getLibraries();
+
+    CatalogItem.CatalogItemType getCatalogItemType();
+
+    Class<?> getCatalogItemJavaType();
+
+    Class<?> getSpecType();
+
+    boolean isDeprecated();
+
+    boolean isDisabled();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/EnricherMemento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/EnricherMemento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/EnricherMemento.java
new file mode 100644
index 0000000..c6b7e8c
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/EnricherMemento.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind.mementos;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
+
+/**
+ * Represents the state of an enricher, so that it can be reconstructed (e.g. after restarting brooklyn).
+ * 
+ * @see RebindSupport
+ */
+public interface EnricherMemento extends Memento {
+
+    Map<String, Object> getConfig();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/EntityMemento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/EntityMemento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/EntityMemento.java
new file mode 100644
index 0000000..4c74695
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/EntityMemento.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind.mementos;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.api.effector.Effector;
+import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.config.ConfigKey;
+
+/**
+ * Represents the state of an entity, so that it can be reconstructed (e.g. after restarting brooklyn).
+ * 
+ * @see RebindSupport
+ * 
+ * @author aled
+ */
+public interface EntityMemento extends Memento, TreeNode {
+
+    /** all dynamic effectors (ie differences between those registered on the entity type */ 
+    public List<Effector<?>> getEffectors();
+
+    public Map<ConfigKey<?>, Object> getConfig();
+
+    /** true if the entity is top-level (parentless) and an application
+     * (there may be parentless "orphaned" entities, for which this is false,
+     * and "application" instances nested inside other apps, for which this is again)
+     */
+    public boolean isTopLevelApp();
+    
+    public Map<String, Object> getConfigUnmatched();
+    
+    public Map<AttributeSensor<?>, Object> getAttributes();
+
+    /**
+     * The ids of the member entities, if this is a Group; otherwise empty.
+     * 
+     * @see Group.getMembers()
+     */
+    public List<String> getMembers();
+    
+    /**
+     * The ids of the locations for this entity.
+     */
+    public List<String> getLocations();
+
+    /**
+     * The ids of the policies of this entity.
+     */
+    public Collection<String> getPolicies();
+
+    /**
+     * The ids of the enrichers of this entity.
+     */
+    public Collection<String> getEnrichers();
+
+    /**
+     * The ids of the sensor feeds attached to this entity.
+     */
+    public Collection<String> getFeeds();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/FeedMemento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/FeedMemento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/FeedMemento.java
new file mode 100644
index 0000000..52424c3
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/FeedMemento.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind.mementos;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
+
+/**
+ * Represents the state of a feed, so that it can be reconstructed (e.g. after restarting brooklyn).
+ * 
+ * @see RebindSupport
+ */
+public interface FeedMemento extends Memento {
+
+    Map<String, Object> getConfig();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/LocationMemento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/LocationMemento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/LocationMemento.java
new file mode 100644
index 0000000..016db01
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/LocationMemento.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind.mementos;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
+
+/**
+ * Represents the state of a location, so that it can be reconstructed (e.g. after restarting brooklyn).
+ * 
+ * @see RebindSupport
+ * 
+ * @author aled
+ */
+public interface LocationMemento extends TreeNode, Memento {
+
+    Map<String, Object> getLocationConfig();
+    Set<String> getLocationConfigUnused();
+    String getLocationConfigDescription();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java
new file mode 100644
index 0000000..5911f28
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind.mementos;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
+import org.apache.brooklyn.api.objs.EntityAdjunct;
+
+/**
+ * Represents the internal state of something in brooklyn, so that it can be reconstructed (e.g. after restarting brooklyn).
+ * 
+ * @see RebindSupport
+ * 
+ * @author aled
+ */
+public interface Memento extends Serializable {
+
+    /**
+     * The version of brooklyn used when this memento was generated.
+     */
+    String getBrooklynVersion();
+    
+    String getId();
+    
+    public String getType();
+    
+    public String getCatalogItemId();
+    
+    public String getDisplayName();
+    
+    /**
+     * A (weakly-typed) property set for this memento.
+     * These can be used to avoid sub-classing the entity memento, but developers can sub-class to get strong typing if desired.
+     * 
+     * @deprecated since 0.7.0; use config/attributes so generic persistence will work, rather than requiring "custom fields"
+     */
+    @Deprecated
+    public Object getCustomField(String name);
+
+    /**
+     * @deprecated since 0.7.0; use config/attributes so generic persistence will work, rather than requiring "custom fields"
+     */
+    @Deprecated
+    public Map<String, ? extends Object> getCustomFields();
+    
+    public String toVerboseString();
+    
+    public void injectTypeClass(Class<?> clazz);
+    
+    /**
+     * Returns the injected type class, or null if not injected.
+     * <p>
+     * This is useful for ensuring the correct classloader is used (e.g. for {@link EntityMemento} 
+     * previously calling {@code EntityTypes.getDefinedSensors(getType())}. 
+     */
+    public Class<?> getTypeClass();
+
+    public Collection<Object> getTags();
+    
+    public Map<String,Set<String>> getRelations();
+    
+    /** Null for {@link Entity}, but important for adjuncts; see {@link EntityAdjunct#getUniqueTag()} */
+    public String getUniqueTag();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/PolicyMemento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/PolicyMemento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/PolicyMemento.java
new file mode 100644
index 0000000..bfec7af
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/PolicyMemento.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind.mementos;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
+
+/**
+ * Represents the state of an policy, so that it can be reconstructed (e.g. after restarting brooklyn).
+ * 
+ * @see RebindSupport
+ * 
+ * @author aled
+ */
+public interface PolicyMemento extends Memento {
+
+    Map<String, Object> getConfig();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/TreeNode.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/TreeNode.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/TreeNode.java
new file mode 100644
index 0000000..cde6a34
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/TreeNode.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.mgmt.rebind.mementos;
+
+import java.util.List;
+
+/**
+ * A simple tree structure, where a node references a parent and children using their ids.
+ * 
+ * e.g. could be used to represent the entity hierarchy within mementos, where the 
+ * String is the id of parent/child entities.
+ * 
+ * @author aled
+ */
+public interface TreeNode {
+
+    /**
+     * The id of this node in the tree. This id will be used by the parent's getChildren(), 
+     * and by each child's getParent().
+     */
+    String getId();
+    
+    /**
+     * The id of the parent entity, or null if none.
+     */
+    String getParent();
+    
+    /**
+     * The ids of the children.
+     */
+    List<String> getChildren();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java
new file mode 100644
index 0000000..b42bc58
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.objs;
+
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
+import org.apache.brooklyn.api.mgmt.SubscriptionContext;
+import org.apache.brooklyn.api.mgmt.SubscriptionHandle;
+import org.apache.brooklyn.api.mgmt.SubscriptionManager;
+import org.apache.brooklyn.api.relations.RelationshipType;
+import org.apache.brooklyn.api.sensor.Sensor;
+import org.apache.brooklyn.api.sensor.SensorEventListener;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Super-type of entity, location, policy and enricher.
+ */
+public interface BrooklynObject extends Identifiable, Configurable {
+    
+    /**
+     * A display name; recommended to be a concise single-line description.
+     */
+    String getDisplayName();
+
+    /**
+     * The catalog item ID this object was loaded from.
+     * <p>
+     * This can be used to understand the appropriate classloading context,
+     * such as for versioning purposes, as well as meta-information such as 
+     * branding (maybe you can even get an icon) and 
+     * potentially things like resource lifecycle (if a software version is being sunsetted).
+     * <p>
+     * In some cases this may be set heuristically from context and so may not be accurate.
+     * Callers can set an explicit catalog item ID if inferencing is not correct.
+     */
+    String getCatalogItemId();
+    
+    /** 
+     * Tags are arbitrary objects which can be attached to an entity for subsequent reference.
+     * They must not be null (as {@link ImmutableMap} may be used under the covers; also there is little point!);
+     * and they should be amenable to our persistence (on-disk serialization) and our JSON serialization in the REST API.
+     */
+    TagSupport tags();
+
+    /**
+     * Subscriptions are the mechanism for receiving notifications of sensor-events (e.g. attribute-changed) from 
+     * other entities.
+     */
+    SubscriptionSupport subscriptions();
+
+    /**
+     * Relations specify a typed, directed connection between two entities.
+     * Generic type is overridden in sub-interfaces.
+     */
+    public RelationSupport<?> relations();
+    
+    public interface TagSupport {
+        /**
+         * @return An immutable copy of the set of tags on this entity. 
+         * Note {@link #containsTag(Object)} will be more efficient,
+         * and {@link #addTag(Object)} and {@link #removeTag(Object)} will not work on the returned set.
+         */
+        @Nonnull Set<Object> getTags();
+        
+        boolean containsTag(@Nonnull Object tag);
+        
+        boolean addTag(@Nonnull Object tag);
+        
+        boolean addTags(@Nonnull Iterable<?> tags);
+        
+        boolean removeTag(@Nonnull Object tag);
+    }
+    
+    @Beta
+    public interface SubscriptionSupport {
+        /**
+         * Allow us to subscribe to data from a {@link Sensor} on another entity.
+         * 
+         * @return a subscription id which can be used to unsubscribe
+         *
+         * @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener)
+         */
+        @Beta
+        <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
+     
+        /**
+         * Allow us to subscribe to data from a {@link Sensor} on another entity.
+         * 
+         * @return a subscription id which can be used to unsubscribe
+         *
+         * @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener)
+         */
+        @Beta
+        <T> SubscriptionHandle subscribe(Map<String, ?> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
+
+        /** @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener) */
+        @Beta
+        <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
+     
+        /** @see SubscriptionManager#subscribeToMembers(Group, Sensor, SensorEventListener) */
+        @Beta
+        <T> SubscriptionHandle subscribeToMembers(Group group, Sensor<T> sensor, SensorEventListener<? super T> listener);
+
+        /**
+         * Unsubscribes from the given producer.
+         *
+         * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+         */
+        @Beta
+        boolean unsubscribe(Entity producer);
+
+        /**
+         * Unsubscribes the given handle.
+         *
+         * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+         */
+        @Beta
+        boolean unsubscribe(Entity producer, SubscriptionHandle handle);
+        
+        /**
+         * Unsubscribes the given handle.
+         * 
+         * It is (currently) more efficient to also pass in the producer -
+         * see {@link SubscriptionSupport#unsubscribe(Entity, SubscriptionHandle)} 
+         */
+        boolean unsubscribe(SubscriptionHandle handle);
+    }
+    
+    public interface RelationSupport<T extends BrooklynObject> {
+        /** Adds a relationship of the given type from this object pointing at the given target, 
+         * and ensures that the inverse relationship (if there is one) is present at the target pointing back at this object. 
+         */
+        public <U extends BrooklynObject> void add(RelationshipType<? super T,? super U> relationship, U target);
+        
+        /** Removes any and all relationships of the given type from this object pointing at the given target,
+         * and ensures that the inverse relationships (if there are one) are also removed. 
+         */
+        public <U extends BrooklynObject> void remove(RelationshipType<? super T,? super U> relationship, U target);
+        
+        /** @return the {@link RelationshipType}s originating from this object */
+        public Set<RelationshipType<? super T,? extends BrooklynObject>> getRelationshipTypes();
+        
+        /** @return the {@link BrooklynObject}s which are targets of the given {@link RelationshipType} */
+        public <U extends BrooklynObject> Set<U> getRelations(RelationshipType<? super T,U> relationshipType);
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObjectType.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObjectType.java b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObjectType.java
new file mode 100644
index 0000000..e0ef84c
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObjectType.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.objs;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.api.sensor.Enricher;
+import org.apache.brooklyn.api.sensor.EnricherSpec;
+import org.apache.brooklyn.api.sensor.Feed;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.CaseFormat;
+
+@Beta
+public enum BrooklynObjectType {
+    // these are correctly type-checked by i can't tell how to get java not to warn!
+    @SuppressWarnings("unchecked") ENTITY(Entity.class, EntitySpec.class, "entities"),
+    @SuppressWarnings("unchecked") LOCATION(Location.class, LocationSpec.class, "locations"),
+    @SuppressWarnings("unchecked") POLICY(Policy.class, PolicySpec.class, "policies"),
+    @SuppressWarnings("unchecked") ENRICHER(Enricher.class, EnricherSpec.class, "enrichers"),
+    FEED(Feed.class, null, "feeds"),
+    CATALOG_ITEM(CatalogItem.class, null, "catalog"),
+    UNKNOWN(null, null, "unknown");
+    
+    private final Class<? extends BrooklynObject> interfaceType;
+    private final Class<? extends AbstractBrooklynObjectSpec<?,?>> specType;
+    private final String subPathName;
+    
+    <T extends BrooklynObject,K extends AbstractBrooklynObjectSpec<T,K>> BrooklynObjectType(Class<T> interfaceType, Class<K> specType, String subPathName) {
+        this.interfaceType = interfaceType;
+        this.specType = specType;
+        this.subPathName = subPathName;
+    }
+    public String toCamelCase() {
+        return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, this.name());
+    }
+
+    public String getSubPathName() {
+        return subPathName;
+    }
+    
+    public Class<? extends BrooklynObject> getInterfaceType() {
+        return interfaceType;
+    }
+    
+    public Class<? extends AbstractBrooklynObjectSpec<?, ?>> getSpecType() {
+        return specType;
+    }
+    
+    public static BrooklynObjectType of(BrooklynObject instance) {
+        for (BrooklynObjectType t: values()) {
+            if (t.getInterfaceType()!=null && t.getInterfaceType().isInstance(instance))
+                return t;
+        }
+        return UNKNOWN;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynType.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynType.java b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynType.java
new file mode 100644
index 0000000..72d0be9
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynType.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.objs;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import org.apache.brooklyn.config.ConfigKey;
+
+/**
+ * Gives type information for a {@link BrooklynObject}. It is an immutable snapshot.
+ * 
+ * It reflects a given brooklyn object at the time the snapshot was created: if anything
+ * were added or removed on-the-fly then those changes will be included in subsequent
+ * snapshots. Therefore instances of a given class could have different {@link BrooklynType}s.
+ */
+// TODO rename as BrooklynObjectSignature or BrooklynObjectMetadata;
+// or (perhaps better and easier to retire deprecated usage, if that is required?)
+// introduce new mechanism for storing accessing this information
+public interface BrooklynType extends Serializable {
+
+    /**
+     * The type name of this entity (normally the fully qualified class name).
+     */
+    String getName();
+    
+    /**
+     * The simple type name of this entity (normally the unqualified class name).
+     */
+    String getSimpleName();
+
+    /**
+     * ConfigKeys available on this entity.
+     */
+    Set<ConfigKey<?>> getConfigKeys();
+    
+    /**
+     * The ConfigKey with the given name, or null if not found.
+     */
+    ConfigKey<?> getConfigKey(String name);
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
new file mode 100644
index 0000000..d7f2935
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.objs;
+
+import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Something that has mutable config, such as an entity or policy.
+ * 
+ * @author aled
+ */
+public interface Configurable {
+
+    // FIXME Moved from core project to api project, as part of moving EntityLocal.
+    // (though maybe it's fine here?)
+
+    /**
+     * @return the old value, or null if there was not one
+     * @deprecated since 0.7.0; use {@link ConfigurationSupport#set(ConfigKey, Object)}, such as {@code config().set(key, val)} 
+     */
+    @Deprecated
+    public <T> T setConfig(ConfigKey<T> key, T val);
+
+    /**
+     * Convenience for calling {@link ConfigurationSupport#get(ConfigKey)},
+     * via code like {@code config().get(key)}.
+     * 
+     * @since 0.9.0
+     */
+    <T> T getConfig(ConfigKey<T> key);
+
+    ConfigurationSupport config();
+    
+    @Beta
+    public interface ConfigurationSupport {
+
+        /**
+         * Gets the given configuration value for this entity, in the following order of precedence:
+         * <ol>
+         *   <li> value (including null) explicitly set on the entity
+         *   <li> value (including null) explicitly set on an ancestor (inherited)
+         *   <li> a default value (including null) on the best equivalent static key of the same name declared on the entity
+         *        (where best equivalence is defined as preferring a config key which extends another, 
+         *        as computed in EntityDynamicType.getConfigKeys)
+         *   <li> a default value (including null) on the key itself
+         *   <li> null
+         * </ol>
+         */
+        <T> T get(ConfigKey<T> key);
+        
+        /**
+         * @see {@link #getConfig(ConfigKey)}
+         */
+        <T> T get(HasConfigKey<T> key);
+
+        /**
+         * Sets the config to the given value.
+         */
+        <T> T set(ConfigKey<T> key, T val);
+        
+        /**
+         * @see {@link #setConfig(HasConfigKey, Object)}
+         */
+        <T> T set(HasConfigKey<T> key, T val);
+        
+        /**
+         * Sets the config to the value returned by the task.
+         * 
+         * Returns immediately without blocking; subsequent calls to {@link #getConfig(ConfigKey)} 
+         * will execute the task, and block until the task completes.
+         * 
+         * @see {@link #setConfig(ConfigKey, Object)}
+         */
+        <T> T set(ConfigKey<T> key, Task<T> val);
+        
+        /**
+         * @see {@link #setConfig(ConfigKey, Task)}
+         */
+        <T> T set(HasConfigKey<T> key, Task<T> val);
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/objs/EntityAdjunct.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/EntityAdjunct.java b/api/src/main/java/org/apache/brooklyn/api/objs/EntityAdjunct.java
new file mode 100644
index 0000000..674d7f2
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/objs/EntityAdjunct.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.objs;
+
+import javax.annotation.Nullable;
+
+/**
+ * EntityAdjuncts are supplementary logic that can be attached to Entities, 
+ * such as providing sensor enrichment or event-driven policy behavior
+ */
+public interface EntityAdjunct extends BrooklynObject {
+    /**
+     * A unique id for this adjunct, typically created by the system with no meaning
+     */
+    @Override
+    String getId();
+
+    /**
+     * Whether the adjunct is destroyed
+     */
+    boolean isDestroyed();
+    
+    /**
+     * Whether the adjunct is available/active, ie started and not stopped or interrupted
+     */
+    boolean isRunning();
+    
+    /**
+     * An optional tag used to identify adjuncts with a specific purpose, typically created by the caller.
+     * This is used to prevent multiple instances with the same purpose from being created,
+     * and to access and customize adjuncts so created.
+     * <p>
+     * This will be included in the call to {@link #getTags()}.
+     */
+    @Nullable String getUniqueTag();
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/objs/HasShortName.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/HasShortName.java b/api/src/main/java/org/apache/brooklyn/api/objs/HasShortName.java
new file mode 100644
index 0000000..3d13337
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/objs/HasShortName.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.api.objs;
+
+public interface HasShortName {
+
+    /** gets a short name, for human-friendly identification e.g. inside the name of a VM */
+    String getShortName();
+    
+}