add support for clearing out stale/non-master management node records

included in GUI, which allows if you start to get a long list of old dead 
servers it is easy to clear them


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

Branch: refs/heads/master
Commit: dfd8d575645e299dc0ed4db140487e362445eace
Parents: 304e708
Author: Alex Heneveld <[email protected]>
Authored: Fri Jan 23 11:16:42 2015 +0000
Committer: Alex Heneveld <[email protected]>
Committed: Fri Jan 23 11:44:37 2015 +0000

----------------------------------------------------------------------
 .../management/ha/HighAvailabilityManager.java  |  7 +++-
 .../ha/HighAvailabilityManagerImpl.java         | 15 ++++++++
 .../NonDeploymentManagementContext.java         |  4 +++
 usage/jsgui/src/main/webapp/assets/css/base.css |  3 +-
 .../main/webapp/assets/js/view/ha-summary.js    |  7 ++--
 .../src/main/webapp/assets/js/view/home.js      | 36 +++++++++++++++-----
 .../webapp/assets/tpl/home/applications.html    | 15 ++++++--
 .../main/java/brooklyn/rest/api/ServerApi.java  |  5 +++
 .../brooklyn/rest/resources/ServerResource.java |  6 ++++
 9 files changed, 84 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dfd8d575/api/src/main/java/brooklyn/management/ha/HighAvailabilityManager.java
----------------------------------------------------------------------
diff --git 
a/api/src/main/java/brooklyn/management/ha/HighAvailabilityManager.java 
b/api/src/main/java/brooklyn/management/ha/HighAvailabilityManager.java
index 597e407..04079bb 100644
--- a/api/src/main/java/brooklyn/management/ha/HighAvailabilityManager.java
+++ b/api/src/main/java/brooklyn/management/ha/HighAvailabilityManager.java
@@ -97,7 +97,12 @@ public interface HighAvailabilityManager {
     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.

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dfd8d575/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java 
b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
index 5511c29..dda9e19 100644
--- a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
+++ b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
@@ -595,6 +595,21 @@ public class HighAvailabilityManagerImpl implements 
HighAvailabilityManager {
         }
     }
     
+    public void publishClearNonMaster() {
+        ManagementPlaneSyncRecord plane = getLastManagementPlaneSyncRecord();
+        if (plane==null || persister==null) {
+            LOG.warn("Cannot clear HA node records; HA not active (or not yet 
loaded)");
+            return;
+        }
+        brooklyn.management.ha.ManagementPlaneSyncRecordDeltaImpl.Builder db = 
ManagementPlaneSyncRecordDeltaImpl.builder();
+        for (Map.Entry<String,ManagementNodeSyncRecord> node: 
plane.getManagementNodes().entrySet())
+            if 
(!ManagementNodeState.MASTER.equals(node.getValue().getStatus()))
+                db.removedNodeId(node.getKey());
+        persister.delta(db.build());
+        // then get, so model is updated
+        loadManagementPlaneSyncRecord(true);
+    }
+    
     protected synchronized void publishDemotion(boolean demotingFromMaster) {
         checkState(getNodeState() != ManagementNodeState.MASTER, "node status 
must not be master when demoting", getNodeState());
         

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dfd8d575/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 3066720..ea4ec2b 100644
--- 
a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
+++ 
b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
@@ -599,5 +599,9 @@ public class NonDeploymentManagementContext implements 
ManagementContextInternal
         public Map<String, Object> getMetrics() {
             throw new IllegalStateException("Non-deployment context 
"+NonDeploymentManagementContext.this+" is not valid for this operation.");
         }
+        @Override
+        public void publishClearNonMaster() {
+            throw new IllegalStateException("Non-deployment context 
"+NonDeploymentManagementContext.this+" is not valid for this operation.");
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dfd8d575/usage/jsgui/src/main/webapp/assets/css/base.css
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/css/base.css 
b/usage/jsgui/src/main/webapp/assets/css/base.css
index 4d8b763..756f999 100644
--- a/usage/jsgui/src/main/webapp/assets/css/base.css
+++ b/usage/jsgui/src/main/webapp/assets/css/base.css
@@ -454,7 +454,8 @@ input[type="color"]:focus,.uneditable-input:focus {
 #reload-brooklyn-properties-resource {
        text-align: right;
 }
-#reload-brooklyn-properties-indicator {
+
+#clear-ha-node-records-resource {
     text-align: right;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dfd8d575/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 fb96ea1..62b5c3e 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
@@ -17,10 +17,10 @@
  * under the License.
 */
 define([
-    "jquery", "underscore", "backbone", "moment",
+    "jquery", "underscore", "backbone", "moment", "view/viewutils",
     "model/ha",
     "text!tpl/home/ha-summary.html"
-], function ($, _, Backbone, moment, ha, HASummaryHtml) {
+], function ($, _, Backbone, moment, ViewUtils, ha, HASummaryHtml) {
 
     var template = _.template(HASummaryHtml);
     var nodeRowTemplate = _.template(
@@ -44,6 +44,9 @@ define([
             clearInterval(this.updateTimestampCallback);
             this.stopListening();
         },
+        updateNow: function() {
+            ha.fetch();
+        },
         render: function() {
             this.$el.html(template());
             if (ha.loaded) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dfd8d575/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 3552d73..de9ce69 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/home.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/home.js
@@ -39,6 +39,7 @@ define([
         events:{
             'click #add-new-application':'createApplication',
             'click #reload-brooklyn-properties': 'reloadBrooklynProperties',
+            'click #clear-ha-node-records': 'clearHaNodeRecords',
             'click .addApplication':'createApplication'
         },
         
@@ -159,7 +160,7 @@ define([
                 url: "/v1/server/properties/reload",
                 contentType: "application/json",
                 success: function() {
-                    console.log("Reloaded brooklyn properties");
+                    console.log("reloaded brooklyn properties");
                     self.options.locations.fetch();
                     // clear submitted indicator
                     setTimeout(function() { 
self.$('#reload-brooklyn-properties-indicator').hide(); }, 250);
@@ -173,16 +174,38 @@ define([
                     console.debug(data);
                 }
             });
+        },
+        
+        clearHaNodeRecords: function() {
+            var self = this;
+            // indicate submitted
+            self.$('#clear-ha-node-records-indicator').show();
+            $.ajax({
+                type: "POST",
+                url: "/v1/server/ha/states/clear",
+                contentType: "application/json",
+                success: function() {
+                    console.log("cleared HA node records");
+                    self.haSummaryView.updateNow();
+                    // clear submitted indicator
+                    setTimeout(function() { 
self.$('#clear-ha-node-records-indicator').hide(); }, 250);
+                },
+                error: function(data) {
+                    // TODO render the error better than poor-man's flashing
+                    // (would just be connection error -- with timeout=0 we 
get a task even for invalid input)
+                    
self.$el.fadeTo(100,1).delay(200).fadeTo(200,0.2).delay(200).fadeTo(200,1);
+                    self.$('#clear-ha-node-records-indicator').hide();
+                    console.error("ERROR clearing HA nodes");
+                    console.debug(data);
+                }
+            });
         }
     })
 
     HomeView.HomeSummariesView = Backbone.View.extend({
         tagName:'div',
         template:_.template(HomeSummariesHtml),
-
-        initialize:function () {
-//            this.apps.on('change', this.render, this)
-        },
+        // no listening needed here; it's done by outer class
         render:function () {
             this.$el.html(this.template({
                 apps:this.options.applications,
@@ -190,9 +213,6 @@ define([
             }))
             return this
         },
-        beforeClose:function () {
-//            this.off("change", this.render)
-        }
     })
     
     HomeView.AppEntryView = Backbone.View.extend({

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dfd8d575/usage/jsgui/src/main/webapp/assets/tpl/home/applications.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/home/applications.html 
b/usage/jsgui/src/main/webapp/assets/tpl/home/applications.html
index 00f4ebc..3c38989 100644
--- a/usage/jsgui/src/main/webapp/assets/tpl/home/applications.html
+++ b/usage/jsgui/src/main/webapp/assets/tpl/home/applications.html
@@ -55,14 +55,25 @@ under the License.
         <button id="add-new-application" type="button" class="btn btn-info">
             Add Application</button>
     </div>
+    
     <dl class="dl-horizontal"></dl>
     <div id="reload-brooklyn-properties-resource">
         <button id="reload-brooklyn-properties" type="button" class="btn 
btn-info">
-            Reload properties</button>
+            Reload Properties</button>
     </div>
-    <div id="reload-brooklyn-properties-indicator" class="throbber hide">
+    <div id="reload-brooklyn-properties-indicator" class="throbber hide" 
style="float: right;">
         <img src="/assets/images/throbber.gif"/>
     </div>
+    
+    <dl class="dl-horizontal"></dl>
+    <div id="clear-ha-node-records-resource">
+        <button id="clear-ha-node-records" type="button" class="btn btn-info">
+            Clear HA Node Records</button>
+    </div>
+    <div id="clear-ha-node-records-indicator" class="throbber hide" 
style="float: right;">
+        <img src="/assets/images/throbber.gif"/>
+    </div>
+    
   </div>
   
     </div>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dfd8d575/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 add51c4..6621ce1 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
@@ -117,6 +117,11 @@ public interface ServerApi {
             responseClass = "brooklyn.rest.domain.HighAvailabilitySummary")
     public HighAvailabilitySummary getHighAvailabilityPlaneStates();
 
+    @POST
+    @Path("/ha/states/clear")
+    @ApiOperation(value = "Clears HA node information for non-master nodes; 
active nodes will repopulate and other records will be erased")
+    public Response clearHighAvailabilityPlaneStates();
+    
     @GET
     @Path("/ha/priority")
     @ApiOperation(value = "Returns the HA node priority for MASTER failover")

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dfd8d575/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 04424d4..eeed1b8 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
@@ -287,6 +287,12 @@ public class ServerResource extends 
AbstractBrooklynRestResource implements Serv
     }
 
     @Override
+    public Response clearHighAvailabilityPlaneStates() {
+        mgmt().getHighAvailabilityManager().publishClearNonMaster();
+        return Response.ok().build();
+    }
+
+    @Override
     public String getUser() {
         EntitlementContext entitlementContext = 
Entitlements.getEntitlementContext();
         if (entitlementContext!=null && entitlementContext.user()!=null){

Reply via email to