You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ak...@apache.org on 2014/01/23 14:25:21 UTC

git commit: AMBARI-4392. Storm: Add widget for Supervisor's live/dead nodes count. (Denys Buzhor via akovalenko)

Updated Branches:
  refs/heads/trunk 2e34a088b -> 386330fde


AMBARI-4392. Storm: Add widget for Supervisor's live/dead nodes count. (Denys Buzhor via akovalenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/386330fd
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/386330fd
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/386330fd

Branch: refs/heads/trunk
Commit: 386330fde96666c33efa7028dee6182538d40a3d
Parents: 2e34a08
Author: Aleksandr Kovalenko <ak...@hortonworks.com>
Authored: Thu Jan 23 15:22:43 2014 +0200
Committer: Aleksandr Kovalenko <ak...@hortonworks.com>
Committed: Thu Jan 23 15:24:51 2014 +0200

----------------------------------------------------------------------
 ambari-web/app/messages.js                      |   1 +
 ambari-web/app/views.js                         |   1 +
 ambari-web/app/views/main/dashboard.js          |  35 +++-
 ambari-web/app/views/main/dashboard/widget.js   |  21 ++-
 .../main/dashboard/widgets/supervisor_live.js   | 177 +++++++++++++++++++
 5 files changed, 220 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/386330fd/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 2f2ea10..e41b8df 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1514,6 +1514,7 @@ Em.I18n.translations = {
   'dashboard.widgets.JobTrackerCapacity': 'JobTracker Capacity',
   'dashboard.widgets.DataNodeUp': 'DataNodes Live',
   'dashboard.widgets.TaskTrackerUp': 'TaskTrackers Live',
+  'dashboard.widgets.SuperVisorUp': 'Supervisors Live',
   'dashboard.widgets.NameNodeRpc': 'NameNode RPC',
   'dashboard.widgets.JobTrackerRpc': 'JobTracker RPC',
   'dashboard.widgets.MapReduceSlots': 'MapReduce Slots',

http://git-wip-us.apache.org/repos/asf/ambari/blob/386330fd/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index 6c1be82..b02c3f8 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -145,6 +145,7 @@ require('views/main/dashboard/widgets/resource_manager_heap');
 require('views/main/dashboard/widgets/resource_manager_uptime');
 require('views/main/dashboard/widgets/node_managers_live');
 require('views/main/dashboard/widgets/yarn_memory');
+require('views/main/dashboard/widgets/supervisor_live');
 
 
 require('views/main/service');

http://git-wip-us.apache.org/repos/asf/ambari/blob/386330fd/ambari-web/app/views/main/dashboard.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard.js b/ambari-web/app/views/main/dashboard.js
index 61853cb..c5a78b8 100644
--- a/ambari-web/app/views/main/dashboard.js
+++ b/ambari-web/app/views/main/dashboard.js
@@ -82,9 +82,13 @@ App.MainDashboardView = Em.View.extend({
         case "HBASE":
           self.set('hbase_model', App.HBaseService.find(item.get('id')) || item);
           break;
+        case "STORM":
+          self.set('storm_model', item);
+          break;
       }
     }, this);
   },
+
   setInitPrefObject: function() {
     //in case of some service not installed
     var visibleFull = [
@@ -93,7 +97,8 @@ App.MainDashboardView = Em.View.extend({
       '18', '1', '6', '5', '9',
       '3', '7', '15', '16', '20',
       '19', '21', '23',
-      '24', '25', '26', '27'// all yarn
+      '24', '25', '26', '27',// all yarn
+      '28' // storm
     ]; // all in order
     var hiddenFull = [['22','Region In Transition']];
     if (this.get('hdfs_model') == null) {
@@ -114,12 +119,19 @@ App.MainDashboardView = Em.View.extend({
         visibleFull = visibleFull.without(item);
       }, this);
       hiddenFull = [];
-    }if (this.get('yarn_model') == null) {
+    }
+    if (this.get('yarn_model') == null) {
       var yarn = ['24', '25', '26', '27'];
       yarn.forEach ( function (item) {
         visibleFull = visibleFull.without(item);
       }, this);
     }
+    if (this.get('storm_model') == null) {
+      var storm = ['28'];
+      storm.forEach(function(item) {
+        visibleFull = visibleFull.without(item);
+      }, this);
+    }
     var obj = this.get('initPrefObject');
     obj.set('visible', visibleFull);
     obj.set('hidden', hiddenFull);
@@ -130,6 +142,7 @@ App.MainDashboardView = Em.View.extend({
   mapreduce2_model: null,
   yarn_model: null,
   hbase_model: null,
+  storm_model: null,
   visibleWidgets: [],
   hiddenWidgets: [], // widget child view will push object in this array if deleted
 
@@ -313,6 +326,18 @@ App.MainDashboardView = Em.View.extend({
         toAdd = toAdd.concat(yarn);
       }
     }
+    if (this.get('storm_model') != null) {
+      var storm = ['28'];
+      var flag = self.containsWidget(toDelete, storm[0]);
+      var self = this;
+      if (flag) {
+        storm.forEach ( function (item) {
+          toDelete = self.removeWidget(toDelete, item);
+        }, this);
+      } else {
+        toAdd = toAdd.concat(storm);
+      }
+    }
     var value = currentPrefObject;
     if (toDelete.visible.length || toDelete.hidden.length) {
       toDelete.visible.forEach ( function (item) {
@@ -362,6 +387,7 @@ App.MainDashboardView = Em.View.extend({
       case '25': return App.ResourceManagerUptimeView;
       case '26': return App.NodeManagersLiveView;
       case '27': return App.YARNMemoryPieChartView;
+      case '28': return App.SuperVisorUpView;
     }
   },
 
@@ -372,7 +398,7 @@ App.MainDashboardView = Em.View.extend({
     hidden: [],
     threshold: {1: [80, 90], 2: [85, 95], 3: [90, 95], 4: [80, 90], 5: [1000, 3000], 6: [70, 90], 7: [90, 95], 8: [50, 75], 9: [30000, 120000],
       10: [], 11: [], 12: [], 13: [], 14: [], 15: [], 16: [], 17: [], 18: [], 19: [], 20: [70, 90], 21: [10, 19.2], 22: [3, 10], 23: [],
-      24: [70, 90], 25: [], 26: [50, 75], 27: [50, 75]} // id:[thresh1, thresh2]
+      24: [70, 90], 25: [], 26: [50, 75], 27: [50, 75], 28: [85, 95]} // id:[thresh1, thresh2]
   }),
   persistKey: function () {
     var loginName = App.router.get('loginName');
@@ -413,7 +439,6 @@ App.MainDashboardView = Em.View.extend({
    * post persist key/value to server, value is object
    */
   postUserPref: function (key, value) {
-    var url = App.apiPrefix + '/persist/';
     var keyValuePair = {};
     keyValuePair[key] = JSON.stringify(value);
 
@@ -453,6 +478,7 @@ App.MainDashboardView = Em.View.extend({
     }
     this.translateToReal(oldValue);
   },
+
   switchToNew: function () {
     if(!App.testMode){
       this.getUserPref(this.get('persistKey'));
@@ -486,6 +512,7 @@ App.MainDashboardView = Em.View.extend({
       }
     }, this);
   }.observes('App.router.updateController.isUpdate'),
+
   services: function () {
     var services = App.Service.find();
     if (this.get('content').length > 0) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/386330fd/ambari-web/app/views/main/dashboard/widget.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widget.js b/ambari-web/app/views/main/dashboard/widget.js
index 07751a7..8c55598 100644
--- a/ambari-web/app/views/main/dashboard/widget.js
+++ b/ambari-web/app/views/main/dashboard/widget.js
@@ -23,16 +23,15 @@ App.DashboardWidgetView = Em.View.extend({
   title: null,
   templateName: null, // each has specific template
 
+  /**
+   * Setup model for widget by `model_type`. Usually `model_type` is a lowercase service name,
+   * for example `hdfs`, `yarn`, etc. You need to set `model_type` in extended object View, for example
+   * look App.DataNodeUpView.
+   * @return {Object} - model that set up in App.MainDashboardView.setWidgetsDataModel()
+   */
   model : function () {
-    if (this.get('model_type') == 'hdfs') {
-      return this.get('parentView').get('hdfs_model');
-    } else if (this.get('model_type') == 'mapreduce') {
-      return this.get('parentView').get('mapreduce_model');
-    } else if (this.get('model_type') == 'hbase') {
-      return this.get('parentView').get('hbase_model');
-    } else if (this.get('model_type') == 'yarn') {
-      return this.get('parentView').get('yarn_model');
-    }
+    if (!this.get('model_type')) return {};
+    return this.get('parentView').get(this.get('model_type') + '_model');
   }.property(), //data bind from parent view
 
   id: null, // id 1-10 used to identify
@@ -49,8 +48,8 @@ App.DashboardWidgetView = Em.View.extend({
   hiddenInfo: null, // more info details
   hiddenInfoClass: "hidden-info-two-line",
 
-  thresh1: null, //num not string
-  thresh2: null,
+  thresh1: null, //@type {Number}
+  thresh2: null, //@type {Number}
 
   didInsertElement: function () {
     App.tooltip(this.$("[rel='ZoomInTooltip']"), {placement : 'left'});

http://git-wip-us.apache.org/repos/asf/ambari/blob/386330fd/ambari-web/app/views/main/dashboard/widgets/supervisor_live.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/supervisor_live.js b/ambari-web/app/views/main/dashboard/widgets/supervisor_live.js
new file mode 100644
index 0000000..597cb7f
--- /dev/null
+++ b/ambari-web/app/views/main/dashboard/widgets/supervisor_live.js
@@ -0,0 +1,177 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.SuperVisorUpView = App.TextDashboardWidgetView.extend({
+
+  title: Em.I18n.t('dashboard.widgets.SuperVisorUp'),
+  id: '28',
+
+  isPieChart: false,
+  isText: true,
+  isProgressBar: false,
+  model_type: 'storm',
+
+  hiddenInfo: function () {
+    var result = [];
+    result.pushObject(this.get('superVisorsLive').length + ' ' + Em.I18n.t('dashboard.services.hdfs.nodes.live'));
+    result.pushObject(this.get('superVisorsDead').length + ' ' + Em.I18n.t('dashboard.services.hdfs.nodes.dead'));
+    return result;
+  }.property('superVisorsLive', 'superVisorsDead'),
+  hiddenInfoClass: "hidden-info-two-line",
+
+  thresh1: 40,
+  thresh2: 70,
+  maxValue: 100,
+
+  superVisorComponents: function() {
+    return this.get('model.hostComponents').filterProperty('componentName', 'SUPERVISOR');
+  }.property('model.hostComponents.length'),
+
+  superVisorsLive: function () {
+    return this.get('superVisorComponents').filterProperty("workStatus", "STARTED");
+  }.property('superVisorComponents.@each.workStatus'),
+
+  superVisorsDead: function () {
+    return this.get('superVisorComponents').filterProperty("workStatus", "INSTALLED");
+  }.property('superVisorComponents.@each.workStatus'),
+
+
+  data: function () {
+    if ( !this.get('superVisorComponents.length')) {
+      return -1;
+    } else {
+      return ((this.get('superVisorsLive').length / this.get('model.hostComponents').filterProperty('componentName', 'SUPERVISOR').length).toFixed(2)) * 100;
+    }
+  }.property('model.hostComponents.length', 'superVisorsLive'),
+
+  content: function () {
+    return this.get('superVisorsLive').length + "/" + this.get('superVisorComponents').length;
+  }.property('superVisorComponents.length', 'superVisorsLive'),
+
+  editWidget: function (event) {
+    var parent = this;
+    var max_tmp =  parseFloat(parent.get('maxValue'));
+    var configObj = Ember.Object.create({
+      thresh1: parent.get('thresh1') + '',
+      thresh2: parent.get('thresh2') + '',
+      hintInfo: Em.I18n.t('dashboard.widgets.hintInfo.hint1').format(max_tmp),
+      isThresh1Error: false,
+      isThresh2Error: false,
+      errorMessage1: "",
+      errorMessage2: "",
+      maxValue: max_tmp,
+      observeNewThresholdValue: function () {
+        var thresh1 = this.get('thresh1');
+        var thresh2 = this.get('thresh2');
+        if (thresh1.trim() != "") {
+          if (isNaN(thresh1) || thresh1 > max_tmp || thresh1 < 0){
+            this.set('isThresh1Error', true);
+            this.set('errorMessage1', 'Invalid! Enter a number between 0 - ' + max_tmp);
+          } else if ( this.get('isThresh2Error') === false && parseFloat(thresh2)<= parseFloat(thresh1)) {
+            this.set('isThresh1Error', true);
+            this.set('errorMessage1', 'Threshold 1 should be smaller than threshold 2 !');
+          } else {
+            this.set('isThresh1Error', false);
+            this.set('errorMessage1', '');
+          }
+        } else {
+          this.set('isThresh1Error', true);
+          this.set('errorMessage1', 'This is required');
+        }
+
+        if (thresh2.trim() != "") {
+          if (isNaN(thresh2) || thresh2 > max_tmp || thresh2 < 0) {
+            this.set('isThresh2Error', true);
+            this.set('errorMessage2', 'Invalid! Enter a number between 0 - ' + max_tmp);
+          } else {
+            this.set('isThresh2Error', false);
+            this.set('errorMessage2', '');
+          }
+        } else {
+          this.set('isThresh2Error', true);
+          this.set('errorMessage2', 'This is required');
+        }
+
+        // update the slider handles and color
+        if (this.get('isThresh1Error') === false && this.get('isThresh2Error') === false) {
+          $("#slider-range").slider('values', 0 , parseFloat(thresh1));
+          $("#slider-range").slider('values', 1 , parseFloat(thresh2));
+        }
+      }.observes('thresh1', 'thresh2')
+
+    });
+
+    var browserVerion = this.getInternetExplorerVersion();
+    App.ModalPopup.show({
+      header: Em.I18n.t('dashboard.widgets.popupHeader'),
+      classNames: [ 'sixty-percent-width-modal-edit-widget'],
+      bodyClass: Ember.View.extend({
+        templateName: require('templates/main/dashboard/edit_widget_popup'),
+        configPropertyObj: configObj
+      }),
+      primary: Em.I18n.t('common.apply'),
+      onPrimary: function () {
+        configObj.observeNewThresholdValue();
+        if (!configObj.isThresh1Error && !configObj.isThresh2Error) {
+          parent.set('thresh1', parseFloat(configObj.get('thresh1')) );
+          parent.set('thresh2', parseFloat(configObj.get('thresh2')) );
+          if (!App.testMode) {
+            var big_parent = parent.get('parentView');
+            big_parent.getUserPref(big_parent.get('persistKey'));
+            var oldValue = big_parent.get('currentPrefObject');
+            oldValue.threshold[parseInt(parent.id)] = [configObj.get('thresh1'), configObj.get('thresh2')];
+            big_parent.postUserPref(big_parent.get('persistKey'),oldValue);
+          }
+          this.hide();
+        }
+      },
+
+      didInsertElement: function () {
+        var handlers = [configObj.get('thresh1'), configObj.get('thresh2')];
+        var colors = ['#B80000', '#FF8E00', '#95A800']; //color red, orange, green
+
+        if (browserVerion == -1 || browserVerion > 9) {
+          configObj.set('isIE9', false);
+          configObj.set('isGreenOrangeRed', false);
+          $("#slider-range").slider({
+            range: true,
+            min: 0,
+            max: max_tmp,
+            values: handlers,
+            create: function (event, ui) {
+              parent.updateColors(handlers, colors);
+            },
+            slide: function (event, ui) {
+              parent.updateColors(ui.values, colors);
+              configObj.set('thresh1', ui.values[0] + '');
+              configObj.set('thresh2', ui.values[1] + '');
+            },
+            change: function (event, ui) {
+              parent.updateColors(ui.values, colors);
+            }
+          });
+        } else {
+          configObj.set('isIE9', true);
+          configObj.set('isGreenOrangeRed', false);
+        }
+      }
+    });
+  }
+});