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:52:54 UTC

[55/71] [abbrv] brooklyn-ui git commit: javascript checks up on start, shows caution

javascript checks up on start, shows caution

popup now appears while server is starting, or if there are errors, and comes back if server changes to standby.
changed to plug in *before* the routes are evaluated, so we don't load the wrong data.

expands rest api to return several pieces of information to simplify gui checks.

simplifies code in rest filters to block requests not compatible with server state, including checking for upness there.


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

Branch: refs/heads/0.7.0-incubating
Commit: a8899307d8de566b64cbd7c10a70c14b0000f859
Parents: 6741a42
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Apr 23 16:31:30 2015 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Apr 27 08:37:04 2015 +0100

----------------------------------------------------------------------
 usage/jsgui/src/main/webapp/assets/js/config.js |  10 +-
 .../jsgui/src/main/webapp/assets/js/model/ha.js |  62 ------
 .../assets/js/model/server-extended-status.js   |  87 ++++++++
 usage/jsgui/src/main/webapp/assets/js/router.js | 205 ++++++++++---------
 .../main/webapp/assets/js/view/ha-summary.js    |  17 +-
 .../src/main/webapp/assets/js/view/home.js      |   4 +-
 .../webapp/assets/tpl/home/server-caution.html  |  94 +++++++++
 .../assets/tpl/home/server-not-ha-master.html   |  35 ----
 usage/jsgui/src/main/webapp/index.html          |   2 +-
 .../src/test/javascript/specs/model/ha-spec.js  |  41 ----
 .../src/test/javascript/specs/router-spec.js    |   3 -
 11 files changed, 303 insertions(+), 257 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/a8899307/usage/jsgui/src/main/webapp/assets/js/config.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/config.js b/usage/jsgui/src/main/webapp/assets/js/config.js
index 918a7ca..4fa477d 100644
--- a/usage/jsgui/src/main/webapp/assets/js/config.js
+++ b/usage/jsgui/src/main/webapp/assets/js/config.js
@@ -76,13 +76,9 @@ require.config({
 
 /*
  * Main application entry point.
- *
- * Inclusion of brooklyn module sets up logging.
  */
 require([
-    "backbone", "brooklyn", "router", "model/ha"
-], function (Backbone, Brooklyn, Router, ha) {
-    ha.autoUpdate();
-    var router = new Router();
-    Backbone.history.start();
+    "router"
+], function (Router) {
+    new Router().startBrooklynGui();
 });

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/a8899307/usage/jsgui/src/main/webapp/assets/js/model/ha.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/model/ha.js b/usage/jsgui/src/main/webapp/assets/js/model/ha.js
deleted file mode 100644
index 8ece989..0000000
--- a/usage/jsgui/src/main/webapp/assets/js/model/ha.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.
-*/
-define(["backbone", "brooklyn", "view/viewutils"], function (Backbone, Brooklyn, ViewUtils) {
-
-    var HAStatus = Backbone.Model.extend({
-        callbacks: [],
-        loaded: false,
-        url: "/v1/server/highAvailability",
-        isMaster: function() {
-            return this.get("masterId") == this.get("ownId");
-        },
-        getMasterUri: function() {
-            // Might be undefined if first fetch hasn't completed
-            var nodes = this.get("nodes") || {};
-            var master = nodes[this.get("masterId")];
-            // defensive, if this happens something more serious has gone wrong!
-            if (!master) {
-                return null;
-            } else {
-                return master.nodeUri;
-            }
-        },
-        onLoad: function(f) {
-            if (this.loaded) {
-                f();
-            } else {
-                this.callbacks.push(f);
-            }
-        },
-        autoUpdate: function() {
-            ViewUtils.fetchModelRepeatedlyWithDelay(this, { doitnow: true });
-        }
-    });
-
-    var haStatus = new HAStatus();
-    haStatus.once("sync", function() {
-        haStatus.loaded = true;
-        _.invoke(haStatus.callbacks, "apply");
-        haStatus.callbacks = undefined;
-    });
-
-    // Will returning the instance rather than the object be confusing?
-    // It breaks the pattern used by all the other models.
-    return haStatus;
-
-});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/a8899307/usage/jsgui/src/main/webapp/assets/js/model/server-extended-status.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/model/server-extended-status.js b/usage/jsgui/src/main/webapp/assets/js/model/server-extended-status.js
new file mode 100644
index 0000000..88e1ef2
--- /dev/null
+++ b/usage/jsgui/src/main/webapp/assets/js/model/server-extended-status.js
@@ -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.
+*/
+define(["backbone", "brooklyn", "view/viewutils"], function (Backbone, Brooklyn, ViewUtils) {
+
+    var ServerExtendedStatus = Backbone.Model.extend({
+        callbacks: [],
+        loaded: false,
+        url: "/v1/server/up/extended",
+        whenUp: function(f) {
+            var that = this;
+            if (this.isUp()) {
+                f();
+            } else {
+                this.addCallback(function() { that.whenUp(f); });
+            }
+        },
+        onLoad: function(f) {
+            if (this.loaded) {
+                f();
+            } else {
+                this.addCallback(f);
+            }
+        },
+        addCallback: function(f) {
+            this.callbacks.push(f);
+        },
+        autoUpdate: function() {
+            var that = this;
+            // to debug:
+//            serverExtendedStatus.onLoad(function() { log("loaded server status:"); log(that.attributes); })
+            ViewUtils.fetchModelRepeatedlyWithDelay(this, { doitnow: true });
+        },
+
+        isUp: function() { return this.get("up") },
+        isHealthy: function() { return this.get("healthy") },
+        isMaster: function() {
+            ha = this.get("ha") || {};
+            ownId = ha.ownId;
+            if (!ownId) return null;
+            return ha.masterId == ownId;
+        },
+        getMasterUri: function() {
+            // Might be undefined if first fetch hasn't completed
+            ha = this.get("ha") || {};
+            states = ha.states || {};
+            if (!states) return null;
+            
+            var nodes = this.get("nodes") || {};
+            var master = nodes[this.get("masterId")];
+            // defensive, if this happens something more serious has gone wrong!
+            if (!master) {
+                return null;
+            } else {
+                return master.nodeUri;
+            }
+        },
+    });
+
+    var serverExtendedStatus = new ServerExtendedStatus();
+    serverExtendedStatus.on("sync", function() {
+        serverExtendedStatus.loaded = true;
+        var currentCallbacks = serverExtendedStatus.callbacks;
+        serverExtendedStatus.callbacks = [];
+        _.invoke(currentCallbacks, "apply");
+    });
+
+    // Will returning the instance rather than the object be confusing?
+    // It breaks the pattern used by all the other models.
+    return serverExtendedStatus;
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/a8899307/usage/jsgui/src/main/webapp/assets/js/router.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/router.js b/usage/jsgui/src/main/webapp/assets/js/router.js
index 186dd72..4c7689a 100644
--- a/usage/jsgui/src/main/webapp/assets/js/router.js
+++ b/usage/jsgui/src/main/webapp/assets/js/router.js
@@ -18,46 +18,95 @@
 */
 define([
     "brooklyn", "underscore", "jquery", "backbone",
-    "model/application", "model/app-tree", "model/location", "model/ha",
+    "model/application", "model/app-tree", "model/location", 
+    "model/server-extended-status",
     "view/home", "view/application-explorer", "view/catalog", "view/apidoc", "view/script-groovy",
-    "text!tpl/help/page.html","text!tpl/labs/page.html", "text!tpl/home/server-not-ha-master.html"
+    "text!tpl/help/page.html","text!tpl/labs/page.html", "text!tpl/home/server-caution.html"
 ], function (Brooklyn, _, $, Backbone,
-        Application, AppTree, Location, ha,
-        HomeView, ExplorerView, CatalogView, ApidocView, ScriptGroovyView,
-        HelpHtml, LabsHtml, ServerNotMasterHtml) {
+        Application, AppTree, Location, 
+        serverStatus,
+        HomeView, ExplorerView, CatalogView, ApidocView, ScriptGroovyView, 
+        HelpHtml, LabsHtml, ServerCautionHtml) {
 
-    /**
-     * @returns {jquery.Deferred}
-     *      A promise that resolves when the high availability status has been
-     *      loaded. Actions to be taken on the view after it has loaded should
-     *      be registered with calls to .done()
-     */
-    // Not just defined as a function on Router because the delay if the HA status
-    // hasn't loaded requires a reference to the function, which we lose if we use
-    // 'this.showView'.
-    function showViewImpl(router, selector, view) {
-        // Don't do anything until the HA status has loaded.
-        var promise = $.Deferred()
-            .done(function () {
-                // close the previous view - does binding clean-up and avoids memory leaks
-                if (router.currentView) {
-                    router.currentView.close();
-                }
-                // render the view inside the selector element
-                $(selector).html(view.render().el);
-                router.currentView = view;
-                return view
+    var ServerCautionOverlay = Backbone.View.extend({
+        template: _.template(ServerCautionHtml),
+        scheduledRedirect: false,
+        initialize: function() {
+            var that = this;
+            this.carryOnRegardless = false;
+            _.bindAll(this);
+            serverStatus.addCallback(this.renderAndAddCallback);
+        },
+        renderAndAddCallback: function() {
+            this.renderOnUpdate();
+            serverStatus.addCallback(this.renderAndAddCallback);
+        },
+        renderOnUpdate: function() {
+            var that = this;
+            if (this.carryOnRegardless) return this.renderEmpty();
+            
+            var state = {
+                    loaded: serverStatus.loaded,
+                    up: serverStatus.isUp(),
+                    healthy: serverStatus.isHealthy(),
+                    master: serverStatus.isMaster(),
+                    masterUri: serverStatus.getMasterUri(),
+                };
+            if (state.loaded && state.up && state.healthy && state.master) return this.renderEmpty();
+            
+            this.warningActive = true;
+            this.$el.html(this.template(state));
+                
+            $("#dismiss-standby-warning", this.$el).click(function() {
+                that.carryOnRegardless = true;
+                if (that.redirectPending) {
+                    log("Cancelling redirect, using this non-master instance");
+                    clearTimeout(that.redirectPending);
+                    that.redirectPending = null;
+                }       
+                that.renderOnUpdate();
             });
-        (function isComplete() {
-            if (ha.loaded) {
-                promise.resolve();
-            } else {
-                _.defer(isComplete, 100);
+            
+            if (!state.master && state.masterUri) {
+                if (!this.scheduledRedirect && !this.redirectPending) {
+                    log("Not master; will redirect shortly to: "+state.masterUri);
+                    var destination = state.masterUri + "#" + Backbone.history.fragment;
+                    var time = 10;
+                    this.scheduledRedirect = true;
+                    log("Redirecting to " + destination + " in " + time + " seconds");
+                    this.redirectPending = setTimeout(function () {
+                        // re-check, in case the server's status changed in the wait
+                        if (!serverStatus.isMaster()) {
+                            if (that.redirectPending) {
+                                window.location.href = destination;
+                            } else {
+                                log("Cancelled redirect, using this non-master instance");
+                            }
+                        } else {
+                            log("Cancelled redirect, this instance is now master");
+                        }
+                    }, time * 1000);
+                }
             }
-        })();
-        return promise;
-    }
-
+            return this;
+        },
+        renderEmpty: function() {
+            this.warningActive = false;
+            this.$el.empty();
+            return this;
+        },
+        beforeClose: function() {
+            this.stopListening();
+        },
+        warnIfNotLoaded: function() {
+            if (!this.loaded)
+                this.renderOnUpdate();
+        }
+    });
+    // look for ha-standby-overlay for compatibility with older index.html copies
+    var serverCautionOverlay = new ServerCautionOverlay({ el: $("#server-caution-overlay").length ? $("#server-caution-overlay") : $("#ha-standby-overlay")});
+    serverCautionOverlay.render();
+    
     var Router = Backbone.Router.extend({
         routes:{
             'v1/home/*trail':'homePage',
@@ -75,7 +124,14 @@ define([
         },
 
         showView: function(selector, view) {
-            return showViewImpl(this, selector, view);
+            // close the previous view - does binding clean-up and avoids memory leaks
+            if (this.currentView) {
+                this.currentView.close();
+            }
+            // render the view inside the selector element
+            $(selector).html(view.render().el);
+            this.currentView = view;
+            return view;
         },
 
         defaultRoute: function() {
@@ -94,6 +150,7 @@ define([
                 homeView = new HomeView({
                     collection:that.applications,
                     locations:that.locations,
+                    cautionOverlay:serverCautionOverlay,
                     appRouter:that
                 });
                 veryFirstViewLoad = !that.currentView;
@@ -102,13 +159,10 @@ define([
             this.applications.fetch({success:function () {
                 render();
                 // show add application wizard if none already exist and this is the first page load
-                if ((veryFirstViewLoad && trail=='auto' && that.applications.isEmpty()) ||
-                     (trail=='add_application') ) {
-                    ha.onLoad(function() {
-                        if (ha.isMaster()) {
-                            homeView.createApplication();
-                        }
-                    });
+                if ((veryFirstViewLoad && trail=='auto' && that.applications.isEmpty()) || (trail=='add_application') ) {
+                    if (serverStatus.isMaster()) {
+                        homeView.createApplication();
+                    }
                 }
             }, error: render});
         },
@@ -156,64 +210,17 @@ define([
         labsPage:function () {
             $("#application-content").html(_.template(LabsHtml, {}))
             $(".nav1").removeClass("active")
-        }
-    })
-
-    var HaStandbyOverlay = Backbone.View.extend({
-        template: _.template(ServerNotMasterHtml),
-        scheduledRedirect: false,
-        initialize: function() {
-            this.carryOnRegardless = false;
-            this.listenTo(ha, "change", this.render);
         },
-        render: function() {
-            var that = this;
-            
-            if (!ha.isMaster() && !this.carryOnRegardless) {
-                var masterUri = ha.getMasterUri();
-                this.$el.html(this.template({"masterUri": masterUri}));
-                
-                log("render, redirect = "+this.redirectPending);
-                
-                $("#dismiss-standby-warning", this.$el).click(function() {
-                    that.carryOnRegardless = true;
-                    if (that.redirectPending) {
-                        console.log("Cancelling redirect, using this non-master instance");
-                        clearTimeout(that.redirectPending);
-                        that.redirectPending = null;
-                    }       
-                    that.render();
-                });
-                
-                if (masterUri && !this.scheduledRedirect && !this.redirectPending) {
-                    var destination = masterUri + "#" + Backbone.history.fragment;
-                    var time = 10;
-                    this.scheduledRedirect = true;
-                    console.log("Redirecting to " + destination + " in " + time + " seconds");
-                    this.redirectPending = setTimeout(function () {
-                        // re-check, in case the server's status changed in the wait
-                        if (!ha.isMaster()) {
-                            if (that.redirectPending) {
-                                window.location.href = destination;
-                            } else {
-                                console.log("Cancelled redirect, using this non-master instance");
-                            }
-                        } else {
-                            console.log("Cancelled redirect, this instance is now master");
-                        }
-                    }, time * 1000);
-                }
-            } else {
-                this.$el.empty();
-            }
-            return this;
-        },
-        beforeClose: function() {
-            this.stopListening();
+
+        /** Triggers the Backbone.Router process which drives this GUI through Backbone.history,
+         *  after starting background server health checks and waiting for confirmation of health
+         *  (or user click-through). */
+        startBrooklynGui: function() {
+            serverStatus.whenUp(function() { Backbone.history.start(); });
+            serverStatus.autoUpdate();
+            _.delay(serverCautionOverlay.warnIfNotLoaded, 2*1000)
         }
     });
-    new HaStandbyOverlay({ el: $("#ha-standby-overlay") }).render();
-
 
     $.ajax({
         type: "GET",
@@ -221,7 +228,7 @@ define([
         dataType: "text"
     }).done(function (data) {
         if (data != null) {
-            $("#user").html(data);
+            $("#user").html(_.escape(data));
         }
     });
 

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/a8899307/usage/jsgui/src/main/webapp/assets/js/view/ha-summary.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/ha-summary.js b/usage/jsgui/src/main/webapp/assets/js/view/ha-summary.js
index 62b5c3e..2032d1d 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/ha-summary.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/ha-summary.js
@@ -18,9 +18,9 @@
 */
 define([
     "jquery", "underscore", "backbone", "moment", "view/viewutils",
-    "model/ha",
+    "model/server-extended-status",
     "text!tpl/home/ha-summary.html"
-], function ($, _, Backbone, moment, ViewUtils, ha, HASummaryHtml) {
+], function ($, _, Backbone, moment, ViewUtils, serverStatus, HASummaryHtml) {
 
     var template = _.template(HASummaryHtml);
     var nodeRowTemplate = _.template(
@@ -38,26 +38,27 @@ define([
         initialize: function() {
             _.bindAll(this);
             this.updateTimestampCallback = setInterval(this.updateTimestamps, 1000);
-            this.listenTo(ha, "change", this.renderNodeStatus);
+            this.listenTo(serverStatus, "change", this.renderNodeStatus);
         },
         beforeClose: function() {
             clearInterval(this.updateTimestampCallback);
             this.stopListening();
         },
         updateNow: function() {
-            ha.fetch();
+            serverStatus.fetch();
         },
         render: function() {
             this.$el.html(template());
-            if (ha.loaded) {
+            if (serverStatus.loaded) {
                 this.renderNodeStatus();
             }
             return this;
         },
         renderNodeStatus: function() {
-            var master = ha.get("masterId"),
-                self = ha.get("ownId"),
-                nodes = ha.get("nodes"),
+            var serverHa = serverStatus.get("ha") || {};
+            var master = serverHa.masterId,
+                self = serverHa.ownId,
+                nodes = serverHa.nodes,
                 $target = this.$(".ha-summary-table-body");
             $target.empty();
             // undefined check just in case server returns something odd

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/a8899307/usage/jsgui/src/main/webapp/assets/js/view/home.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/home.js b/usage/jsgui/src/main/webapp/assets/js/view/home.js
index de9ce69..ae2ba3a 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/home.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/home.js
@@ -139,7 +139,9 @@ define([
                 this._modal.close()
             }
             var that = this;
-            if (!this.options.offline) {
+            if (this.options.offline || (this.options.cautionOverlay && this.options.cautionOverlay.warningActive)) {
+                // don't show wizard
+            } else {
                 var wizard = new AppAddWizard({appRouter:this.options.appRouter})
                 this._modal = wizard
                 this.$(".add-app #modal-container").html(wizard.render().el)

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/a8899307/usage/jsgui/src/main/webapp/assets/tpl/home/server-caution.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/home/server-caution.html b/usage/jsgui/src/main/webapp/assets/tpl/home/server-caution.html
new file mode 100644
index 0000000..0f767c0
--- /dev/null
+++ b/usage/jsgui/src/main/webapp/assets/tpl/home/server-caution.html
@@ -0,0 +1,94 @@
+
+<!--
+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.
+-->
+
+<div class="server-caution-overlay overlay-with-opacity"></div>
+<div class="server-caution-overlay">
+    <div class="overlay-content">
+        <h1 class="lead">Warning!</h1>
+
+<% if (!loaded) { %>
+        <p><strong>
+            Connecting to server...</strong></p>
+
+            <center><img src="/assets/images/throbber.gif"/></center>        
+        <p>
+            No response from server (yet). 
+            Please check your network connection, or if you are on a slow connection simply be patient!
+            This dialog will disappear if and when the server responds.</p>
+        
+        <p><i>
+            If you understand the risks, that information may be unavailable and operations may fail, 
+            and wish to proceed regardless, click <a id="dismiss-standby-warning">here</a>.</i></p>
+
+<% } else if (!up) { %>
+            <div style="float: right; position: relative; top: -45px; height: 0; overflow: visible;">
+                <img src="/assets/img/icon-status-starting.gif" width="60"/></div>
+            
+        <p><strong>
+            Starting up...</strong></p>
+                    
+        <p>
+            The Brooklyn server is starting.
+            It is recommended to wait before proceeding.
+            This dialog will disappear when the server is ready.</p>
+        
+        <p><i>
+            If you understand the risks, that information may be unavailable and operations may fail, 
+            and wish to proceed regardless, click <a id="dismiss-standby-warning">here</a>.</i></p>
+
+<% } else if (healthy && !master) { %>
+        <p><strong>
+            This Brooklyn server is not the high availability master.</strong></p>
+        
+        <p>
+            It is recommended not to use this server directly.</p>
+            
+    <% if (masterUri) { %>
+        <p>Redirecting to the master server at <a href="<%= masterUri %>"><%= masterUri %></a> shortly.</p>
+    <% } else { %>
+        <p>The address of the master Brooklyn server is not currently known.</p>
+    <% } %>
+
+        <p><i>
+            If you understand the risks, that write operations will likely fail, 
+            and wish to proceed regardless, click <a id="dismiss-standby-warning">here</a>.</i></p>
+          
+<% } else { %>
+        <p><strong>
+            This Brooklyn server has errors.</strong></p>
+        
+        <p>
+            Please check with your system administrator.</p>
+
+    <% if (healthy) { /* this page should not be displayed in this case */ %>
+        <p>
+            The misconfiguration may be in Javascript as the server is reporting it is healthy.</p><% } %>
+        
+        <p><i>
+          If you would like to debug the server, click <a id="dismiss-standby-warning">here</a>
+          to dismiss this warning until you reload this page. 
+          (You should reload the page once you believe the errors are fixed
+          to confirm that this dialog does not return.)
+          </i></p>
+
+<% } %>
+
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/a8899307/usage/jsgui/src/main/webapp/assets/tpl/home/server-not-ha-master.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/home/server-not-ha-master.html b/usage/jsgui/src/main/webapp/assets/tpl/home/server-not-ha-master.html
deleted file mode 100644
index b9b8b73..0000000
--- a/usage/jsgui/src/main/webapp/assets/tpl/home/server-not-ha-master.html
+++ /dev/null
@@ -1,35 +0,0 @@
-
-<!--
-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.
--->
-
-<div class="ha-standby-overlay overlay-with-opacity"></div>
-<div class="ha-standby-overlay">
-    <div class="overlay-content">
-        <h1 class="lead">Warning!</h1>
-        <p><strong>This Brooklyn server is not the high availability master.</strong></p>
-        <p>It is recommended not to use this server directly.</p>
-    <% if (masterUri) { %>
-        <p>Redirecting to the master server at <a href="<%= masterUri %>"><%= masterUri %></a> shortly.</p>
-    <% } else { %>
-        <p>The address of the master Brooklyn server is not currently known.</p>
-    <% } %>
-        <p><i>If you understand the risks, that write operations will likely fail, 
-          and wish to proceed regardless, click <a id="dismiss-standby-warning">here</a>.</i>
-    </div>
-</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/a8899307/usage/jsgui/src/main/webapp/index.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/index.html b/usage/jsgui/src/main/webapp/index.html
index 856830e..fda3514 100644
--- a/usage/jsgui/src/main/webapp/index.html
+++ b/usage/jsgui/src/main/webapp/index.html
@@ -67,7 +67,7 @@ under the License.
 
 <div id="main-content">
     <div id="application-content"></div>
-    <div id="ha-standby-overlay"></div>
+    <div id="server-caution-overlay"></div>
 </div>
 
 <!-- load our code with require.js. data-main is replaced with optimised file at build -->

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/a8899307/usage/jsgui/src/test/javascript/specs/model/ha-spec.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/test/javascript/specs/model/ha-spec.js b/usage/jsgui/src/test/javascript/specs/model/ha-spec.js
deleted file mode 100644
index 0e51ef0..0000000
--- a/usage/jsgui/src/test/javascript/specs/model/ha-spec.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
-*/
-define([
-    "model/ha"
-], function (ha) {
-
-    describe("model/ha", function() {
-
-        beforeEach(function () {
-            ha.url = "fixtures/ha-summary.json";
-            ha.fetch();
-        });
-
-        it("should determine the master's URI", function() {
-            expect(ha.getMasterUri()).toBe("http://10.30.40.50:8081/");
-        });
-
-        it("should determine isMaster", function() {
-            expect(ha.isMaster()).toBe(true);
-            ha.set("masterId", "something else");
-            expect(ha.isMaster()).toBe(false);
-        });
-
-    });
-});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/a8899307/usage/jsgui/src/test/javascript/specs/router-spec.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/test/javascript/specs/router-spec.js b/usage/jsgui/src/test/javascript/specs/router-spec.js
index bd30eca..0041373 100644
--- a/usage/jsgui/src/test/javascript/specs/router-spec.js
+++ b/usage/jsgui/src/test/javascript/specs/router-spec.js
@@ -20,9 +20,6 @@ define([
     "brooklyn", "router", "model/ha"
 ], function (Brooklyn, Router, ha) {
 
-    ha.url = "fixtures/ha-summary.json";
-    ha.loaded = true;
-
     var View = Backbone.View.extend({
         render:function () {
             this.$el.html("<p>fake view</p>")