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:30 UTC

[48/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/AccessController.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/AccessController.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/AccessController.java
new file mode 100644
index 0000000..331d990
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/AccessController.java
@@ -0,0 +1,65 @@
+/*
+ * 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;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.Location;
+
+import com.google.common.annotations.Beta;
+
+@Beta
+public interface AccessController {
+
+    // TODO Expect this class' methods to change, e.g. including the user doing the
+    // provisioning or the provisioning parameters such as jurisdiction
+    
+    public static class Response {
+        private static final Response ALLOWED = new Response(true, "");
+        
+        public static Response allowed() {
+            return ALLOWED;
+        }
+        
+        public static Response disallowed(String msg) {
+            return new Response(false, msg);
+        }
+        
+        private final boolean allowed;
+        private final String msg;
+
+        private Response(boolean allowed, String msg) {
+            this.allowed = allowed;
+            this.msg = msg;
+        }
+        
+        public boolean isAllowed() {
+            return allowed;
+        }
+        
+        public String getMsg() {
+            return msg;
+        }
+    }
+
+    public Response canProvisionLocation(Location provisioner);
+
+    public Response canManageLocation(Location loc);
+    
+    public Response canManageEntity(Entity entity);
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/EntityManager.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/EntityManager.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/EntityManager.java
new file mode 100644
index 0000000..fe66a5b
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/EntityManager.java
@@ -0,0 +1,126 @@
+/*
+ * 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;
+
+import java.util.Collection;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.entity.EntityTypeRegistry;
+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 com.google.common.base.Predicate;
+
+/**
+ * For managing and querying entities.
+ */
+public interface EntityManager {
+
+    /**
+     * Returns the type registry, used to identify the entity implementation when instantiating an
+     * entity of a given type.
+     * 
+     * @see EntityManager.createEntity(EntitySpec)
+     */
+    EntityTypeRegistry getEntityTypeRegistry();
+    
+    /**
+     * Creates a new entity. Management is started immediately (by this method).
+     * 
+     * @param spec
+     * @return A proxy to the created entity (rather than the actual entity itself).
+     */
+    <T extends Entity> T createEntity(EntitySpec<T> spec);
+    
+    /**
+     * Convenience (particularly for groovy code) to create an entity.
+     * Equivalent to {@code createEntity(EntitySpec.create(type).configure(config))}
+     * 
+     * @see createEntity(EntitySpec)
+     */
+    <T extends Entity> T createEntity(Map<?,?> config, Class<T> type);
+
+    /**
+     * Creates a new policy (not managed; not associated with any entity).
+     * 
+     * @param spec
+     */
+    <T extends Policy> T createPolicy(PolicySpec<T> spec);
+
+    /**
+     * Creates a new enricher (not managed; not associated with any entity).
+     * 
+     * @param spec
+     */
+    <T extends Enricher> T createEnricher(EnricherSpec<T> spec);
+
+    /**
+     * All entities under control of this management plane
+     */
+    Collection<Entity> getEntities();
+
+    /**
+     * All entities managed as part of the given application
+     */
+    Collection<Entity> getEntitiesInApplication(Application application);
+
+    /**
+     * All entities under control of this management plane that match the given filter
+     */
+    Collection<Entity> findEntities(Predicate<? super Entity> filter);
+
+    /**
+     * All entities managed as part of the given application that match the given filter
+     */
+    Collection<Entity> findEntitiesInApplication(Application application, Predicate<? super Entity> filter);
+
+    /**
+     * Returns the entity with the given identifier (may be a full instance, or a proxy to one which is remote),
+     * or null.
+     */
+    @Nullable Entity getEntity(String id);
+    
+    /** whether the entity is under management by this management context */
+    boolean isManaged(Entity entity);
+
+    /**
+     * Begins management for the given entity and its children, recursively.
+     *
+     * depending on the implementation of the management context,
+     * this might push it out to one or more remote management nodes.
+     * Manage an entity.
+     */
+    // TODO manage and unmanage without arguments should be changed to take an explicit ManagementTransitionMode
+    // (but that class is not currently in the API project)
+    void manage(Entity e);
+    
+    /**
+     * Causes the given entity and its children, recursively, to be removed from the management plane
+     * (for instance because the entity is no longer relevant)
+     */
+    void unmanage(Entity e);
+    
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/ExecutionContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/ExecutionContext.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/ExecutionContext.java
new file mode 100644
index 0000000..4540240
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/ExecutionContext.java
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+
+import org.apache.brooklyn.api.entity.Entity;
+
+/**
+ * This is a Brooklyn extension to the Java {@link Executor}.
+ * 
+ * The "context" could, for example, be an {@link Entity} so that tasks executed 
+ * can be annotated as executing in that context.
+ */
+public interface ExecutionContext extends Executor {
+
+    /**
+     * Get the tasks executed through this context (returning an immutable set).
+     */
+    Set<Task<?>> getTasks();
+
+    /**
+     * See {@link ExecutionManager#submit(Map, TaskAdaptable)} for properties that can be passed in.
+     */
+    Task<?> submit(Map<?,?> properties, Runnable runnable);
+
+    /**
+     * See {@link ExecutionManager#submit(Map, TaskAdaptable)} for properties that can be passed in.
+     */
+    <T> Task<T> submit(Map<?,?> properties, Callable<T> callable);
+
+    /** {@link ExecutionManager#submit(Runnable) */
+    Task<?> submit(Runnable runnable);
+ 
+    /** {@link ExecutionManager#submit(Callable) */
+    <T> Task<T> submit(Callable<T> callable);
+
+    /** See {@link ExecutionManager#submit(Map, TaskAdaptable)}. */
+    <T> Task<T> submit(TaskAdaptable<T> task);
+    
+    /**
+     * See {@link ExecutionManager#submit(Map, TaskAdaptable)} for properties that can be passed in.
+     */
+    <T> Task<T> submit(Map<?,?> properties, TaskAdaptable<T> task);
+
+    boolean isShutdown();
+
+}
\ 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/mgmt/ExecutionManager.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/ExecutionManager.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/ExecutionManager.java
new file mode 100644
index 0000000..4988721
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/ExecutionManager.java
@@ -0,0 +1,117 @@
+/*
+ * 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;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+
+import org.apache.brooklyn.api.entity.Entity;
+
+/** 
+ * This class manages the execution of a number of jobs with tags.
+ * 
+ * It is like an executor service (and it ends up delegating to one) but adds additional support
+ * where jobs can be:
+ * <ul>
+ * <li>Tracked with tags/buckets
+ * <li>Be {@link Runnable}s, {@link Callable}s, or {@link groovy.lang.Closure}s
+ * <li>Remembered after completion
+ * <li>Treated as {@link Task} instances (see below)
+ * <li>Given powerful synchronization capabilities
+ * </ul>
+ * <p>
+ * The advantage of treating them as {@link Task} instances include: 
+ * <ul>
+ * <li>Richer status information
+ * <li>Started-by, contained-by relationships automatically remembered
+ * <li>Runtime metadata (start, stop, etc)
+ * <li>Grid and multi-machine support) 
+ * </ul>
+ * <p>
+ * For usage instructions see {@link #submit(Map, TaskAdaptable)}, and for examples see the various
+ * {@code ExecutionTest} and {@code TaskTest} instances.
+ * <p>
+ * It has been developed for multi-location provisioning and management to track work being
+ * done by each {@link Entity}.
+ * <p>
+ * Note the use of the environment variable {@code THREAD_POOL_SIZE} which is used to size
+ * the {@link ExecutorService} thread pool. The default is calculated as twice the number
+ * of CPUs in the system plus two, giving 10 for a four core system, 18 for an eight CPU
+ * server and so on.
+ */
+public interface ExecutionManager {
+    public boolean isShutdown();
+    
+    /** returns the task with the given ID, or null if none */ 
+    public Task<?> getTask(String id);
+    
+    /** returns all tasks with the given tag (immutable) */
+    public Set<Task<?>> getTasksWithTag(Object tag);
+
+    /** returns all tasks that have any of the given tags (immutable) */
+    public Set<Task<?>> getTasksWithAnyTag(Iterable<?> tags);
+
+    /** returns all tasks that have all of the given tags (immutable) */
+    public Set<Task<?>> getTasksWithAllTags(Iterable<?> tags);
+
+    /** returns all tags known to this manager (immutable) */
+    public Set<Object> getTaskTags();
+
+//    /** returns all tasks known to this manager (immutable) */
+//    public Set<Task<?>> getAllTasks();
+
+    /** see {@link #submit(Map, TaskAdaptable)} */
+    public Task<?> submit(Runnable r);
+
+    /** see {@link #submit(Map, TaskAdaptable)} */
+    public <T> Task<T> submit(Callable<T> c);
+
+    /** see {@link #submit(Map, TaskAdaptable)} */
+    public <T> Task<T> submit(TaskAdaptable<T> task);
+    
+    /** see {@link #submit(Map, TaskAdaptable)} */
+    public Task<?> submit(Map<?, ?> flags, Runnable r);
+
+    /** see {@link #submit(Map, TaskAdaptable)} */
+    public <T> Task<T> submit(Map<?, ?> flags, Callable<T> c);
+
+    /**
+     * Submits the given {@link Task} for execution in the context associated with this manager.
+     *
+     * The following optional flags supported (in the optional map first arg):
+     * <ul>
+     * <li><em>tag</em> - A single object to be used as a tag for looking up the task
+     * <li><em>tags</em> - A {@link Collection} of object tags each of which the task should be associated,
+     *                      used for associating with contexts, mutex execution, and other purposes
+     * <li><em>synchId</em> - A string, or {@link Collection} of strings, representing a category on which an object should own a synch lock 
+     * <li><em>synchObj</em> - A string, or {@link Collection} of strings, representing a category on which an object should own a synch lock 
+     * <li><em>newTaskStartCallback</em> - A {@link groovy.lang.Closure} that will be invoked just before the task starts if it starts as a result of this call
+     * <li><em>newTaskEndCallback</em> - A {@link groovy.lang.Closure} that will be invoked when the task completes if it starts as a result of this call
+     * </ul>
+     * Callbacks run in the task's thread, and if the callback is a {@link groovy.lang.Closure} it is passed the task for convenience. The closure can be any of the
+     * following types; either a {@link groovy.lang.Closure}, {@link Runnable} or {@link Callable}.
+     * <p>
+     * If a Map is supplied it must be modifiable (currently; may allow immutable maps in future). 
+     */
+    public <T> Task<T> submit(Map<?, ?> flags, TaskAdaptable<T> task);
+
+}
\ 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/mgmt/HasTaskChildren.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/HasTaskChildren.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/HasTaskChildren.java
new file mode 100644
index 0000000..52f9735
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/HasTaskChildren.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+import com.google.common.annotations.Beta;
+
+/** 
+ * Interface marks tasks which have explicit children,
+ * typically where the task defines the ordering of running those children tasks
+ * <p>
+ * The {@link Task#getSubmittedByTask()} on the child will typically return the parent,
+ * but note there are other means of submitting tasks (e.g. background, in the same {@link ExecutionContext}),
+ * where the submitter has no API reference to the submitted tasks.
+ * <p>
+ * In general the children mechanism is preferred as it is easier to navigate
+ * (otherwise you have to scan the {@link ExecutionContext} to find tasks submitted by a task).  
+ */
+@Beta // in 0.6.0
+public interface HasTaskChildren {
+
+    public Iterable<Task<?>> getChildren();
+    
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/LocationManager.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/LocationManager.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/LocationManager.java
new file mode 100644
index 0000000..9d20a34
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/LocationManager.java
@@ -0,0 +1,87 @@
+/*
+ * 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;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+
+/**
+ * For managing and querying entities.
+ */
+public interface LocationManager {
+
+    /**
+     * Creates a new location, which is tracked by the management context.
+     * 
+     * @param spec
+     */
+    <T extends Location> T createLocation(LocationSpec<T> spec);
+
+    /**
+     * Convenience (particularly for groovy code) to create a location.
+     * Equivalent to {@code createLocation(LocationSpec.create(type).configure(config))}
+     * 
+     * @see #createLocation(LocationSpec)
+     */
+    <T extends Location> T createLocation(Map<?,?> config, Class<T> type);
+
+    /**
+     * All locations under control of this management plane.
+     * 
+     * This returns a snapshot of the current locations; it will not reflect future changes in the locations.
+     * If no locations are found, the collection will be empty (i.e. null is never returned).
+     */
+    Collection<Location> getLocations();
+
+    /**
+     * Returns the location under management (e.g. in use) with the given identifier 
+     * (e.g. random string; and different to the LocationDefinition id).
+     * May return a full instance, or a proxy to one which is remote.
+     * If no location found with that id, returns null.
+     */
+    Location getLocation(String id);
+    
+    /** whether the location is under management by this management context */
+    boolean isManaged(Location loc);
+
+    /**
+     * Begins management for the given location and its children, recursively.
+     *
+     * depending on the implementation of the management context,
+     * this might push it out to one or more remote management nodes.
+     * Manage a location.
+     * 
+     * @since 0.6.0 (added only for backwards compatibility, where locations are being created directly).
+     * @deprecated in 0.6.0; use {@link #createLocation(LocationSpec)} instead.
+     */
+    Location manage(Location loc);
+    
+    /**
+     * Causes the given location and its children, recursively, to be removed from the management plane
+     * (for instance because the location is no longer relevant).
+     * 
+     * If the given location is not managed (e.g. it has already been unmanaged) then this is a no-op 
+     * (though it may be logged so duplicate calls are best avoided).
+     */
+    void unmanage(Location loc);
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/ManagementContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/ManagementContext.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/ManagementContext.java
new file mode 100644
index 0000000..cabadee
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/ManagementContext.java
@@ -0,0 +1,267 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.net.URI;
+import java.util.Collection;
+
+import org.apache.brooklyn.api.catalog.BrooklynCatalog;
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.drivers.DriverDependentEntity;
+import org.apache.brooklyn.api.entity.drivers.EntityDriverManager;
+import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolverManager;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationRegistry;
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementManager;
+import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityManager;
+import org.apache.brooklyn.api.mgmt.rebind.RebindManager;
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry;
+import org.apache.brooklyn.config.StringConfigMap;
+import org.apache.brooklyn.util.guava.Maybe;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * This is the entry point for accessing and interacting with a realm of applications and their entities in Brooklyn.
+ *
+ * For example, policies and the management console(s) (web-app, etc) can use this to interact with entities; 
+ * policies, web-app, and entities share the realm for subscribing to events, executing tasks, and generally co-existing.      
+ * <p>
+ * It may refer to several applications, and it refers to all the entities descended from those applications.
+ */
+public interface ManagementContext {
+
+    // TODO Consider separating out into a ConfigManager for methods like:
+    //  - getConfig()
+    //  - reloadBrooklynProperties();
+    //  - addPropertiesReloadListener
+    //  - removePropertiesReloadListener
+    //  - interface PropertiesReloadListener
+    
+    /** 
+     * UID for the Brooklyn management plane which this {@link ManagementContext} node is a part of.
+     * <p>
+     * Each Brooklyn entity is actively managed by a unique management plane 
+     * whose ID which should not normally change for the duration of that entity, 
+     * even though the nodes in that plane might, and the plane may go down and come back up. 
+     * In other words the value of {@link Application#getManagementContext()#getManagementPlaneId()} 
+     * will generally be constant (in contrast to {@link #getManagementNodeId()}).
+     * <p>
+     * This value should not be null unless the management context is a non-functional
+     * (non-deployment) instance. */
+    String getManagementPlaneId();
+    
+    /** 
+     * UID for this {@link ManagementContext} node (as part of a single management plane).
+     * <p>
+     * No two instances of {@link ManagementContext} should ever have the same node UID. 
+     * The value of {@link Application#getManagementContext()#getManagementNodeId()} may
+     * change many times (in contrast to {@link #getManagementPlaneId()}). 
+     * <p>
+     * This value should not be null unless the management context is a non-functional
+     * (non-deployment) instance. */
+    String getManagementNodeId();
+
+    /**
+     * The URI that this management node's REST API is available at, or absent if the node's
+     * API is unavailable.
+     */
+    Maybe<URI> getManagementNodeUri();
+
+    /**
+     * All applications under control of this management plane
+     */
+    Collection<Application> getApplications();
+
+    /**
+     * Returns the {@link EntityManager} instance for managing/querying entities.
+     */
+    EntityManager getEntityManager();
+    
+    /**
+     * Returns the {@link ExecutionManager} instance for entities and users in this management realm 
+     * to submit tasks and to observe what tasks are occurring
+     */
+    ExecutionManager getExecutionManager();
+    
+    /** 
+     * Returns an {@link ExecutionContext} within the {@link ExecutionManager} for tasks
+     * associated to the Brooklyn node's operation (not any entities). 
+     **/
+    ExecutionContext getServerExecutionContext();
+
+    /**
+     * Returns the {@link EntityDriverManager} entities can use to create drivers. This
+     * manager can also be used to programmatically customize which driver type to use 
+     * for entities in different locations.
+     * 
+     * The default strategy for choosing a driver is to use a naming convention: 
+     * {@link DriverDependentEntity#getDriverInterface()} returns the interface that the
+     * driver must implement; its name should end in "Driver". For example, this suffix is 
+     * replaced with "SshDriver" for SshMachineLocation, for example.
+     */
+    EntityDriverManager getEntityDriverManager();
+
+    /**
+     * Returns the {@link DownloadResolverManager} for resolving things like which URL to download an installer from.
+     * 
+     * The default {@link DownloadResolverManager} will retrieve {@code entity.getAttribute(Attributes.DOWNLOAD_URL)},
+     * and substitute things like "${version}" etc.
+     * 
+     * However, additional resolvers can be registered to customize this behaviour (e.g. to always go to an 
+     * enterprise's repository).
+     */
+    DownloadResolverManager getEntityDownloadsManager();
+
+    /**
+     * Returns the {@link SubscriptionManager} instance for entities and users of this management realm
+     * to subscribe to sensor events (and, in the case of entities, to emit sensor events) 
+     */
+    SubscriptionManager getSubscriptionManager();
+
+    //TODO (Alex) I'm not sure the following two getXxxContext methods are needed on the interface;
+    //I expect they will only be called once, in AbstractEntity, and fully capable
+    //there of generating the respective contexts from the managers
+    //(Litmus test will be whether there is anything in FederatedManagementContext
+    //which requires a custom FederatedExecutionContext -- or whether BasicEC 
+    //works with FederatedExecutionManager)
+    /**
+     * Returns an {@link ExecutionContext} instance representing tasks 
+     * (from the {@link ExecutionManager}) associated with this entity, and capable 
+     * of conveniently running such tasks which will be associated with that entity  
+     */
+    ExecutionContext getExecutionContext(Entity entity);
+    
+    /**
+     * Returns a {@link SubscriptionContext} instance representing subscriptions
+     * (from the {@link SubscriptionManager}) associated with this entity, and capable 
+     * of conveniently subscribing on behalf of that entity  
+     */
+    SubscriptionContext getSubscriptionContext(Entity entity);
+
+    /**
+     * Returns a {@link SubscriptionContext} instance representing subscriptions
+     * (from the {@link SubscriptionManager}) associated with this location, and capable 
+     * of conveniently subscribing on behalf of that location  
+     */
+    @Beta
+    SubscriptionContext getSubscriptionContext(Location location);
+
+    @Beta // method may move to an internal interface; brooklyn users should not need to call this directly
+    RebindManager getRebindManager();
+
+    /**
+     * @since 0.7.0
+     */
+    @Beta // method may move to an internal interface; brooklyn users should not need to call this directly
+    HighAvailabilityManager getHighAvailabilityManager();
+    
+    /**
+     * Returns the ConfigMap (e.g. BrooklynProperties) applicable to this management context.
+     * Defaults to reading ~/.brooklyn/brooklyn.properties but configurable in the management context.
+     */
+    StringConfigMap getConfig();
+    
+    /**
+     * Whether the management context has been initialized and not yet terminated.
+     * This does not mean startup is entirely completed. See also {@link #isStartupComplete()}.
+     */
+    // TODO should we replace this with isNotYetTerminated() ??
+    // and perhaps introduce isFullyRunning() which does (isStartupComplete() && isRunning()),
+    // and/or move to a MgmtContextStatus subclass where errors can also be stored?
+    public boolean isRunning();
+    
+    /**
+     * Whether all startup tasks have completed. Previous to this point the management context is still usable 
+     * (and hence {@link #isRunning()} returns true immediately after construction)
+     * but some subsystems (e.g. persistence, OSGi, webapps, entities started at startup)
+     * may not be available until this returns true.
+     * <p>
+     * Also see {@link #isStartupComplete()}.
+     */
+    @Beta  // see comment on isRunning() as items might move to a status handler
+    public boolean isStartupComplete();
+
+    /** Record of configured locations and location resolvers */
+    LocationRegistry getLocationRegistry();
+    
+    /** Record of configured Brooklyn entities (and templates and policies) which can be loaded */
+    BrooklynCatalog getCatalog();
+
+    /** Record of configured classes which can be loaded */
+    BrooklynTypeRegistry getTypeRegistry();
+    
+    /** Returns the class loader to be used to load items. 
+     * Temporary routine while catalog supports classloader-based and OSGi-based classloading. */
+    @Beta
+    ClassLoader getCatalogClassLoader();
+
+    LocationManager getLocationManager();
+
+    /**
+     * For controlling access to operations - can be queried to find if an operation is allowed.
+     * Callers should *not* cache the result of this method, but should instead always call
+     * again to get the {@link AccessController}.
+     */
+    AccessController getAccessController();
+
+    /**
+     * Reloads locations from {@code brooklyn.properties}. Any changes will apply only to newly created applications
+     */
+    void reloadBrooklynProperties();
+
+    /**
+     * Listener for {@code brooklyn.properties} reload events.
+     *
+     * @see {@link #raddPropertiesReloadListenerPropertiesReloadListener)}
+     * @see {@link #removePropertiesReloadListener(PropertiesReloadListener)}
+     */
+    interface PropertiesReloadListener extends Serializable {
+
+        /** Called when {@code brooklyn.properties} is reloaded. */
+        void reloaded();
+
+    }
+    
+    /**
+     * Registers a listener to be notified when brooklyn.properties is reloaded
+     */
+    void addPropertiesReloadListener(PropertiesReloadListener listener);
+    
+    /**
+     * Deregisters a listener from brooklyn.properties reload notifications 
+     */
+    void removePropertiesReloadListener(PropertiesReloadListener listener);
+
+    /**
+     * Active entitlements checker instance.
+     */
+    EntitlementManager getEntitlementManager();
+ 
+    /** As {@link #lookup(String, Class)} but not constraining the return type */
+    public BrooklynObject lookup(String id);
+    
+    /** Finds an entity with the given ID known at this management context */
+    // TODO in future support policies etc
+    public <T extends BrooklynObject> T lookup(String id, Class<T> type); 
+
+}
\ 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/mgmt/SubscriptionContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/SubscriptionContext.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/SubscriptionContext.java
new file mode 100644
index 0000000..3328b1a
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/SubscriptionContext.java
@@ -0,0 +1,66 @@
+/*
+ * 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;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
+import org.apache.brooklyn.api.sensor.Sensor;
+import org.apache.brooklyn.api.sensor.SensorEvent;
+import org.apache.brooklyn.api.sensor.SensorEventListener;
+
+/**
+ * This is the context through which an {@link Entity} can manage its subscriptions.
+ */
+public interface SubscriptionContext {
+    /**
+     * As {@link SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener)} with default subscription parameters for this context
+     */
+    <T> SubscriptionHandle subscribe(Map<String, ?> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
+ 
+    /** @see #subscribe(Map, Entity, Sensor, SensorEventListener) */
+    <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
+    
+    /** @see #subscribe(Map, Entity, Sensor, SensorEventListener) */
+    <T> SubscriptionHandle subscribeToChildren(Map<String, Object> flags, Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
+ 
+    /** @see #subscribe(Map, Entity, Sensor, SensorEventListener) */
+    <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
+    
+    /** @see #subscribe(Map, Entity, Sensor, SensorEventListener) */
+    <T> SubscriptionHandle subscribeToMembers(Map<String, Object> flags, Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
+ 
+    /** @see #subscribe(Map, Entity, Sensor, SensorEventListener) */
+    <T> SubscriptionHandle subscribeToMembers(Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
+    
+    /** @see SubscriptionManager#unsubscribe(SubscriptionHandle) */
+    boolean unsubscribe(SubscriptionHandle subscriptionId);
+    
+    /** causes all subscriptions to be deregistered
+     * @return number of subscriptions removed */
+    int unsubscribeAll();
+
+    /** @see SubscriptionManager#publish(SensorEvent) */
+    <T> void publish(SensorEvent<T> event);
+
+    /** Return the subscriptions associated with this context */
+    Set<SubscriptionHandle> getSubscriptions();
+}
\ 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/mgmt/SubscriptionHandle.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/SubscriptionHandle.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/SubscriptionHandle.java
new file mode 100644
index 0000000..bb4de8c
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/SubscriptionHandle.java
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+/**
+ * A "receipt" returned by {@link SubscriptionContext} and {@link SubscriptionManager}'s {@code subscribe()} 
+ * methods. It can be used to unsubscribe - see {@link SubscriptionContext#unsubscribe(SubscriptionHandle)} 
+ * and {@link SubscriptionManager#unsubscribe(SubscriptionHandle)}.
+ */
+public interface SubscriptionHandle {
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/SubscriptionManager.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/SubscriptionManager.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/SubscriptionManager.java
new file mode 100644
index 0000000..1fa327e
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/SubscriptionManager.java
@@ -0,0 +1,112 @@
+/*
+ * 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;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
+import org.apache.brooklyn.api.sensor.Sensor;
+import org.apache.brooklyn.api.sensor.SensorEvent;
+import org.apache.brooklyn.api.sensor.SensorEventListener;
+
+/**
+ * The management interface for subscriptions.
+ * 
+ * Different implementations will handle entities subscribing and unsubscribing to {@link SensorEvent}s
+ * and their delivery.
+ * 
+ * @see SubscriptionContext
+ */
+public interface SubscriptionManager {
+    /**
+     * Subscribe to {@link Sensor} data changes and events on a given {@link Entity}, supplying the {@link SensorEventListener}
+     * to invoke when they occur.
+     * 
+     * The method returns an id which can be used to {@link #unsubscribe(SubscriptionHandle)} later.
+     * <p>
+     * The listener callback is in-order single-threaded and synchronized on this object. The flags
+     * parameters can include the following:
+     * <ul>
+     * <li>subscriber - object to identify the subscriber (e.g. entity, or console session uid) 
+     * <li><i>in future</i> - control parameters for the subscription (period, minimum delta for updates, etc)
+     * </ul>
+     * 
+     * @param flags optional parameters to be associated with the subscription
+     * @param producer entity to listen to, or null to listen to all entities
+     * @param sensor sensor channel of events to listen to, or null for all sensors from the given producer(s)
+     * @param listener callback to invoke when an event occurs
+     * @return an id for this subscription
+     * 
+     * @see #unsubscribe(SubscriptionHandle)
+     */
+    <T> SubscriptionHandle subscribe(Map<String, Object> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
+ 
+    /** @see #subscribe(Map, Entity, Sensor, SensorEventListener) */
+    <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
+
+    /**
+     * Subscribe to {@link Sensor} data changes and events on all children of a given {@link Entity}, supplying the
+     * {@link SensorEventListener} to invoke when they occur.
+     * 
+     * The subscriptions will be created recursively for all children, and the same listener callback will be invoked for each
+     * sensor datum. The semantics are otherwise identical to the {@link #subscribe(Map, Entity, Sensor, SensorEventListener)} method.
+     *
+     * @see #subscribe(Map, Entity, Sensor, SensorEventListener)
+     */
+    <T> SubscriptionHandle subscribeToChildren(Map<String, Object> flags, Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
+ 
+    /** @see #subscribeToChildren(Map, Entity, Sensor, SensorEventListener) */
+    <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
+
+    /**
+     * Subscribe to {@link Sensor} data changes and events on all members of a given {@link Group}, supplying the
+     * {@link SensorEventListener} to invoke when they occur.
+     * 
+     * The subscriptions will be created recursively for all children, and the same listener callback will be invoked for each
+     * sensor datum. The semantics are otherwise identical to the {@link #subscribe(Map, Entity, Sensor, SensorEventListener)} method.
+     *
+     * @see #subscribe(Map, Entity, Sensor, SensorEventListener)
+     */
+    <T> SubscriptionHandle subscribeToMembers(Map<String, Object> flags, Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
+ 
+    /** @see #subscribeToMembers(Map, Group, Sensor, SensorEventListener) */
+    <T> SubscriptionHandle subscribeToMembers(Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
+
+    /**
+     * Unsubscribe the given subscription id.
+     * 
+     * @return true if such a subscription was present (and it will now be removed)
+     * 
+     * @see #subscribe(Map, Entity, Sensor, SensorEventListener)
+     */
+    boolean unsubscribe(SubscriptionHandle subscriptionId);
+
+    /**
+     * Deliver a {@link SensorEvent} to all subscribed listeners.
+     */
+    <T> void publish(SensorEvent<T> event);
+
+    /** Return the subscriptions requested by a given subscriber */
+    Set<SubscriptionHandle> getSubscriptionsForSubscriber(Object subscriber);
+    
+    /** Return the subscriptions on a given source-sensor pair */
+    Set<SubscriptionHandle> getSubscriptionsForEntitySensor(Entity source, Sensor<?> sensor);
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/Task.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/Task.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/Task.java
new file mode 100644
index 0000000..42147c5
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/Task.java
@@ -0,0 +1,146 @@
+/*
+ * 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;
+
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.brooklyn.util.time.Duration;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Represents a unit of work for execution.
+ *
+ * When used with an {@link ExecutionManager} or {@link ExecutionContext} it will record submission time,
+ * execution start time, end time, and any result. A task can be submitted to the ExecutionManager or
+ * ExecutionContext, in which case it will be returned, or it may be created by submission
+ * of a {@link Runnable} or {@link Callable} and thereafter it can be treated just like a {@link Future}.
+ */
+public interface Task<T> extends ListenableFuture<T>, TaskAdaptable<T> {
+    
+    public String getId();
+    
+    public Set<Object> getTags();
+    /** if {@link #isSubmitted()} returns the time when the task was submitted; or -1 otherwise */
+    public long getSubmitTimeUtc();
+    /** if {@link #isBegun()} returns the time when the task was starts;
+     * guaranteed to be >= {@link #getSubmitTimeUtc()} > 0 if started, or -1 otherwise */
+    public long getStartTimeUtc();
+    /** if {@link #isDone()} (for any reason) returns the time when the task ended;
+     * guaranteed to be >= {@link #getStartTimeUtc()} > 0 if ended, or -1 otherwise */
+    public long getEndTimeUtc();
+    public String getDisplayName();
+    public String getDescription();
+    
+    /** task which submitted this task, if was submitted by a task */
+    public Task<?> getSubmittedByTask();
+
+    /** The thread where the task is running, if it is running. */
+    public Thread getThread();
+
+    /**
+     * Whether task has been submitted
+     *
+     * Submitted tasks are normally expected to start running then complete,
+     * but unsubmitted tasks are sometimes passed around for someone else to submit them.
+     */
+    public boolean isSubmitted();
+
+    /**
+     * Whether task has started running.
+     *
+     * Will remain true after normal completion or non-cancellation error.
+     * will be true on cancel iff the thread did actually start.
+     */
+    public boolean isBegun();
+
+    /**
+     * Whether the task threw an error, including cancellation (implies {@link #isDone()})
+     */
+    public boolean isError();
+
+    /**
+     * As {@link Future#isDone()}. In particular if cancelled, this will return true
+     * as soon as it is cancelled. The thread for this task may still be running,
+     * if the cancellation (often an interruption, but may be weaker) has not applied,
+     * and submitted threads may also be running depending on cancellation parameters.
+     * <p>
+     * {@link #get()} is guaranteed to return immediately, throwing in the case of cancellation
+     * prior to completion (and including the case above where a thread may still be running).
+     * <p>
+     * To check whether cancelled threads for this task have completed, 
+     * inspect {@link #getEndTimeUtc()}, which is guaranteed to be set when threads complete
+     * if the thread is started (as determinable by whether {@link #getStartTimeUtc()} is set).
+     * (The threads of submitted/child tasks will usually be independent; to determine their
+     * completion requires inspecting the {@link ExecutionManager}.)  
+     */
+    @Override
+    public boolean isDone();
+    
+    /**
+     * Causes calling thread to block until the task is started.
+     */
+    public void blockUntilStarted();
+
+    /**
+     * Causes calling thread to block until the task is ended.
+     * <p>
+     * Either normally or by cancellation or error, but without throwing error on cancellation or error.
+     * (Errors are logged at debug.)
+     */
+    public void blockUntilEnded();
+
+    /**
+     * As {@link #blockUntilEnded()}, but returning after the given timeout;
+     * true if the task has ended and false otherwise
+     */
+    public boolean blockUntilEnded(Duration timeout);
+
+    public String getStatusSummary();
+
+    /**
+     * Returns detailed status, suitable for a hover.
+     *
+     * Plain-text format, with new-lines (and sometimes extra info) if multiline enabled.
+     */
+    public String getStatusDetail(boolean multiline);
+
+    /** As {@link #get(long, java.util.concurrent.TimeUnit)} */
+    public T get(Duration duration) throws InterruptedException, ExecutionException, TimeoutException;
+    
+    /** As {@link #get()}, but propagating checked exceptions as unchecked for convenience. */
+    public T getUnchecked();
+
+    /** As {@link #get()}, but propagating checked exceptions as unchecked for convenience
+     * (including a {@link TimeoutException} if the duration expires) */
+    public T getUnchecked(Duration duration);
+
+    /** As {@link Future#cancel(boolean)}. Note that {@link #isDone()} and {@link #blockUntilEnded(Duration)} return immediately
+     * once a task is cancelled, consistent with the underlying {@link FutureTask} behaviour.  
+     * TODO Fine-grained control over underlying jobs, e.g. to ensure anything represented by this task is actually completed,
+     * is not (yet) publicly exposed. See the convenience method blockUntilInternalTasksEnded in the Tasks set of helpers
+     * for more discussion. */
+    public boolean cancel(boolean mayInterruptIfRunning);
+    
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskAdaptable.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskAdaptable.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskAdaptable.java
new file mode 100644
index 0000000..4b371be
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskAdaptable.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+/** marker interface for something which can be adapted to a task  */
+public interface TaskAdaptable<T> {
+    Task<T> asTask();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskFactory.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskFactory.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskFactory.java
new file mode 100644
index 0000000..adc4817
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskFactory.java
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+
+/** Interface for something which can generate tasks (or task wrappers) */
+public interface TaskFactory<T extends TaskAdaptable<?>> {
+    T newTask();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskQueueingContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskQueueingContext.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskQueueingContext.java
new file mode 100644
index 0000000..9794c5e
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskQueueingContext.java
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+import java.util.List;
+
+import org.apache.brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Marks a place where tasks can be added, e.g. a task which allows children to be added (including after it is activated);
+ * if the implementer of this is also a task, then it may be picked up by hierarchical methods (e.g. in DynamicTasks).
+ * 
+ * @since 0.6.0
+ */
+@Beta
+public interface TaskQueueingContext {
+
+    /** queues the task for submission as part of this queueing context
+     * <p>
+     * implementations should mark it as queued but not yet submitted.
+     * note the task may have already been submitted, and is being queued here for informational purposes,
+     * in which case the implementation should not run it. */
+    public void queue(Task<?> t);
+    
+    /** returns a list of queued tasks (immutable copy) */
+    public List<Task<?>> getQueue();
+
+    /** Drains the task queue for this context to complete, ie waits for this context to complete (or terminate early)
+     * @param optionalTimeout null to run forever
+     * @param includePrimaryThread whether the parent (this context) should also be joined on;
+     *   should only be true if invoking this from another task, as otherwise it will be waiting for itself!
+     * @param throwFirstError whether to throw the first exception encountered
+     * <p>
+     * Also note that this waits on tasks so that blocking details on the caller are meaningful.
+     */
+    public void drain(Duration optionalTimeout, boolean includePrimaryThread, boolean throwFirstError);
+
+    /** Returns the task which is this queueing context */
+    public Task<?> asTask();
+
+    /** causes subsequent children failures not to fail the parent */
+    public void swallowChildrenFailures();
+    
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskWrapper.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskWrapper.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskWrapper.java
new file mode 100644
index 0000000..a66b2e5
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/TaskWrapper.java
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+/**
+ * Interface for something which is not a task, but which is closely linked to one, ie. it has a task.
+ * 
+ * @since 0.6.0
+ */
+public interface TaskWrapper<T> extends TaskAdaptable<T> {
+    Task<T> getTask();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java
new file mode 100644
index 0000000..f95c0d8
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java
@@ -0,0 +1,50 @@
+/*
+ * 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.classloading;
+
+import java.net.URL;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.util.guava.Maybe;
+
+/** 
+ * Provides functionality for loading classes based on the current context
+ * (e.g. the bundles of a registered type from which an entity is created)
+ */
+public interface BrooklynClassLoadingContext {
+
+    public ManagementContext getManagementContext();
+    public Class<?> loadClass(String className);
+    public <T> Class<? extends T> loadClass(String className, @Nullable Class<T> supertype);
+
+    public Maybe<Class<?>> tryLoadClass(String className);
+    public <T> Maybe<Class<? extends T>> tryLoadClass(String className, @Nullable Class<T> supertype);
+
+    /** As {@link ClassLoader#getResource(String)} */
+    public URL getResource(String name);
+
+    /**
+     * As {@link ClassLoader#getResources(String)} but returning an {@link Iterable} rather than
+     * an {@link java.util.Enumeration}.
+     */
+    public Iterable<URL> getResources(String name);
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/entitlement/EntitlementClass.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/entitlement/EntitlementClass.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/entitlement/EntitlementClass.java
new file mode 100644
index 0000000..a44a621
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/entitlement/EntitlementClass.java
@@ -0,0 +1,27 @@
+/*
+ * 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.entitlement;
+
+import com.google.common.reflect.TypeToken;
+
+/** @see EntitlementManager */
+public interface EntitlementClass<T> {
+    String entitlementClassIdentifier();
+    TypeToken<T> entitlementClassArgumentType();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/entitlement/EntitlementContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/entitlement/EntitlementContext.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/entitlement/EntitlementContext.java
new file mode 100644
index 0000000..8525adc
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/entitlement/EntitlementContext.java
@@ -0,0 +1,24 @@
+/*
+ * 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.entitlement;
+
+/** @see EntitlementManager */
+public interface EntitlementContext {
+    String user();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/entitlement/EntitlementManager.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/entitlement/EntitlementManager.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/entitlement/EntitlementManager.java
new file mode 100644
index 0000000..54fcd7e
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/entitlement/EntitlementManager.java
@@ -0,0 +1,45 @@
+/*
+ * 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.entitlement;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.google.common.annotations.Beta;
+
+/** 
+ * Entitlement lookup relies on:
+ * <li>an "entitlement context", consisting of at minimum a string identifier of the user/actor for which entitlement is being requested
+ * <li>an "entitlement class", representing the category of activity for which entitlement is being requested
+ * <li>an "entitlement class argument", representing the specifics of the activity for which entitlement is being requested
+ * <p>
+ * Instances of this class typically have a 1-arg constructor taking a BrooklynProperties object
+ * (configuration injected by the Brooklyn framework)
+ * or a 0-arg constructor (if no external configuration is needed).
+ * <p>
+ * An EntitlementManagerAdapter class is available to do dispatch to common methods.
+ * <p>
+ * Instantiation is done e.g. by Entitlements.newManager.  
+ * @since 0.7.0 */
+@Beta
+public interface EntitlementManager {
+
+    public <T> boolean isEntitled(@Nullable EntitlementContext context, @Nonnull EntitlementClass<T> entitlementClass, @Nullable T entitlementClassArgument);
+    
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/HighAvailabilityManager.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/HighAvailabilityManager.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/HighAvailabilityManager.java
new file mode 100644
index 0000000..6724a03
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/HighAvailabilityManager.java
@@ -0,0 +1,129 @@
+/*
+ * 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.util.Map;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Monitors other management nodes (via the {@link ManagementPlaneSyncRecordPersister}) to detect
+ * if the current master has failed or stopped. If so, then deterministically chooses a new master.
+ * If that master is self, then promotes.
+
+ * Users are not expected to implement this class, or to call methods on it directly.
+ * 
+ * Expected lifecycle of methods calls on this is:
+ * <ol>
+ *   <li>{@link #setPersister(ManagementPlaneSyncRecordPersister)}
+ *   <li>Exactly one of {@link #disabled()} or {@link #start(HighAvailabilityMode)}
+ *   <li>{@link #stop()}
+ * </ol>
+ * 
+ * @since 0.7.0
+ */
+@Beta
+public interface HighAvailabilityManager {
+
+    ManagementNodeState getNodeState();
+    
+    /** The time in milliseconds when the state was last changed. -1 if no state transition has occurred yet.*/
+    long getLastStateChange();
+    
+    /**
+     * @param persister
+     * @return self
+     */
+    HighAvailabilityManager setPersister(ManagementPlaneSyncRecordPersister persister);
+
+    /**
+     * Indicates that HA is disabled: this node will act as the only management node in this management plane,
+     * and will not persist HA meta-information (meaning other nodes cannot join). 
+     * <p>
+     * Subsequently can expect {@link #getNodeState()} to be {@link ManagementNodeState#MASTER} 
+     * and {@link #loadManagementPlaneSyncRecord(boolean)} to show just this one node --
+     * as if it were running HA with just one node --
+     * but {@link #isRunning()} will return false.
+     * <p>
+     * Currently this method is intended to be called early in the lifecycle,
+     * instead of {@link #start(HighAvailabilityMode)}. It may be an error if
+     * this is called after this HA Manager is started.
+     */
+    @Beta
+    void disabled();
+
+    /** Whether HA mode is operational */
+    boolean isRunning();
+    
+    /**
+     * Starts the monitoring of other nodes (and thus potential promotion of this node from standby to master).
+     * <p>
+     * When this method returns, the status of this node will be set,
+     * either {@link ManagementNodeState#MASTER} if appropriate 
+     * or {@link ManagementNodeState#STANDBY} / {@link ManagementNodeState#HOT_STANDBY} / {@link ManagementNodeState#HOT_BACKUP}.
+     *
+     * @param startMode mode to start with
+     * @throws IllegalStateException if current state of the management-plane doesn't match that desired by {@code startMode} 
+     */
+    void start(HighAvailabilityMode startMode);
+
+    /**
+     * Stops this node, then publishes own status (via {@link ManagementPlaneSyncRecordPersister} of {@link ManagementNodeState#TERMINATED}.
+     */
+    void stop();
+
+    /** changes the mode that this HA server is running in
+     * <p>
+     * note it will be an error to {@link #changeMode(HighAvailabilityMode)} to {@link ManagementNodeState#MASTER} 
+     * when there is already a master; to promote a node explicitly set its priority higher than
+     * the others and invoke {@link #changeMode(HighAvailabilityMode)} to a standby mode on the existing master */
+    void changeMode(HighAvailabilityMode mode);
+
+    /** sets the priority, and publishes it synchronously so it is canonical */
+    void setPriority(long priority);
+    
+    long getPriority();
+
+    /** deletes non-master node records; active nodes (including this) will republish, 
+     * so this provides a simple way to clean out the cache of dead brooklyn nodes */
+    @Beta
+    void publishClearNonMaster();
+
+    /**
+     * Returns a snapshot of the management-plane's current / most-recently-known status,
+     * as last read from {@link #loadManagementPlaneSyncRecord(boolean)}, or null if none read.
+     */
+    ManagementPlaneSyncRecord getLastManagementPlaneSyncRecord();
+    
+    /**
+     * @param useLocalKnowledgeForThisNode - if true, the record for this mgmt node will be replaced with the
+     * actual current status known in this JVM (may be more recent than what is persisted);
+     * for most purposes there is little difference but in some cases the local node being updated
+     * may be explicitly wanted or not wanted
+     */
+    ManagementPlaneSyncRecord loadManagementPlaneSyncRecord(boolean useLocalKnowledgeForThisNode);
+    
+    @VisibleForTesting
+    ManagementPlaneSyncRecordPersister getPersister();
+
+    /** Returns a collection of metrics */
+    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/ha/HighAvailabilityMode.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/HighAvailabilityMode.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/HighAvailabilityMode.java
new file mode 100644
index 0000000..146057d
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/HighAvailabilityMode.java
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+/** Specifies the HA mode that a mgmt node should run in */
+public enum HighAvailabilityMode {
+    /** 
+     * Means HA mode should not be operational.
+     * <p>
+     * When specified for the initial HA mode, this simply turns off HA.
+     * <p>
+     * However if being used to {@link HighAvailabilityManager#changeMode(HighAvailabilityMode)},
+     * this will cause the node to transition to a {@link ManagementNodeState#FAILED} state.
+     * Switching to a "master-but-not-part-of-HA" state is not currently supported, as this would be
+     * problematic if another node (which was part of HA) then tries to become master,
+     * and the more common use of this at runtime is to disable a node from being part of the HA plane. 
+     */
+    DISABLED,
+    
+    /**
+     * Means auto-detect whether to be master or standby; if there is already a master then start as standby, 
+     * otherwise start as master.
+     */
+    AUTO,
+    
+    /**
+     * Means node must be lukewarm standby; if there is not already a master then fail fast on startup.
+     * See {@link ManagementNodeState#STANDBY}. 
+     */
+    STANDBY,
+    
+    /**
+     * Means node must be hot standby; if there is not already a master then fail fast on startup.
+     * See {@link ManagementNodeState#HOT_STANDBY}. 
+     */
+    HOT_STANDBY,
+    
+    /**
+     * Means node must be hot backup; do not attempt to become master (but it <i>can</i> start without a master).
+     * See {@link ManagementNodeState#HOT_BACKUP}. 
+     */
+    HOT_BACKUP,
+    
+    /**
+     * Means node must be master; if there is already a master then fail fast on startup.
+     * See {@link ManagementNodeState#MASTER}.
+     */
+    // TODO when multi-master supported we will of course not fail fast on startup when there is already a master;
+    // instead the responsibility for master entities will be divided among masters
+    MASTER;
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementNodeState.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementNodeState.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementNodeState.java
new file mode 100644
index 0000000..6e42796
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementNodeState.java
@@ -0,0 +1,72 @@
+/*
+ * 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 org.apache.brooklyn.util.guava.Maybe;
+
+public enum ManagementNodeState {
+    /** Node is either coming online, or is in some kind of recovery/transitioning mode */
+    INITIALIZING,
+    
+    /** Node is in "lukewarm standby" mode, where it is available to be promoted to master,
+     * but does not have entities loaded and will require some effort to be promoted */
+    STANDBY,
+    /** Node is acting as read-only proxy available to be promoted to master on existing master failure */
+    HOT_STANDBY,
+    /** Node is acting as a read-only proxy but not making itself available for promotion to master */
+    HOT_BACKUP,
+    /** Node is running as primary/master, able to manage entities and create new ones */
+    // the semantics are intended to support multi-master here; we could have multiple master nodes,
+    // but we need to look up who is master for any given entity
+    MASTER,
+
+    /** Node has failed and requires maintenance attention */
+    FAILED,
+    /** Node has gone away; maintenance not possible */
+    TERMINATED;
+
+    /** Converts a {@link HighAvailabilityMode} to a {@link ManagementNodeState}, if possible */
+    public static Maybe<ManagementNodeState> of(HighAvailabilityMode startMode) {
+        switch (startMode) {
+        case AUTO:
+        case DISABLED:
+            return Maybe.absent("Requested "+HighAvailabilityMode.class+" mode "+startMode+" cannot be converted to "+ManagementNodeState.class);
+        case HOT_BACKUP:
+            return Maybe.of(HOT_BACKUP);
+        case HOT_STANDBY:
+            return Maybe.of(HOT_STANDBY);
+        case MASTER:
+            return Maybe.of(MASTER);
+        case STANDBY:
+            return Maybe.of(STANDBY);
+        }
+        // above should be exhaustive
+        return Maybe.absent("Requested "+HighAvailabilityMode.class+" mode "+startMode+" was not expected");
+    }
+
+    /** true for hot non-master modes, where we are proxying the data from the persistent store */
+    public static boolean isHotProxy(ManagementNodeState state) {
+        return state==HOT_BACKUP || state==HOT_STANDBY;
+    }
+
+    /** true for non-master modes which can be promoted to master */
+    public static boolean isStandby(ManagementNodeState state) {
+        return state==ManagementNodeState.STANDBY || state==ManagementNodeState.HOT_STANDBY;
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementNodeSyncRecord.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementNodeSyncRecord.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementNodeSyncRecord.java
new file mode 100644
index 0000000..dccbd01
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementNodeSyncRecord.java
@@ -0,0 +1,62 @@
+/*
+ * 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.net.URI;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents the state of a management-node.
+ * 
+ * @see {@link ManagementPlaneSyncRecord#getManagementNodes()}
+ * 
+ * @since 0.7.0
+ * 
+ * @author aled
+ */
+@Beta
+public interface ManagementNodeSyncRecord {
+
+    // TODO Not setting URI currently; ManagementContext doesn't know its URI; only have one if web-console was enabled.
+    
+    // TODO Add getPlaneId(); but first need to set it in a sensible way
+    
+    String getBrooklynVersion();
+    
+    String getNodeId();
+    
+    URI getUri();
+    
+    ManagementNodeState getStatus();
+
+    Long getPriority();
+    
+    /** timestamp set by the originating management machine */
+    long getLocalTimestamp();
+
+    /** timestamp set by shared persistent store, if available
+     * <p>
+     * this will not be set on records originating at this machine, nor will it be persisted,
+     * but it will be populated for records being read */
+    Long getRemoteTimestamp();
+    
+    String toVerboseString();
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementPlaneSyncRecord.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementPlaneSyncRecord.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementPlaneSyncRecord.java
new file mode 100644
index 0000000..86bb74e
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/ha/ManagementPlaneSyncRecord.java
@@ -0,0 +1,51 @@
+/*
+ * 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.util.Map;
+
+import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMemento;
+import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoPersister;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Meta-data about the management plane - the management nodes and who is currently master.
+ * Does not contain any data about the entities under management.
+ * <p>
+ * This is very similar to how {@link BrooklynMemento} is used by {@link BrooklynMementoPersister},
+ * but it is not a memento in the sense it does not reconstitute the entire management plane
+ * (so is not called Memento although it can be used by the same memento-serializers).
+ * 
+ * @since 0.7.0
+ * 
+ * @author aled
+ */
+@Beta
+public interface ManagementPlaneSyncRecord {
+
+    // TODO Add getPlaneId(); but first need to set it sensibly on each management node
+    
+    String getMasterNodeId();
+    
+    /** returns map of {@link ManagementNodeSyncRecord} instances keyed by the nodes' IDs */
+    Map<String, ManagementNodeSyncRecord> getManagementNodes();
+
+    String toVerboseString();
+}