brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From henev...@apache.org
Subject [1/7] incubator-brooklyn git commit: adjust cli start sequence so web/rest is avail always, with isUp check on rest api
Date Thu, 07 May 2015 10:57:16 GMT
Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master d0cbcf36c -> d64808206


adjust cli start sequence so web/rest is avail always, with isUp check on rest api

first step towards being able to interactively track the startup sequence and notify on errors


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

Branch: refs/heads/master
Commit: 20810ac9e275eadbf5c00c8b2ba07534841e56f5
Parents: 7b97cee
Author: Alex Heneveld <alex.heneveld@cloudsoftcorp.com>
Authored: Thu Apr 23 07:46:32 2015 +0100
Committer: Alex Heneveld <alex.heneveld@cloudsoftcorp.com>
Committed: Mon Apr 27 08:34:36 2015 +0100

----------------------------------------------------------------------
 .../brooklyn/management/ManagementContext.java  | 17 ++++++++-
 .../internal/AbstractManagementContext.java     |  6 +++
 .../internal/LocalManagementContext.java        |  4 ++
 .../NonDeploymentManagementContext.java         |  8 ++++
 usage/cli/src/main/java/brooklyn/cli/Main.java  | 19 +++++-----
 .../brooklyn/launcher/BrooklynLauncher.java     | 39 ++++++++++++++------
 .../main/java/brooklyn/rest/api/ServerApi.java  | 10 +++++
 .../resources/AbstractBrooklynRestResource.java | 13 +++++--
 .../brooklyn/rest/resources/ServerResource.java | 31 +++++++++++++++-
 .../testing/mocks/ManagementContextMock.java    |  5 +++
 10 files changed, 125 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/20810ac9/api/src/main/java/brooklyn/management/ManagementContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/management/ManagementContext.java b/api/src/main/java/brooklyn/management/ManagementContext.java
index b45ecef..12ead70 100644
--- a/api/src/main/java/brooklyn/management/ManagementContext.java
+++ b/api/src/main/java/brooklyn/management/ManagementContext.java
@@ -172,9 +172,24 @@ public interface ManagementContext {
     StringConfigMap getConfig();
     
     /**
-     * Whether this management context is still running, or has been terminated.
+     * 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();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/20810ac9/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
index 14fe100..501f4e4 100644
--- a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
@@ -163,6 +163,7 @@ public abstract class AbstractManagementContext implements ManagementContextInte
     private final BrooklynStorage storage;
 
     private volatile boolean running = true;
+    protected boolean startupComplete = false;
 
     protected Maybe<URI> uri = Maybe.absent();
 
@@ -201,6 +202,11 @@ public abstract class AbstractManagementContext implements ManagementContextInte
     public boolean isRunning() {
         return running;
     }
+    
+    @Override
+    public boolean isStartupComplete() {
+        return startupComplete;
+    }
 
     @Override
     public BrooklynStorage getStorage() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/20810ac9/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java b/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
index 202e4a6..39e4dc5 100644
--- a/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
@@ -412,4 +412,8 @@ public class LocalManagementContext extends AbstractManagementContext
{
     public void removePropertiesReloadListener(PropertiesReloadListener listener) {
         reloadListeners.remove(listener);
     }
+
+    public void noteStartupComplete() {
+        startupComplete = true;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/20810ac9/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
index 0972871..72d83bd 100644
--- a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
@@ -164,6 +164,14 @@ public class NonDeploymentManagementContext implements ManagementContextInternal
         // Assume that the real management context has not been terminated, so always true
         return true;
     }
+    
+    @Override
+    public boolean isStartupComplete() {
+        // This mgmt context is only used by items who are not yet fully started.
+        // It's slightly misleading as this does not refer to the main mgmt context.
+        // OTOH it probably won't be used.  TBC.  -Alex, Apr 2015
+        return false;
+    }
 
     @Override
     public InternalEntityFactory getEntityFactory() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/20810ac9/usage/cli/src/main/java/brooklyn/cli/Main.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/brooklyn/cli/Main.java b/usage/cli/src/main/java/brooklyn/cli/Main.java
index e674c1d..b66a6eb 100644
--- a/usage/cli/src/main/java/brooklyn/cli/Main.java
+++ b/usage/cli/src/main/java/brooklyn/cli/Main.java
@@ -82,6 +82,7 @@ import brooklyn.util.text.Strings;
 
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
 import com.google.common.base.Objects.ToStringHelper;
 import com.google.common.collect.ImmutableList;
 
@@ -377,7 +378,15 @@ public class Main extends AbstractMain {
                 }
     
                 launcher = createLauncher();
-    
+
+                launcher.customizeInitialCatalog(new Function<BrooklynLauncher,Void>()
{
+                    @Override
+                    public Void apply(BrooklynLauncher launcher) {
+                        populateCatalog(launcher.getServerDetails().getManagementContext().getCatalog());
+                        return null;
+                    }
+                });
+                
                 launcher.persistMode(persistMode);
                 launcher.persistenceDir(persistenceDir);
                 launcher.persistenceLocation(persistenceLocation);
@@ -418,14 +427,6 @@ public class Main extends AbstractMain {
             BrooklynServerDetails server = launcher.getServerDetails();
             ManagementContext ctx = server.getManagementContext();
             
-            try {
-                populateCatalog(launcher.getServerDetails().getManagementContext().getCatalog());
-            } catch (Exception e) {
-                Exceptions.propagateIfFatal(e);
-                // don't fail to start just because catalog is not available
-                log.error("Error populating catalog: "+e, e);
-            }
-
             if (verbose) {
                 Entities.dumpInfo(launcher.getApplications());
             }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/20810ac9/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
index 9cc8ea2..10c9afb 100644
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
+++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
@@ -158,6 +158,7 @@ public class BrooklynLauncher {
     private StopWhichAppsOnShutdown stopWhichAppsOnShutdown = StopWhichAppsOnShutdown.THESE_IF_NOT_PERSISTED;
     
     private Function<ManagementContext,Void> customizeManagement = null;
+    private Function<BrooklynLauncher,Void> customizeInitialCatalog = null;
     
     private PersistMode persistMode = PersistMode.DISABLED;
     private HighAvailabilityMode highAvailabilityMode = HighAvailabilityMode.DISABLED;
@@ -420,6 +421,11 @@ public class BrooklynLauncher {
         return this;
     }
 
+    public BrooklynLauncher customizeInitialCatalog(Function<BrooklynLauncher, Void>
customizeInitialCatalog) {
+        this.customizeInitialCatalog = customizeInitialCatalog;
+        return this;
+    }
+
     public BrooklynLauncher shutdownOnExit(boolean val) {
         LOG.warn("Call to deprecated `shutdownOnExit`", new Throwable("source of deprecated
call"));
         stopWhichAppsOnShutdown = StopWhichAppsOnShutdown.THESE_IF_NOT_PERSISTED;
@@ -555,13 +561,22 @@ public class BrooklynLauncher {
         // Create the management context
         initManagementContext();
 
+        // Start webapps as soon as mgmt context available -- can use them to detect progress
of other processes
+        if (startWebApps) {
+            try {
+                startWebApps();
+            } catch (Exception e) {
+                handleSubsystemStartupError(ignoreWebErrors, "core web apps", e);
+            }
+        }
+        
         // Add a CAMP platform
         campPlatform = new BrooklynCampPlatformLauncherNoServer()
                 .useManagementContext(managementContext)
                 .launch()
                 .getCampPlatform();
         // TODO start CAMP rest _server_ in the below (at /camp) ?
-        
+
         try {
             initPersistence();
             startPersistence();
@@ -569,34 +584,34 @@ public class BrooklynLauncher {
             handleSubsystemStartupError(ignorePersistenceErrors, "persistence", e);
         }
 
+        try {
+            if (customizeInitialCatalog!=null)
+                customizeInitialCatalog.apply(this);
+        } catch (Exception e) {
+            handleSubsystemStartupError(true, "initial catalog", e);
+        }
+
         // Create the locations. Must happen after persistence is started in case the
         // management context's catalog is loaded from persisted state. (Location
         // resolution uses the catalog's classpath to scan for resolvers.)
         locations.addAll(managementContext.getLocationRegistry().resolve(locationSpecs));
 
-        // Start the web-console
-        if (startWebApps) {
-            try {
-                startWebApps();
-            } catch (Exception e) {
-                handleSubsystemStartupError(ignoreWebErrors, "web apps", e);
-            }
-        }
-
         try {
             createApps();
             startApps();
         } catch (Exception e) {
-            handleSubsystemStartupError(ignoreAppErrors, "managed apps", e);
+            handleSubsystemStartupError(ignoreAppErrors, "brooklyn autostart apps", e);
         }
 
         if (startBrooklynNode) {
             try {
                 startBrooklynNode();
             } catch (Exception e) {
-                handleSubsystemStartupError(ignoreWebErrors, "web apps", e);
+                handleSubsystemStartupError(true, "brooklyn node / self entity", e);
             }
         }
+        
+        ((LocalManagementContext)managementContext).noteStartupComplete();
 
         return this;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/20810ac9/usage/rest-api/src/main/java/brooklyn/rest/api/ServerApi.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/api/ServerApi.java b/usage/rest-api/src/main/java/brooklyn/rest/api/ServerApi.java
index 624c9db..7ee371f 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/api/ServerApi.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/api/ServerApi.java
@@ -82,6 +82,16 @@ public interface ServerApi {
     @ApiOperation(value = "Return version identifier information for this Brooklyn instance",
responseClass = "String", multiValueResponse = false)
     public VersionSummary getVersion();
 
+    @GET
+    @Path("/up")
+    @ApiOperation(value = "Returns whether this server is up - fully started, and not stopping,
though it may have errors")
+    public boolean isUp();
+    
+    @GET
+    @Path("/healthy")
+    @ApiOperation(value = "Returns whether this node is healthy - fully started, not stopping,
and no errors")
+    public boolean isHealthy();
+    
     @Deprecated /** @deprecated since 0.7.0 use /ha/node (which returns correct JSON) */
     @GET
     @Path("/status")

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/20810ac9/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
b/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
index 553e31c..0f49caf 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/AbstractBrooklynRestResource.java
@@ -32,6 +32,7 @@ import brooklyn.management.ManagementContextInjectable;
 import brooklyn.rest.util.BrooklynRestResourceUtils;
 import brooklyn.rest.util.WebResourceUtils;
 import brooklyn.rest.util.json.BrooklynJacksonJsonProvider;
+import brooklyn.util.guava.Maybe;
 import brooklyn.util.task.Tasks;
 import brooklyn.util.time.Duration;
 
@@ -52,12 +53,16 @@ public abstract class AbstractBrooklynRestResource implements ManagementContextI
     private BrooklynRestResourceUtils brooklynRestResourceUtils;
     private ObjectMapper mapper;
 
-    public synchronized ManagementContext mgmt() {
-        if (managementContext!=null) return managementContext;
+    public ManagementContext mgmt() {
+        return mgmtMaybe().get();
+    }
+    
+    protected synchronized Maybe<ManagementContext> mgmtMaybe() {
+        if (managementContext!=null) return Maybe.of(managementContext);
         managementContext = (ManagementContext) servletContext.getAttribute(BrooklynServiceAttributes.BROOKLYN_MANAGEMENT_CONTEXT);
-        if (managementContext!=null) return managementContext;
+        if (managementContext!=null) return Maybe.of(managementContext);
         
-        throw new IllegalStateException("ManagementContext not supplied for Brooklyn Jersey
Resource "+this);
+        return Maybe.absent("ManagementContext not available for Brooklyn Jersey Resource
"+this);
     }
     
     public void injectManagementContext(ManagementContext managementContext) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/20810ac9/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
index e44437f..422e06d 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java
@@ -35,6 +35,7 @@ import javax.ws.rs.core.Response;
 
 import brooklyn.config.ConfigKey;
 import brooklyn.entity.basic.ConfigKeys;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,6 +47,7 @@ import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils;
 import brooklyn.entity.rebind.persister.FileBasedObjectStore;
 import brooklyn.entity.rebind.persister.PersistenceObjectStore;
+import brooklyn.management.ManagementContext;
 import brooklyn.management.Task;
 import brooklyn.management.entitlement.EntitlementContext;
 import brooklyn.management.entitlement.Entitlements;
@@ -64,6 +66,7 @@ import brooklyn.util.ResourceUtils;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.file.ArchiveBuilder;
 import brooklyn.util.flags.TypeCoercions;
+import brooklyn.util.guava.Maybe;
 import brooklyn.util.os.Os;
 import brooklyn.util.text.Identifiers;
 import brooklyn.util.text.Strings;
@@ -229,6 +232,9 @@ public class ServerResource extends AbstractBrooklynRestResource implements
Serv
 
     @Override
     public VersionSummary getVersion() {
+        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SERVER_STATUS,
null))
+            throw WebResourceUtils.unauthorized("User '%s' is not authorized for this operation",
Entitlements.getEntitlementContext().user());
+        
         // TODO reconcile this with BrooklynVersion reading from the OSGi manifest
         // @ahgittin / @sjcorbett to decide, is there need for this in addition to the OSGi
manifest?
         // TODO as part of this call should we have a strategy for reporting downstream builds
in this call?
@@ -257,6 +263,26 @@ public class ServerResource extends AbstractBrooklynRestResource implements
Serv
         return new VersionSummary(BrooklynVersion.get(), gitSha1, gitBranch);
     }
 
+    @Override
+    public boolean isUp() {
+        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SERVER_STATUS,
null))
+            throw WebResourceUtils.unauthorized("User '%s' is not authorized for this operation",
Entitlements.getEntitlementContext().user());
+
+        Maybe<ManagementContext> mm = mgmtMaybe();
+        if (mm.isAbsent()) return false;
+        ManagementContext m = mm.get();
+        if (!m.isStartupComplete()) return false;
+        if (!m.isRunning()) return false;
+        return true;
+    }
+    
+    @Override
+    public boolean isHealthy() {
+        if (!isUp()) return false;
+        // TODO errors
+        return true;
+    }
+    
     @Deprecated
     @Override
     public String getStatus() {
@@ -282,7 +308,10 @@ public class ServerResource extends AbstractBrooklynRestResource implements
Serv
     public ManagementNodeState getHighAvailabilityNodeState() {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SERVER_STATUS,
null))
             throw WebResourceUtils.unauthorized("User '%s' is not authorized for this operation",
Entitlements.getEntitlementContext().user());
-        return mgmt().getHighAvailabilityManager().getNodeState();
+        
+        Maybe<ManagementContext> mm = mgmtMaybe();
+        if (mm.isAbsent()) return ManagementNodeState.INITIALIZING;
+        return mm.get().getHighAvailabilityManager().getNodeState();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/20810ac9/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/ManagementContextMock.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/ManagementContextMock.java
b/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/ManagementContextMock.java
index 90edf1e..d7c461e 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/ManagementContextMock.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/ManagementContextMock.java
@@ -135,6 +135,11 @@ public class ManagementContextMock implements ManagementContext {
     }
 
     @Override
+    public boolean isStartupComplete() {
+        throw fail();
+    }
+    
+    @Override
     public LocationRegistry getLocationRegistry() {
         throw fail();
     }


Mime
View raw message