浏览代码

AMBARI-1145. Cluster Management refactoring. (yusaku)

git-svn-id: https://svn.apache.org/repos/asf/incubator/ambari/trunk@1431645 13f79535-47bb-0310-9956-ffa450edef68
Yusaku Sako 12 年之前
父节点
当前提交
a38f982d32

+ 56 - 1
ambari-web/app/controllers/global/cluster_controller.js

@@ -22,6 +22,10 @@ App.ClusterController = Em.Controller.extend({
   name:'clusterController',
   cluster:null,
   isLoaded:false,
+  /**
+   * Whether we need to update statuses automatically or not
+   */
+  isWorking: false,
   updateLoadStatus:function (item) {
     var loadList = this.get('dataLoadList');
     var loaded = true;
@@ -246,6 +250,57 @@ App.ClusterController = Em.Controller.extend({
       secondary : null
     });
   },
+
+  statusTimeoutId: null,
+
+  loadUpdatedStatusDelayed: function(delay){
+    delay = delay || App.componentsUpdateInterval;
+    var self = this;
+
+    this.set('statusTimeoutId',
+      setTimeout(function(){
+        self.loadUpdatedStatus();
+      }, delay)
+    );
+  },
+
+  loadUpdatedStatus: function(){
+
+    var timeoutId = this.get('statusTimeoutId');
+    if(timeoutId){
+      clearTimeout(timeoutId);
+      this.set('statusTimeoutId', null);
+    }
+
+    if(!this.get('isWorking')){
+      return false;
+    }
+
+    if(!this.get('clusterName')){
+      this.loadUpdatedStatusDelayed(this.get('componentsUpdateInterval')/2, 'error:clusterName');
+      return;
+    }
+    
+    var servicesUrl = this.getUrl('/data/dashboard/services.json', '/services?fields=components/ServiceComponentInfo,components/host_components,components/host_components/HostRoles');
+
+    var self = this;
+    App.HttpClient.get(servicesUrl, App.statusMapper, {
+      complete:function (jqXHR, textStatus) {
+        //console.log('Cluster Controller: Updated components statuses successfully!!!')
+        self.loadUpdatedStatusDelayed();
+      }
+    }, function(){
+      self.loadUpdatedStatusDelayed(null, 'error:response error');
+    });
+
+  },
+  startLoadUpdatedStatus: function(){
+    var self = this;
+    this.set('isWorking', true);
+    setTimeout(function(){
+      self.loadUpdatedStatus();
+    }, App.componentsUpdateInterval*2);
+  },
   /**
    *
    *  load all data and update load status
@@ -297,7 +352,7 @@ App.ClusterController = Em.Controller.extend({
       self.updateLoadStatus('users');
     });
 
-    App.router.get('updateController').updateServices(function(){
+    App.router.get('updateController').updateServiceMetric(function(){
       self.updateLoadStatus('services');
     }, true);
 

+ 3 - 3
ambari-web/app/controllers/global/update_controller.js

@@ -40,7 +40,7 @@ App.UpdateController = Em.Controller.extend({
       if(timeIntervalId) return;
       this.set('timeIntervalId', setInterval(function(){
         self.updateHost();
-        self.updateServices();
+        self.updateServiceMetric();
         self.graphsUpdate();
       }, App.contentUpdateInterval));
     } else {
@@ -74,11 +74,11 @@ App.UpdateController = Em.Controller.extend({
   },
   
   /**
-   * Updates the services and their components information.
+   * Updates the services information. 
    * 
    * @param isInitialLoad  If true, only basic information is loaded.
    */
-  updateServices: function (callback, isInitialLoad) {
+  updateServiceMetric: function (callback, isInitialLoad) {
     var self = this;
     self.set('isUpdated', false);
     var servicesUrl = isInitialLoad ? 

+ 2 - 0
ambari-web/app/controllers/main.js

@@ -63,9 +63,11 @@ App.MainController = Em.Controller.extend({
   startPolling: function(){
     App.router.get('updateController').set('isWorking', true);
     App.router.get('backgroundOperationsController').set('isWorking', true);
+    App.router.get('clusterController').startLoadUpdatedStatus();
   },
   stopPolling: function(){
     App.router.get('updateController').set('isWorking', false);
     App.router.get('backgroundOperationsController').set('isWorking', false);
+    App.router.get('clusterController').set('isWorking', false);
   }
 })

+ 2 - 0
ambari-web/app/initialize.js

@@ -30,6 +30,7 @@ App.timeout = 20000;
 // retry times
 App.times = 3;
 App.bgOperationsUpdateInterval = 6000;
+App.componentsUpdateInterval = 6000;
 App.contentUpdateInterval = 15000;
 
 require('messages');
@@ -44,6 +45,7 @@ require('views');
 require('router');
 
 require('mappers/server_data_mapper');
+require('mappers/status_mapper');
 require('mappers/hosts_mapper');
 require('mappers/cluster_mapper');
 require('mappers/jobs_mapper');

+ 122 - 76
ambari-web/app/mappers/service_mapper.js

@@ -143,57 +143,146 @@ App.servicesMapper = App.QuickDataMapper.create({
     }
 
     if (json.items) {
-      var addArray = [];
+      var result = [];
       json.items.forEach(function (item) {
         var finalConfig = jQuery.extend({}, this.config);
-        var finalJson, commonJson;
+        var finalJson = [];
         item.host_components = [];
+        if (this.get('model').find(item.ServiceInfo.service_name).get('isLoaded')) {
+          this.update(item);
+          return;
+        }
         item.components.forEach(function (component) {
           component.host_components.forEach(function (host_component) {
             host_component.id = host_component.HostRoles.component_name + "_" + host_component.HostRoles.host_name;
             item.host_components.push(host_component.id);
           }, this)
         }, this);
-        commonJson = this.parseIt(item, this.config);
+
         if (item && item.ServiceInfo && item.ServiceInfo.service_name == "HDFS") {
           // Change the JSON so that it is easy to map
           finalJson = this.hdfsMapper(item);
-          this.updateServices(commonJson, finalJson, addArray, App.HDFSService);
+          result.push(finalJson);
+          App.store.load(App.HDFSService, finalJson);
         } else if (item && item.ServiceInfo && item.ServiceInfo.service_name == "MAPREDUCE") {
           finalJson = this.mapreduceMapper(item);
-          this.updateServices(commonJson, finalJson, addArray, App.MapReduceService);
+          result.push(finalJson);
+          App.store.load(App.MapReduceService, finalJson);
         } else if (item && item.ServiceInfo && item.ServiceInfo.service_name == "HBASE") {
           finalJson = this.hbaseMapper(item);
-          this.updateServices(commonJson, finalJson, addArray, App.HBaseService);
+          result.push(finalJson);
+          App.store.load(App.HBaseService, finalJson);
         } else {
-          finalJson = commonJson;
-          this.updateServices(commonJson, finalJson, addArray);
+          result.push(this.parseIt(item, this.config));
         }
       }, this);
 
-      addArray = this.sortByOrder(this.get('servicesSortOrder'), addArray);
-      App.store.loadMany(this.get('model'), addArray);
 
-      addArray = [];
+      result = this.sortByOrder(this.get('servicesSortOrder'), result);
+      App.store.loadMany(this.get('model'), result);
+
+      result = [];
       json.items.forEach(function (item) {
         item.components.forEach(function (component) {
-          var finalJson = this.parseIt(component, this.config2);
-          this.updateHostsComponents(finalJson, addArray, this.get('model2'));
+          result.push(this.parseIt(component, this.config2));
         }, this)
       }, this);
 
-      App.store.loadMany(this.get('model2'), addArray);
+      App.store.loadMany(this.get('model2'), result);
 
-      addArray = [];
+      result = [];
       json.items.forEach(function (item) {
         item.components.forEach(function (component) {
           component.host_components.forEach(function (host_component) {
-            var finalJson = this.parseIt(component, this.config2);
-            this.updateHostsComponents(finalJson, addArray, this.get('model3'));
+            result.push(this.parseIt(host_component, this.config3));
           }, this)
         }, this)
       }, this);
-      App.store.loadMany(this.get('model3'), addArray);
+      App.store.loadMany(this.get('model3'), result);
+    }
+  },
+  update: function (service) {
+    var finalJson;
+    switch (service.ServiceInfo.service_name) {
+      case 'HDFS':
+        finalJson = this.hdfsMapper(service);
+        App.HDFSService.find().map(function (e) {
+          e.set("version", finalJson.version);
+          e.set("nameNodeStartTime", finalJson.name_node_start_time);
+          e.set("jvmMemoryHeapCommitted", finalJson.jvm_memory_heap_committed);
+          e.set("jvmMemoryHeapUsed", finalJson.jvm_memory_heap_used);
+          e.set("capacityUsed", finalJson.capacity_used);
+          e.set("capacityTotal", finalJson.capacity_total);
+          e.set("dfsTotalBlocks", finalJson.dfs_total_blocks);
+          e.set("dfsCorruptBlocks", finalJson.dfs_corrupt_blocks);
+          e.set("dfsMissingBlocks", finalJson.dfs_missing_blocks);
+          e.set("dfsUnderReplicatedBlocks", finalJson.dfs_under_replicated_blocks);
+          e.set("dfsTotalFiles", finalJson.dfs_total_files);
+          e.set("upgradeStatus", finalJson.upgrade_status);
+          e.set("safeModeStatus", finalJson.safe_mode_status);
+          // Live data nodes
+          var dataNodes = e.get('liveDataNodes');
+          if (dataNodes) {
+            dataNodes.clear();
+            finalJson.live_data_nodes.forEach(function (ldn) {
+              dataNodes.pushObject(App.Host.find(ldn));
+            });
+          }
+          // Decommission data nodes
+          dataNodes = e.get('decommissionDataNodes');
+          if (dataNodes) {
+            dataNodes.clear();
+            finalJson.decommission_data_nodes.forEach(function (ldn) {
+              dataNodes.pushObject(App.Host.find(ldn));
+            });
+          }
+          // Dead data nodes
+          dataNodes = e.get('deadDataNodes');
+          if (dataNodes) {
+            dataNodes.clear();
+            finalJson.dead_data_nodes.forEach(function (ldn) {
+              dataNodes.pushObject(App.Host.find(ldn));
+            });
+          }
+        });
+        break;
+      case 'MAPREDUCE':
+        finalJson = this.mapreduceMapper(service);
+        App.MapReduceService.find().map(function (e) {
+          e.set("version", finalJson.version);
+          e.set("jobTrackerStartTime", finalJson.job_tracker_start_time);
+          e.set("jobTrackerHeapUsed", finalJson.job_tracker_heap_used);
+          e.set("jobTrackerHeapMax", finalJson.job_tracker_heap_max);
+          e.set("mapSlots", finalJson.map_slots);
+          e.set("reduceSlots", finalJson.reduce_slots);
+          e.set("jobsSubmitted", finalJson.jobs_submitted);
+          e.set("jobsCompleted", finalJson.jobs_completed);
+          e.set("mapSlotsOccupied", finalJson.map_slots_occupied);
+          e.set("mapSlotsReserved", finalJson.map_slots_reserved);
+          e.set("reduceSlotsOccupied", finalJson.reduce_slots_occupied);
+          e.set("reduceSlotsReserved", finalJson.reduce_slots_reserved);
+          e.set("mapsRunning", finalJson.maps_running);
+          e.set("mapsWaiting", finalJson.maps_waiting);
+          e.set("reducesRunning", finalJson.reduces_running);
+          e.set("reducesWaiting", finalJson.reduces_waiting);
+          e.set("trackersDecommissioned", finalJson.trackers_decommissioned);
+        })
+        break;
+      case 'HBASE':
+        finalJson = this.hbaseMapper(service);
+        App.HBaseService.find().map(function (e) {
+          e.set("version", finalJson.version);
+          e.set("masterStartTime", finalJson.master_start_time);
+          e.set("masterActiveTime", finalJson.master_active_time);
+          e.set("averageLoad", finalJson.average_load);
+          e.set("regionsInTransition", finalJson.regions_in_transition);
+          e.set("revision", finalJson.revision);
+          e.set("heapMemoryUsed", finalJson.heap_memory_used);
+          e.set("heapMemoryMax", finalJson.heap_memory_max);
+        })
+        break;
+      default:
+        this.otherMapper(service);
     }
   },
   otherMapper: function (item) {
@@ -334,67 +423,24 @@ App.servicesMapper = App.QuickDataMapper.create({
     finalJson.quick_links = [13, 14, 15, 16, 17, 18];
     return finalJson;
   },
-  /**
-   * update or add records for service model
-   * if model defined updates Service model  and particular model that defined
-   * @param json
-   * @param addArray
-   * @param model
-   */
-  updateServices: function (commonJson, json, addArray, model) {
-    var commonOldItem = this.get('model').find().filterProperty('id', json.id);
-    var oldItem = (model) ? model.find().filterProperty('id', json.id) : [];
-    if(commonOldItem.length){
-      for (var field in json) {
-        if (field !== 'id') {
-//          if(commonJson.hasOwnProperty(field)){
-//            (json[field] instanceof Array)? this.setHasMany(field, json[field], commonOldItem[0]) : commonOldItem[0].set(field, json[field]);
-//          }
-          if(commonJson.hasOwnProperty(field)){
-            commonOldItem[0].set(field, json[field]);
-          }
-          if(oldItem.length){
-            oldItem[0].set(field, json[field]);
+  _update: function(model, json){
+    var content = model.find();
+    var addArray = [];
+    for(var i in json){
+      var item = json[i];
+      var oldItem = content.findProperty('id', item.id);
+      if(oldItem){
+
+        for(var field in item){ ///<--
+          if(field !== 'id'){
+            oldItem.set(field, item[field]);  //<--
           }
         }
+
+      } else {
+        addArray.push(item);
       }
-    } else {
-      addArray.push(commonJson);
-      if(model){
-        App.store.load(model, json)
-      }
-    }
-  },
-  /**
-   * add or update records for host and component models
-   * @param json
-   * @param addArray
-   * @param model
-   */
-  updateHostsComponents: function(json, addArray, model){
-    var oldItem = model.find().filterProperty('id', json.id);
-    if(oldItem.length){
-      for (var field in json) {
-        if (field !== 'id') {
-          oldItem[0].set(field, json[field]);
-        }
-      }
-    } else {
-      addArray.push(json);
     }
-  },
-  /**
-   * update hasMany relations in model
-   * @param key
-   * @param value
-   * @param oldItem
-   */
-  setHasMany:function(key, value, oldItem){
-    var model;
-    value.clear();
-    value.forEach(function (item) {
-      oldItem.pushObject(model.find(item));
-    }, this);
+    App.store.loadMany(model, addArray);
   }
-
 });

+ 96 - 0
ambari-web/app/mappers/status_mapper.js

@@ -0,0 +1,96 @@
+/**
+ * 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.
+ */
+
+App.statusMapper = App.QuickDataMapper.create({
+
+  config:{
+    id:'ServiceInfo.service_name',
+    work_status:'ServiceInfo.state'
+  },
+
+  config2:{
+    id:'ServiceComponentInfo.component_name',
+    work_status:'host_components[0].HostRoles.state'
+  },
+
+  config3:{
+    id:'id',
+    work_status:'HostRoles.state'
+  },
+
+  map:function (json) {
+
+    if (json.items) {
+      var result = [];
+      json.items.forEach(function (item) {
+
+        item.host_components = [];
+        item.components.forEach(function (component) {
+          component.host_components.forEach(function (host_component) {
+            host_component.id = host_component.HostRoles.component_name + "_" + host_component.HostRoles.host_name;
+            item.host_components.push(host_component.id);
+          }, this)
+        }, this);
+
+        result.push(this.parseIt(item, this.config));
+      }, this);
+
+      //console.log(result)
+      var services = App.Service.find();
+      result.forEach(function(item){
+        var service = services.findProperty('id', item.id);
+        if(service){
+          service.set('workStatus', item.work_status);
+        }
+      })
+
+      result = [];
+      json.items.forEach(function (item) {
+        item.components.forEach(function (component) {
+          result.push(this.parseIt(component, this.config2));
+        }, this)
+      }, this);
+
+      //console.log(result)
+      var components = App.Component.find();
+      result.forEach(function(item){
+        var component = components.findProperty('id', item.id);
+        if(component){
+          component.set('workStatus', item.work_status);
+        }
+      })
+
+      result = [];
+      json.items.forEach(function (item) {
+        item.components.forEach(function (component) {
+          component.host_components.forEach(function (host_component) {
+            result.push(this.parseIt(host_component, this.config3));
+          }, this)
+        }, this)
+      }, this);
+
+      //console.log(result)
+      var hostComponents = App.HostComponent.find();
+      result.forEach(function(item){
+        var hostComponent = hostComponents.findProperty('id', item.id);
+        if(hostComponent){
+          hostComponent.set('workStatus', item.work_status);
+        }
+      })
+    }
+  }
+});

+ 0 - 1
ambari-web/app/models/service/hbase.js

@@ -18,7 +18,6 @@
 var App = require('app');
 
 App.HBaseService = App.Service.extend({
-  serviceName: DS.attr('string'),
   version: DS.attr('string'),
   master: DS.belongsTo('App.Host'),
   regionServers: DS.hasMany('App.Host'),

+ 0 - 1
ambari-web/app/models/service/hdfs.js

@@ -18,7 +18,6 @@
 var App = require('app');
 
 App.HDFSService = App.Service.extend({
-  serviceName: DS.attr('string'),
   version: DS.attr('string'),
   nameNode: DS.belongsTo('App.Host'),
   snameNode: DS.belongsTo('App.Host'),

+ 0 - 1
ambari-web/app/models/service/mapreduce.js

@@ -18,7 +18,6 @@
 var App = require('app');
 
 App.MapReduceService = App.Service.extend({
-  serviceName: DS.attr('string'),
   version: DS.attr('string'),
   jobTracker: DS.belongsTo('App.Host'),
   taskTrackers: DS.hasMany('App.Host'),