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

git commit: AMBARI-5926 Integrate server-side filtering and sorting for Hosts page. (atkach)

Repository: ambari
Updated Branches:
  refs/heads/trunk 776c9d704 -> ff2b111b1


AMBARI-5926 Integrate server-side filtering and sorting for Hosts page. (atkach)


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

Branch: refs/heads/trunk
Commit: ff2b111b15dd690c4aa73b04b8e6fe564e0f29c9
Parents: 776c9d7
Author: atkach <at...@hortonworks.com>
Authored: Thu May 29 15:47:50 2014 +0300
Committer: atkach <at...@hortonworks.com>
Committed: Thu May 29 15:47:50 2014 +0300

----------------------------------------------------------------------
 .../data/stacks/HDP-2.1/service_components.json |  12 -
 .../controllers/global/cluster_controller.js    |  24 +-
 .../app/controllers/global/update_controller.js |  49 +++-
 ambari-web/app/controllers/main/host.js         | 241 ++++++++++++++++++-
 ambari-web/app/data/host/categories.js          |  31 ++-
 ambari-web/app/mappers/hosts_mapper.js          | 131 +---------
 ambari-web/app/mappers/status_mapper.js         |  44 +---
 .../app/mixins/common/tableServerProvider.js    |  98 +++++---
 ambari-web/app/templates/main/host.hbs          |   2 +-
 ambari-web/app/views/common/sort_view.js        | 127 +++++++---
 ambari-web/app/views/common/table_view.js       |  59 -----
 ambari-web/app/views/main/host.js               | 183 +++++++-------
 12 files changed, 586 insertions(+), 415 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/ff2b111b/ambari-web/app/assets/data/stacks/HDP-2.1/service_components.json
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/data/stacks/HDP-2.1/service_components.json b/ambari-web/app/assets/data/stacks/HDP-2.1/service_components.json
index cd1ac19..b8faddc 100644
--- a/ambari-web/app/assets/data/stacks/HDP-2.1/service_components.json
+++ b/ambari-web/app/assets/data/stacks/HDP-2.1/service_components.json
@@ -456,18 +456,6 @@
           }
         },
         {
-          "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/STORM/serviceComponents/LOGVIEWER_SERVER",
-          "StackServiceComponents" : {
-            "component_category" : "MASTER",
-            "component_name" : "LOGVIEWER_SERVER",
-            "is_client" : false,
-            "is_master" : true,
-            "service_name" : "STORM",
-            "stack_name" : "HDP",
-            "stack_version" : "2.1"
-          }
-        },
-        {
           "href" : "http://localhost:8080/api/v1/stacks/HDP/versions/2.1/stackServices/STORM/serviceComponents/NIMBUS",
           "StackServiceComponents" : {
             "component_category" : "MASTER",

http://git-wip-us.apache.org/repos/asf/ambari/blob/ff2b111b/ambari-web/app/controllers/global/cluster_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/global/cluster_controller.js b/ambari-web/app/controllers/global/cluster_controller.js
index dff0f57..016b09b 100644
--- a/ambari-web/app/controllers/global/cluster_controller.js
+++ b/ambari-web/app/controllers/global/cluster_controller.js
@@ -339,25 +339,33 @@ App.ClusterController = Em.Controller.extend({
      * 10. update stale_configs of host-components (depends on App.supports.hostOverrides)
      */
     this.loadStackServiceComponents(function (data) {
+      var updater = App.router.get('updateController');
+
       require('utils/component').loadStackServiceComponentModel(data);
       self.updateLoadStatus('stackComponents');
-      App.router.get('updateController').updateServices(function () {
+      updater.updateServices(function () {
         self.updateLoadStatus('services');
+
         self.loadUpdatedStatus(function () {
-          self.updateLoadStatus('hosts');
+
+          updater.updateHost(function () {
+            self.updateLoadStatus('hosts');
+          });
+
+          updater.updateServiceMetric(function () {
+            updater.updateComponentsState(function () {
+              self.updateLoadStatus('componentsState');
+            });
+          });
+
           if (App.supports.hostOverrides) {
-            App.router.get('updateController').updateComponentConfig(function () {
+            updater.updateComponentConfig(function () {
               self.updateLoadStatus('componentConfigs');
             });
           } else {
             self.updateLoadStatus('componentConfigs');
           }
         }, true);
-        App.router.get('updateController').updateServiceMetric(function () {
-          App.router.get('updateController').updateComponentsState(function () {
-            self.updateLoadStatus('componentsState');
-          });
-        });
       });
     });
   },

http://git-wip-us.apache.org/repos/asf/ambari/blob/ff2b111b/ambari-web/app/controllers/global/update_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/global/update_controller.js b/ambari-web/app/controllers/global/update_controller.js
index dca6f0d..a8fd0a3 100644
--- a/ambari-web/app/controllers/global/update_controller.js
+++ b/ambari-web/app/controllers/global/update_controller.js
@@ -43,19 +43,52 @@ App.UpdateController = Em.Controller.extend({
    * @return {String}
    */
   getComplexUrl: function (testUrl, realUrl, queryParams) {
-    var url = App.apiPrefix + '/clusters/' + App.get('clusterName');
+    var prefix = App.apiPrefix + '/clusters/' + App.get('clusterName');
     var params = '';
+
     if (App.testMode) {
-      url = testUrl;
+      return testUrl;
     } else {
       if (queryParams) {
-        queryParams.forEach(function (param) {
-          params += param.key + '=' + param.value + '&';
-        });
+        params = this.computeParameters(queryParams);
       }
-      url += realUrl.replace('<parameters>', params);
+      return prefix + realUrl.replace('<parameters>', params);
     }
-    return url;
+  },
+
+  /**
+   * compute parameters according to their type
+   * @param queryParams
+   * @return {String}
+   */
+  computeParameters: function (queryParams) {
+    var params = '';
+
+    queryParams.forEach(function (param) {
+      switch (param.type) {
+        case 'PLAIN':
+          params += param.key + '=' + param.value;
+          break;
+        case 'MATCH':
+          params += param.key + '.matches(' + param.value + ')';
+          break;
+        case 'NUMBER':
+          //TODO should be added predicates of comparison (<,>,=)
+          params += param.key + '=' + param.value;
+          break;
+        case 'MULTIPLE':
+          params += param.key + '.in(' + param.value.join(',') + ')';
+          break;
+        case 'SORT':
+          params += 'sortBy=' + param.key + '.' + param.value;
+          break;
+        case 'CRITICAL_ALERTS':
+          params += param.key;
+          break;
+      }
+      params += '&';
+    });
+    return params;
   },
 
   /**
@@ -123,6 +156,8 @@ App.UpdateController = Em.Controller.extend({
       'Hosts/host_status,Hosts/last_heartbeat_time,Hosts/os_arch,Hosts/os_type,Hosts/ip,host_components/HostRoles/state,host_components/HostRoles/maintenance_state,' +
       'Hosts/disk_info,metrics/disk,metrics/load/load_one,metrics/cpu/cpu_system,metrics/cpu/cpu_user,' +
       'metrics/memory/mem_total,metrics/memory/mem_free,alerts/summary&minimal_response=true';
+
+    this.get('queryParams').set('Hosts', App.router.get('mainHostController').getQueryParameters());
     var hostsUrl = this.getComplexUrl(testUrl, realUrl, this.get('queryParams.Hosts'));
     App.HttpClient.get(hostsUrl, App.hostsMapper, {
       complete: callback

http://git-wip-us.apache.org/repos/asf/ambari/blob/ff2b111b/ambari-web/app/controllers/main/host.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host.js b/ambari-web/app/controllers/main/host.js
index be98bc1..4378256 100644
--- a/ambari-web/app/controllers/main/host.js
+++ b/ambari-web/app/controllers/main/host.js
@@ -21,10 +21,10 @@ var validator = require('utils/validator');
 var componentHelper = require('utils/component');
 var batchUtils = require('utils/batch_scheduled_requests');
 
-App.MainHostController = Em.ArrayController.extend({
-  name:'mainHostController',
-  content: App.Host.find(),
+App.MainHostController = Em.ArrayController.extend(App.UserPref, {
+  name: 'mainHostController',
 
+  dataSource: App.Host.find(),
   clearFilters: null,
 
   /**
@@ -61,11 +61,185 @@ App.MainHostController = Em.ArrayController.extend({
     return this.get('componentsForFilter').filterProperty('isClient', true);
   }.property('componentsForFilter'),
 
+  content: function () {
+    return this.get('dataSource').filterProperty('isRequested');
+  }.property('dataSource.@each.isRequested'),
+
+  filterProperties: [
+    {
+      key: 'publicHostName',
+      alias: 'Hosts/host_name',
+      type: 'MATCH'
+    },
+    {
+      key: 'ip',
+      alias: 'Hosts/ip',
+      type: 'MATCH'
+    },
+    {
+      key: 'cpu',
+      alias: 'Hosts/cpu_count',
+      type: 'PLAIN'
+    },
+    {
+      key: 'memoryFormatted',
+      alias: 'Hosts/total_mem',
+      type: 'NUMBER'
+    },
+    {
+      key: 'loadAvg',
+      alias: 'metrics/load/load_one',
+      type: 'NUMBER'
+    },
+    {
+      key: 'hostComponents',
+      alias: 'host_components/HostRoles/component_name',
+      type: 'MULTIPLE'
+    },
+    {
+      key: 'healthClass',
+      alias: 'Hosts/host_status',
+      type: 'PLAIN'
+    },
+    {
+      key: 'criticalAlertsCount',
+      alias: 'alerts/summary/CRITICAL>0|alerts/summary/WARNING>0',
+      type: 'CRITICAL_ALERTS'
+    },
+    {
+      key: 'componentsWithStaleConfigsCount',
+      alias: 'host_components/HostRoles/stale_configs',
+      type: 'PLAIN'
+    },
+    {
+      key: 'componentsInPassiveStateCount',
+      alias: 'host_components/HostRoles/maintenance_state',
+      type: 'PLAIN'
+    }
+  ],
+
+  viewProperties: [
+    Em.Object.create({
+      key: 'displayLength',
+      getValue: function (controller) {
+        var name = controller.get('name');
+        var dbValue = App.db.getDisplayLength(name);
+
+        if (Em.isNone(this.get('viewValue'))) {
+          if (dbValue) {
+            this.set('viewValue', dbValue);
+          } else {
+            controller.set('makeRequestAsync', false);
+            controller.getUserPref(controller.displayLengthKey());
+            App.db.setDisplayLength(name, this.get('viewValue'));
+          }
+        }
+        return this.get('viewValue');
+      },
+      viewValue: null,
+      alias: 'page_size'
+    }),
+    Em.Object.create({
+      key: 'startIndex',
+      getValue: function (controller) {
+        var name = controller.get('name');
+        var startIndex = App.db.getStartIndex(name);
+        var value = this.get('viewValue');
+
+        if (Em.isNone(value)) {
+          if (Em.isNone(startIndex)) {
+            value = 0;
+          } else {
+            value = startIndex;
+          }
+        }
+        return (value > 0) ? value - 1 : value;
+      },
+      viewValue: null,
+      alias: 'from'
+    })
+  ],
+
+  sortProps: [
+    {
+      key: 'publicHostName',
+      alias: 'Hosts/host_name'
+    },
+    {
+      key: 'ip',
+      alias: 'Hosts/ip'
+    },
+    {
+      key: 'cpu',
+      alias: 'Hosts/cpu_count'
+    },
+    {
+      key: 'memoryFormatted',
+      alias: 'Hosts/total_mem'
+    },
+    {
+      key: 'diskUsage',
+      //TODO disk_usage is relative property and need support from API, metrics/disk/disk_free used temporarily
+      alias: 'metrics/disk/disk_free'
+    },
+    {
+      key: 'loadAvg',
+      alias: 'metrics/load/load_one'
+    }
+  ],
+
+  /**
+   * get query parameters computed from filter properties, sort properties and custom properties of view
+   * @return {Array}
+   */
+  getQueryParameters: function () {
+    var queryParams = [];
+    var savedFilterConditions = App.db.getFilterConditions(this.get('name')) || [];
+    var savedSortConditions = App.db.getSortingStatuses(this.get('name')) || [];
+    var colPropAssoc = this.get('colPropAssoc');
+    var filterProperties = this.get('filterProperties');
+    var sortProperties = this.get('sortProps');
+
+    this.get('viewProperties').forEach(function (property) {
+      queryParams.push({
+        key: property.get('alias'),
+        value: property.getValue(this),
+        type: 'PLAIN'
+      })
+    }, this);
+
+    savedFilterConditions.forEach(function (filter) {
+      var property = filterProperties.findProperty('key', colPropAssoc[filter.iColumn]);
+
+      if (property && filter.value.length > 0) {
+        queryParams.push({
+          key: property.alias,
+          value: (filter.type === 'multiple') ? filter.value.split(',') : filter.value,
+          type: property.type
+        });
+      }
+    }, this);
+
+    savedSortConditions.forEach(function (sort) {
+      var property = sortProperties.findProperty('key', sort.name);
+
+      if (property && (sort.status === 'sorting_asc' || sort.status === 'sorting_desc')) {
+        queryParams.push({
+          key: property.alias,
+          value: sort.status.replace('sorting_', ''),
+          type: 'SORT'
+        });
+      }
+    });
+
+    return queryParams;
+  },
+
   /**
    * Filter hosts by componentName of <code>component</code>
    * @param {App.HostComponent} component
    */
-  filterByComponent:function (component) {
+  filterByComponent: function (component) {
     if(!component)
       return;
     var id = component.get('componentName');
@@ -79,6 +253,44 @@ App.MainHostController = Em.ArrayController.extend({
     };
     App.db.setFilterConditions(this.get('name'), [filterForComponent]);
   },
+
+  /**
+   * Persist-key of current table displayLength property
+   * @param {String} loginName current user login name
+   * @returns {String}
+   */
+  displayLengthKey: function (loginName) {
+    if (App.get('testMode')) {
+      return 'pagination_displayLength';
+    }
+    loginName = loginName ? loginName : App.router.get('loginName');
+    return this.get('name') + '-pagination-displayLength-' + loginName;
+  },
+
+  /**
+   * Set received from server value to <code>displayLengthOnLoad</code>
+   * @param {Number} response
+   * @param {Object} request
+   * @param {Object} data
+   * @returns {*}
+   */
+  getUserPrefSuccessCallback: function (response, request, data) {
+    console.log('Got DisplayLength value from server with key ' + data.key + '. Value is: ' + response);
+    this.get('viewProperties').findProperty('key', 'displayLength').set('viewValue', response);
+  },
+
+  /**
+   * Set default value to <code>displayLengthOnLoad</code> (and send it on server) if value wasn't found on server
+   * @returns {Number}
+   */
+  getUserPrefErrorCallback: function () {
+    // this user is first time login, so set default value - '25'
+    console.log('Persist did NOT find the key');
+    this.get('viewProperties').findProperty('key', 'displayLength').set('viewValue', '25');
+    if (App.get('isAdmin')) {
+      this.postUserPref(this.displayLengthKey(), '25');
+    }
+  },
   /**
    * On click callback for delete button
    */
@@ -497,6 +709,25 @@ App.MainHostController = Em.ArrayController.extend({
         App.router.get('backgroundOperationsController').showPopup();
       }
     });
-  }
+  },
+  /**
+   * associations between host property and column index
+   * @type {Array}
+   */
+  colPropAssoc: function(){
+    var associations = [];
+    associations[0] = 'healthClass';
+    associations[1] = 'publicHostName';
+    associations[2] = 'ip';
+    associations[3] = 'cpu';
+    associations[4] = 'memoryFormatted';
+    associations[5] = 'loadAvg';
+    associations[6] = 'hostComponents';
+    associations[7] = 'criticalAlertsCount';
+    associations[8] = 'componentsWithStaleConfigsCount';
+    associations[9] = 'componentsInPassiveStateCount';
+    associations[10] = 'selected';
+    return associations;
+  }.property()
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/ff2b111b/ambari-web/app/data/host/categories.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/data/host/categories.js b/ambari-web/app/data/host/categories.js
index 8e8ef13..05f586f 100644
--- a/ambari-web/app/data/host/categories.js
+++ b/ambari-web/app/data/host/categories.js
@@ -20,7 +20,8 @@ module.exports = [
   {
     value: Em.I18n.t('common.all'),
     isHealthStatus: true,
-    healthStatusValue: '',
+    healthStatus: '',
+    healthClass: '',
     isActive: true,
     isVisible: false
   },
@@ -28,32 +29,37 @@ module.exports = [
     value: Em.I18n.t('hosts.host.healthStatusCategory.green'),
     isHealthStatus: true,
     class: App.healthIconClassGreen,
-    healthStatusValue: 'health-status-LIVE'
+    healthStatus: 'HEALTHY',
+    healthClass: 'health-status-LIVE'
   },
   {
     value: Em.I18n.t('hosts.host.healthStatusCategory.red'),
     isHealthStatus: true,
     class: App.healthIconClassRed,
-    healthStatusValue: 'health-status-DEAD-RED'
+    healthStatus: 'UNHEALTHY',
+    healthClass: 'health-status-DEAD-RED'
   },
   {
     value: Em.I18n.t('hosts.host.healthStatusCategory.orange'),
     isHealthStatus: true,
     class: App.healthIconClassOrange,
-    healthStatusValue: 'health-status-DEAD-ORANGE'
+    healthStatus: 'ALERT',
+    healthClass: 'health-status-DEAD-ORANGE'
   },
   {
     value: Em.I18n.t('hosts.host.healthStatusCategory.yellow'),
     isHealthStatus: true,
     class: App.healthIconClassYellow,
-    healthStatusValue: 'health-status-DEAD-YELLOW'
+    healthStatus: 'UNKNOWN',
+    healthClass: 'health-status-DEAD-YELLOW'
   },
   {
     value: Em.I18n.t('hosts.host.alerts.label'),
     hostProperty: 'criticalAlertsCount',
     class: 'icon-exclamation-sign',
     isHealthStatus: false,
-    healthStatusValue: 'health-status-WITH-ALERTS',
+    healthClass: 'health-status-WITH-ALERTS',
+    healthStatus: 'health-status-WITH-ALERTS',
     column: 7,
     type: 'number',
     filterValue: '>0'
@@ -63,17 +69,19 @@ module.exports = [
     hostProperty: 'componentsWithStaleConfigsCount',
     class: 'icon-refresh',
     isHealthStatus: false,
-    healthStatusValue: 'health-status-RESTART',
+    healthClass: 'health-status-RESTART',
+    healthStatus: 'health-status-RESTART',
     column: 8,
     type: 'number',
-    filterValue: '>0'
+    filterValue: 'true'
   },
   {
     value: Em.I18n.t('common.selected'),
     hostProperty: 'selected',
     class: '',
     isHealthStatus: false,
-    healthStatusValue: 'health-status-SELECTED',
+    healthClass: 'health-status-SELECTED',
+    healthStatus: 'health-status-SELECTED',
     selected: true,
     column: 10,
     type: 'boolean',
@@ -85,9 +93,10 @@ module.exports = [
     hostProperty: 'componentsInPassiveStateCount',
     class: 'passive-state icon-medkit',
     isHealthStatus: false,
-    healthStatusValue: 'health-status-PASSIVE_STATE',
+    healthClass: 'health-status-PASSIVE_STATE',
+    healthStatus: 'health-status-PASSIVE_STATE',
     column: 9,
     type: 'number',
-    filterValue: '>0'
+    filterValue: 'ON'
   }
 ];

http://git-wip-us.apache.org/repos/asf/ambari/blob/ff2b111b/ambari-web/app/mappers/hosts_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/hosts_mapper.js b/ambari-web/app/mappers/hosts_mapper.js
index 0f93af5..fe57438 100644
--- a/ambari-web/app/mappers/hosts_mapper.js
+++ b/ambari-web/app/mappers/hosts_mapper.js
@@ -18,11 +18,6 @@
 var App = require('app');
 
 var stringUtils = require('utils/string_utils');
-/**
- * previousResponse contains only mutable properties of host
- * unlike App.cache.Hosts, which contains immutable properties
- */
-var previousResponse = {};
 
 App.hostsMapper = App.QuickDataMapper.create({
 
@@ -31,7 +26,7 @@ App.hostsMapper = App.QuickDataMapper.create({
     id: 'Hosts.host_name',
     host_name: 'Hosts.host_name',
     public_host_name: 'Hosts.public_host_name',
-    cluster_id: 'Hosts.cluster_name',// 1
+    cluster_id: 'cluster_id',// Hosts.cluster_name
     rack: 'Hosts.rack_info',
     host_components_key: 'host_components',
     host_components_type: 'array',
@@ -63,136 +58,34 @@ App.hostsMapper = App.QuickDataMapper.create({
     console.time('App.hostsMapper execution time');
     if (json.items) {
       var hostsWithFullInfo = [];
-      var modifiedHosts = [];
       var hostIds = {};
-      var cacheData = App.cache['Hosts'];
-      var currentHostStatuses = {};
-      var hostsData = {};
-      var isModelLoaded = false;
 
       json.items.forEach(function (item) {
-        var hostName = item.Hosts.host_name;
-        //receive host_components when hosts were added
         item.host_components = item.host_components || [];
         item.host_components.forEach(function (host_component) {
-          host_component.id = host_component.HostRoles.component_name + "_" + hostName;
+          host_component.id = host_component.HostRoles.component_name + "_" + item.Hosts.host_name;
         }, this);
         item.Hosts.disk_info = item.Hosts.disk_info.filter(function(h) {return h.mountpoint!="/boot"});
-        hostIds[hostName] = true;
-        currentHostStatuses[hostName] = item.Hosts.host_status;
+        item.critical_alerts_count = (item.alerts) ? item.alerts.summary.CRITICAL + item.alerts.summary.WARNING : 0;
+        item.cluster_id = App.get('clusterName');
+
+        hostIds[item.Hosts.host_name] = true;
 
-        var hostCache = cacheData[hostName];
-        item.critical_alerts_count = hostCache.critical_alerts_count;
         var parsedItem = this.parseIt(item, this.config);
+        parsedItem.is_requested = true;
 
         hostsWithFullInfo.push(parsedItem);
-        if (hostCache) {
-          if (hostCache.is_modified) {
-            modifiedHosts.push(parsedItem);
-            delete hostCache.is_modified;
-          } else {
-            hostsData[hostName] = this.getDiscrepancies(parsedItem, previousResponse[hostName]);
-          }
-        }
-        previousResponse[hostName] = parsedItem;
       }, this);
 
-      App.cache['previousHostStatuses'] = currentHostStatuses;
       hostsWithFullInfo = hostsWithFullInfo.sortProperty('public_host_name');
 
-      var clientHosts = App.Host.find();
-
-      if (clientHosts) {
-        // hosts were added
-        if (clientHosts.get('length') < hostsWithFullInfo.length) {
-          hostsWithFullInfo.forEach(function (host) {
-            cacheData[host.id] = {
-              ip: host.ip,
-              os_arch: host.os_arch,
-              os_type: host.os_type,
-              public_host_name: host.public_host_name,
-              memory: host.memory,
-              cpu: host.cpu,
-              cpu_physical: host.cpu_physical,
-              host_components: host.host_components
-            };
-          });
-          App.store.loadMany(this.get('model'), hostsWithFullInfo);
-          isModelLoaded = true;
-        } else {
-          //restore properties from cache instead of asking them from server
-          modifiedHosts.forEach(function (host) {
-            var cacheHost = cacheData[host.id];
-            if (cacheHost) {
-              host.ip = cacheHost.ip;
-              host.os_arch = cacheHost.os_arch;
-              host.os_type = cacheHost.os_type;
-              host.public_host_name = cacheHost.public_host_name;
-              host.memory = cacheHost.memory;
-              host.cpu = cacheHost.cpu;
-              host.cpu_physical = cacheHost.cpu_physical;
-              host.host_components = cacheHost.host_components;
-            }
-          });
-          App.store.loadMany(this.get('model'), modifiedHosts);
+      App.Host.find().forEach(function (host) {
+        if (!hostIds[host.get('hostName')]) {
+          host.set('isRequested', false);
         }
-
-        clientHosts.forEach(function (host) {
-          host.set('isRequested', !!hostIds[host.get('hostName')]);
-        }, this);
-
-        // hosts were deleted
-       /* if (clientHosts.get('length') > hostsWithFullInfo.length) {
-          clientHosts.forEach(function (host) {
-            if (host && !hostIds[host.get('hostName')]) {
-              // Delete old ones as new ones will be
-              // loaded by loadMany().
-              this.deleteRecord(host);
-              delete cacheData[host.get('id')];
-            }
-          }, this);
-        }*/
-      }
-      if (!isModelLoaded) {
-        App.Host.find().forEach(function (_host) {
-          var hostData = hostsData[_host.get('id')];
-          if (hostData) {
-            for (var i in hostData) {
-              _host.set(stringUtils.underScoreToCamelCase(i), hostData[i]);
-            }
-          }
-        });
-      }
-    }
-    console.timeEnd('App.hostsMapper execution time');
-    if (!App.router.get('clusterController.dataLoadList.serviceMetrics')) {
-      App.router.get('clusterController').deferServiceMetricsLoad();
-    }
-  },
-  /**
-   * check mutable fields whether they have been changed and if positive
-   * return host object only with properties, that contains new value
-   * @param current
-   * @param previous
-   * @return {*}
-   */
-  getDiscrepancies: function (current, previous) {
-    var result = {};
-    var fields = Em.A(['disk_total', 'disk_free', 'health_status', 'load_one', 'cpu_system', 'cpu_user', 'mem_total', 'mem_free', 'critical_alerts_count', 'passive_state']);
-    if (previous) {
-      fields.forEach(function (field) {
-        if (current[field] != previous[field]) result[field] = current[field];
       });
-      if (JSON.stringify(current.disk_info) !== JSON.stringify(previous.disk_info)) {
-        result.disk_info = current.disk_info;
-      }
-      if (JSON.stringify(current.host_components) !== JSON.stringify(previous.host_components)) {
-        result.host_components = current.host_components;
-      }
-      result.last_heart_beat_time = current.last_heart_beat_time;
-      return result;
+      App.store.loadMany(App.Host, hostsWithFullInfo);
     }
-    return current;
+    console.timeEnd('App.hostsMapper execution time');
   }
-
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/ff2b111b/ambari-web/app/mappers/status_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/status_mapper.js b/ambari-web/app/mappers/status_mapper.js
index cebc32c..0f1e284 100644
--- a/ambari-web/app/mappers/status_mapper.js
+++ b/ambari-web/app/mappers/status_mapper.js
@@ -22,29 +22,20 @@ App.statusMapper = App.QuickDataMapper.create({
   map: function (json) {
     console.time('App.statusMapper execution time');
     if (json.items) {
-      var hostsCache = App.cache['Hosts'];
-      var previousHostStatuses = App.cache['previousHostStatuses'];
       var previousComponentStatuses = App.cache['previousComponentStatuses'];
       var previousComponentPassiveStates = App.cache['previousComponentPassiveStates'];
       var hostComponentRecordsMap = App.cache['hostComponentRecordsMap'];
       var servicesCache = App.cache['services'];
-      var hostStatuses = {};
       var addedHostComponents = [];
       var updatedHostComponents = [];
       var componentServiceMap = App.QuickDataMapper.componentServiceMap();
       var currentComponentStatuses = {};
       var currentComponentPassiveStates = {};
-      var currentHostStatuses = {};
       var hostComponentsOnService = {};
 
       json.items.forEach(function (host) {
         var hostName = host.Hosts.host_name;
-        //update hosts, which have status changed
-        if (previousHostStatuses[hostName] !== host.Hosts.host_status) {
-          hostStatuses[hostName] = host.Hosts.host_status;
-        }
-        //preserve all hosts' status
-        currentHostStatuses[hostName] = host.Hosts.host_status;
+
         var hostComponentsOnHost = [];
         host.host_components.forEach(function (host_component) {
           host_component.id = host_component.HostRoles.component_name + "_" + hostName;
@@ -70,8 +61,6 @@ App.statusMapper = App.QuickDataMapper.create({
               host_id: hostName,
               service_id: service
             });
-            //update host-components only on adding due to Ember Data features
-            if (hostsCache[hostName]) hostsCache[hostName].is_modified = true;
           }
           currentComponentStatuses[host_component.id] = host_component.HostRoles.state;
           currentComponentPassiveStates[host_component.id] = host_component.HostRoles.maintenance_state;
@@ -85,20 +74,7 @@ App.statusMapper = App.QuickDataMapper.create({
           }
           hostComponentsOnService[service].host_components.push(host_component.id);
         }, this);
-        /**
-         * updating relation between Host and his host-components
-         */
-        if (hostsCache[hostName]) {
-          hostsCache[hostName].host_components = hostComponentsOnHost;
-        } else {
-          hostsCache[hostName] = {};
-        }
-        //check whether Nagios installed and started
-        if (host.alerts) {
-          hostsCache[hostName].critical_alerts_count = host.alerts.summary.CRITICAL + host.alerts.summary.WARNING;
-        } else {
-          hostsCache[hostName].critical_alerts_count = 0;
-        }
+
       }, this);
 
 
@@ -114,18 +90,6 @@ App.statusMapper = App.QuickDataMapper.create({
         }
       }, this);
 
-      var hostRecords = App.Host.find();
-      hostRecords.forEach(function (host) {
-        var status = hostStatuses[host.get('id')];
-        var hostCache = hostsCache[host.get('id')];
-        if (status) {
-          host.set('healthStatus', status);
-        }
-        if (hostCache) {
-          host.set('criticalAlertsCount', hostCache.critical_alerts_count);
-        }
-      });
-
       if (addedHostComponents.length) {
         App.store.loadMany(this.get('model'), addedHostComponents);
         App.HostComponent.find().forEach(function(hostComponent){
@@ -142,15 +106,11 @@ App.statusMapper = App.QuickDataMapper.create({
         }
       }, this);
 
-      App.cache['previousHostStatuses'] = currentHostStatuses;
       App.cache['previousComponentStatuses'] = currentComponentStatuses;
       App.cache['previousComponentPassiveStates'] = currentComponentPassiveStates;
       App.cache['hostComponentsOnService'] = hostComponentsOnService;
 
     }
     console.timeEnd('App.statusMapper execution time');
-    if (!App.router.get('clusterController.isLoaded')) {
-      App.hostsMapper.map(json);
-    }
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/ff2b111b/ambari-web/app/mixins/common/tableServerProvider.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/tableServerProvider.js b/ambari-web/app/mixins/common/tableServerProvider.js
index 8c8391b..f1cade7 100644
--- a/ambari-web/app/mixins/common/tableServerProvider.js
+++ b/ambari-web/app/mixins/common/tableServerProvider.js
@@ -22,20 +22,21 @@ var App = require('app');
 App.TableServerProvider = Em.Mixin.create({
   tableName: '',
   updaterBinding: 'App.router.updateController',
-  /**
-   * contains association between property of table and parameter in query
-   */
-  paramAssociations: {},
-  /**
-   * properties which trigger <code>refresh()</code> when they are changed
-   */
-  refreshTriggers: [],
-  refreshCompleted: true,
+  filteringComplete: true,
+  filterConditions: [],
   /**
    * total number of entities in table
    */
   totalCount: 0,
 
+  filteredContent: function () {
+    return this.get('content');
+  }.property('content'),
+
+  pageContent: function () {
+    return this.get('filteredContent');
+  }.property('filteredContent'),
+
   /**
    * Return pagination information displayed on the page
    * @type {String}
@@ -44,45 +45,66 @@ App.TableServerProvider = Em.Mixin.create({
     return this.t('tableView.filters.paginationInfo').format(this.get('startIndex'), this.get('endIndex'), this.get('totalCount'));
   }.property('totalCount', 'endIndex'),
 
-  /**
-   * add observers to trigger properties
-   */
-  initTriggers: function () {
-    this.get('refreshTriggers').forEach(function (trigger) {
-      this.addObserver(trigger, this, 'refresh');
-    }, this);
-  },
-
-  /**
-   * set filter properties of table to query parameters
-   * @param newParams
-   */
-  setParams: function (newParams) {
-    this.get('updater.queryParams').set(this.get('tableName'), newParams);
-  },
 
   /**
    * request latest data filtered by new parameters
    * called when trigger property(<code>refreshTriggers</code>) is changed
    */
   refresh: function () {
-    var params = [];
-    var paramAssociations = this.get('paramAssociations');
     var self = this;
 
-    for (var property in paramAssociations) {
-      if (!Em.isNone(this.get(property))) {
-        params.push({
-          key: paramAssociations[property],
-          value: this.get(property)
-        });
-      }
-    }
-    this.setParams(params);
-    this.set('refreshCompleted', false);
+    if (!this.get('filteringComplete')) return false;
+
+    this.set('filteringComplete', false);
     this.get('updater')[this.get('updater.tableUpdaterMap')[this.get('tableName')]](function () {
-      self.set('refreshCompleted', true);
+      self.set('filteringComplete', true);
       self.propertyDidChange('pageContent');
     });
+    return true;
+  },
+  /**
+   * reset filters value by column to which filter belongs
+   * @param columns {Array}
+   */
+  resetFilterByColumns: function (columns) {
+    var filterConditions = this.get('filterConditions');
+
+    columns.forEach(function (iColumn) {
+      var filterCondition = filterConditions.findProperty('iColumn', iColumn);
+
+      if (filterCondition) {
+        filterCondition.value = '';
+      }
+    });
+    this.saveFilterConditions();
+  },
+  /**
+   * Apply each filter to each row
+   * @param iColumn {Number}
+   * @param value {String}
+   * @param type {String}
+   */
+  updateFilter: function (iColumn, value, type) {
+    var filterCondition = this.get('filterConditions').findProperty('iColumn', iColumn);
+
+    if (filterCondition) {
+      filterCondition.value = value;
+    } else {
+      filterCondition = {
+        iColumn: iColumn,
+        value: value,
+        type: type
+      };
+      this.get('filterConditions').push(filterCondition);
+    }
+    this.saveFilterConditions();
+    this.refresh();
+  },
+
+  /**
+   * save filter conditions to local storage
+   */
+  saveFilterConditions: function () {
+    App.db.setFilterConditions(this.get('controller.name'), this.get('filterConditions'));
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/ff2b111b/ambari-web/app/templates/main/host.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/host.hbs b/ambari-web/app/templates/main/host.hbs
index b5deaa0..35d862f 100644
--- a/ambari-web/app/templates/main/host.hbs
+++ b/ambari-web/app/templates/main/host.hbs
@@ -43,7 +43,7 @@
               {{#if category.isVisible}}
                 <li {{bindAttr class=":category-item category.itemClass"}}>
                   <a {{action selectCategory category target="view"}} href="#">
-                      <span {{bindAttr class="category.isHealthStatus:health-status category.healthStatusValue category.class"}}></span>
+                      <span {{bindAttr class="category.isHealthStatus:health-status category.healthClass category.class"}}></span>
                     {{category.label}}
                   </a>
                </li>

http://git-wip-us.apache.org/repos/asf/ambari/blob/ff2b111b/ambari-web/app/views/common/sort_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/sort_view.js b/ambari-web/app/views/common/sort_view.js
index 2110a98..53b529a 100644
--- a/ambari-web/app/views/common/sort_view.js
+++ b/ambari-web/app/views/common/sort_view.js
@@ -31,8 +31,8 @@ var wrapperView = Em.View.extend({
 
   classNames: ['sort-wrapper'],
 
-  willInsertElement:function () {
-    if(this.get('parentView.tableFilteringComplete')){
+  willInsertElement: function () {
+    if (this.get('parentView.tableFilteringComplete')) {
       this.get('parentView').set('filteringComplete', true);
     }
   },
@@ -41,20 +41,20 @@ var wrapperView = Em.View.extend({
    * Load sort statuses from local storage
    * Works only after finish filtering in the parent View
    */
-  loadSortStatuses: function() {
+  loadSortStatuses: function () {
     var statuses = App.db.getSortingStatuses(this.get('controller.name'));
     if (!this.get('parentView.filteringComplete')) return;
     if (statuses) {
       var childViews = this.get('childViews');
       var self = this;
-      statuses.forEach(function(st) {
+      statuses.forEach(function (st) {
         if (st.status != 'sorting') {
           var sortOrder = false;
-          if(st.status == 'sorting_desc') {
+          if (st.status == 'sorting_desc') {
             sortOrder = true;
           }
           self.sort(childViews.findProperty('name', st.name), sortOrder);
-          childViews.findProperty('name', st.name).set('status', (sortOrder)?'sorting_desc':'sorting_asc');
+          childViews.findProperty('name', st.name).set('status', (sortOrder) ? 'sorting_desc' : 'sorting_asc');
           self.get('controller').set('sortingColumn', childViews.findProperty('name', st.name));
         }
         else {
@@ -69,32 +69,38 @@ var wrapperView = Em.View.extend({
    * Save sort statuses to local storage
    * Works only after finish filtering in the parent View
    */
-  saveSortStatuses: function() {
+  saveSortStatuses: function () {
     if (!this.get('parentView.filteringComplete')) return;
+
     var statuses = [];
-    this.get('childViews').forEach(function(childView) {
+    this.get('childViews').forEach(function (childView) {
       statuses.push({
         name: childView.get('name'),
         status: childView.get('status')
       });
     });
     App.db.setSortingStatuses(this.get('controller.name'), statuses);
-  }.observes('childViews.@each.status'),
+  },
 
   /**
    * sort content by property
-   * @param property
-   * @param order true - DESC, false - ASC
+   * @param property {object}
+   * @param order {Boolean} true - DESC, false - ASC
+   * @param returnSorted {Boolean}
    */
-  sort: function(property, order, returnSorted){
-    returnSorted = returnSorted ? true : false;
+  sort: function (property, order, returnSorted) {
     var content = this.get('content').toArray();
     var sortFunc = this.getSortFunc(property, order);
+    var status = order ? 'sorting_desc' : 'sorting_asc';
+
     this.resetSort();
+    this.get('childViews').findProperty('name', property.get('name')).set('status', status);
+    this.saveSortStatuses(property, order);
     content.sort(sortFunc);
-    if(returnSorted){
+
+    if (!!returnSorted) {
       return content;
-    }else{
+    } else {
       this.set('content', content);
     }
   },
@@ -118,7 +124,7 @@ var wrapperView = Em.View.extend({
   /**
    * reset all sorts fields
    */
-  resetSort: function(){
+  resetSort: function () {
     this.get('childViews').setEach('status', 'sorting');
   },
   /**
@@ -127,9 +133,9 @@ var wrapperView = Em.View.extend({
    * @param order
    * @return {*}
    */
-  getSortFunc: function(property, order){
+  getSortFunc: function (property, order) {
     var func;
-    switch (property.get('type')){
+    switch (property.get('type')) {
       case 'ip':
         func = function (a, b) {
           var a = misc.ipToInt(a.get(property.get('name')));
@@ -153,8 +159,8 @@ var wrapperView = Em.View.extend({
         };
         break;
       default:
-        func = function(a,b){
-          if(order){
+        func = function (a, b) {
+          if (order) {
             if (a.get(property.get('name')) > b.get(property.get('name')))
               return -1;
             if (a.get(property.get('name')) < b.get(property.get('name')))
@@ -172,6 +178,73 @@ var wrapperView = Em.View.extend({
     return func;
   }
 });
+
+/**
+ * view that carry on sorting on server-side via <code>refresh()</code> in parentView
+ * @type {*}
+ */
+var serverWrapperView = Em.View.extend({
+  tagName: 'tr',
+
+  classNames: ['sort-wrapper'],
+
+  willInsertElement: function () {
+    this.loadSortStatuses();
+  },
+
+  loadSortStatuses: function () {
+    var statuses = App.db.getSortingStatuses(this.get('controller.name'));
+
+    if (statuses) {
+      var childViews = this.get('childViews');
+      var self = this;
+      statuses.forEach(function (st) {
+        if (st.status !== 'sorting') {
+          self.sort(childViews.findProperty('name', st.name), (st.status === 'sorting_desc'));
+          self.get('controller').set('sortingColumn', childViews.findProperty('name', st.name));
+        } else {
+          childViews.findProperty('name', st.name).set('status', st.status);
+        }
+      });
+    }
+  },
+
+  /**
+   * Save sort statuses to local storage
+   * Works only after finish filtering in the parent View
+   */
+  saveSortStatuses: function () {
+    var statuses = [];
+    this.get('childViews').forEach(function (childView) {
+      statuses.push({
+        name: childView.get('name'),
+        status: childView.get('status')
+      });
+    });
+    App.db.setSortingStatuses(this.get('controller.name'), statuses);
+  },
+
+  /**
+   * sort content by property
+   * @param property {object}
+   * @param order {Boolean} true - DESC, false - ASC
+   */
+  sort: function (property, order) {
+    var status = order ? 'sorting_desc' : 'sorting_asc';
+
+    this.resetSort();
+    this.get('childViews').findProperty('name', property.get('name')).set('status', status);
+    this.saveSortStatuses();
+    this.get('parentView').refresh();
+  },
+
+  /**
+   * reset all sorts fields
+   */
+  resetSort: function () {
+    this.get('childViews').setEach('status', 'sorting');
+  }
+});
 /**
  * particular view that contain sort field properties:
  * name - name of property in content table
@@ -180,7 +253,7 @@ var wrapperView = Em.View.extend({
  * @type {*}
  */
 var fieldView = Em.View.extend({
-  template:Em.Handlebars.compile('<span {{bindAttr class="view.status :column-name"}}>{{view.displayName}}</span>'),
+  template: Em.Handlebars.compile('<span {{bindAttr class="view.status :column-name"}}>{{view.displayName}}</span>'),
   classNameBindings: ['viewNameClass'],
   tagName: 'th',
   name: null,
@@ -195,15 +268,8 @@ var fieldView = Em.View.extend({
    * callback that run sorting and define order of sorting
    * @param event
    */
-  click: function(event){
-    if(this.get('status') === 'sorting_desc'){
-      this.get('parentView').sort(this, false);
-      this.set('status', 'sorting_asc');
-    }
-    else {
-      this.get('parentView').sort(this, true);
-      this.set('status', 'sorting_desc');
-    }
+  click: function (event) {
+    this.get('parentView').sort(this, (this.get('status') !== 'sorting_desc'));
     this.get('controller').set('sortingColumn', this);
   }
 });
@@ -213,6 +279,7 @@ var fieldView = Em.View.extend({
  * @type {Object}
  */
 module.exports = {
+  serverWrapperView: serverWrapperView,
   wrapperView: wrapperView,
   fieldView: fieldView
 };
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/ff2b111b/ambari-web/app/views/common/table_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/table_view.js b/ambari-web/app/views/common/table_view.js
index e5a455c..5213795 100644
--- a/ambari-web/app/views/common/table_view.js
+++ b/ambari-web/app/views/common/table_view.js
@@ -78,10 +78,6 @@ App.TableView = Em.View.extend(App.UserPref, {
     if (!this.get('displayLength')) {
       if (App.db.getDisplayLength(name)) {
         this.set('displayLength', App.db.getDisplayLength(name));
-      } else {
-        self.dataLoading().done(function (initValue) {
-          self.set('displayLength', initValue);
-        });
       }
     }
 
@@ -107,61 +103,6 @@ App.TableView = Em.View.extend(App.UserPref, {
   },
 
   /**
-   * Load user preference value on hosts page from server
-   */
-  dataLoading: function() {
-    var dfd = $.Deferred();
-    var self = this;
-    this.getUserPref(this.displayLengthKey()).done(function () {
-      var curLength = self.get('displayLengthOnLoad');
-      self.set('displayLengthOnLoad', null);
-      dfd.resolve(curLength);
-    });
-    return dfd.promise();
-  },
-
-  /**
-   * Persist-key of current table displayLength property
-   * @param {String} loginName current user login name
-   * @returns {String}
-   */
-  displayLengthKey: function (loginName) {
-    if (App.get('testMode')) {
-      return 'pagination_displayLength';
-    }
-    loginName = loginName ? loginName : App.router.get('loginName');
-    return this.get('controller.name') + '-pagination-displayLength-' + loginName;
-  },
-
-  /**
-   * Set received from server value to <code>displayLengthOnLoad</code>
-   * @param {Number} response
-   * @param {Object} request
-   * @param {Object} data
-   * @returns {*}
-   */
-  getUserPrefSuccessCallback: function (response, request, data) {
-    console.log('Got DisplayLength value from server with key ' + data.key + '. Value is: ' + response);
-    this.set('displayLengthOnLoad', response);
-    return response;
-  },
-
-  /**
-   * Set default value to <code>displayLengthOnLoad</code> (and send it on server) if value wasn't found on server
-   * @returns {Number}
-   */
-  getUserPrefErrorCallback: function () {
-    // this user is first time login
-    console.log('Persist did NOT find the key');
-    var displayLengthDefault = this.get('defaultDisplayLength');
-    this.set('displayLengthOnLoad', displayLengthDefault);
-    if (App.get('isAdmin')) {
-      this.postUserPref(this.displayLengthKey(), displayLengthDefault);
-    }
-    return displayLengthDefault;
-  },
-
-  /**
    * Do pagination after filtering and sorting
    * Don't call this method! It's already used where it's need
    */

http://git-wip-us.apache.org/repos/asf/ambari/blob/ff2b111b/ambari-web/app/views/main/host.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host.js b/ambari-web/app/views/main/host.js
index 5970212..50e7684 100644
--- a/ambari-web/app/views/main/host.js
+++ b/ambari-web/app/views/main/host.js
@@ -23,20 +23,14 @@ var date = require('utils/date');
 
 App.MainHostView = App.TableView.extend(App.TableServerProvider, {
   templateName:require('templates/main/host'),
-  /**
-   * List of hosts in cluster
-   * @type {Array}
-   */
-  content:function () {
-    return this.get('controller.content');
-  }.property('controller.content.length'),
 
   tableName: 'Hosts',
-  paramAssociations: {
-    'serverStartIndex': 'from',
-    'displayLength': 'page_size'
-  },
-  refreshTriggers: ['serverStartIndex', 'displayLength'],
+
+  /**
+   * Select/deselect all visible hosts flag
+   * @property {bool}
+   */
+  selectAllHosts: false,
 
   /**
    * flag responsible for updating status counters of hosts
@@ -44,15 +38,20 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
   isCountersUpdating: false,
 
   /**
-   * startIndex as query parameter have first index - 0
+   * List of hosts in cluster
+   * @type {Array}
    */
-  serverStartIndex: function() {
-    return this.get('startIndex') - 1;
-  }.property('startIndex'),
-
-  pageContent: function () {
-    return this.get('filteredContent').filterProperty('isRequested');
-  }.property('filteredContent.length'),
+  content:function () {
+    return this.get('controller.content');
+  }.property('controller.content.length'),
+  /**
+   * return filtered number of all content number information displayed on the page footer bar
+   * @returns {String}
+   */
+  filteredContentInfo: function () {
+    //TODO API should return number of filtered hosts
+    return this.t('hosts.filters.filteredHostsInfo').format(this.get('filteredContent.length'), this.get('content').get('length'));
+  }.property('content.length', 'filteredContent.length'),
 
   clearFiltersObs: function() {
     var self = this;
@@ -63,9 +62,56 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
       }
     });
   },
+  /**
+   * Restore filter properties in view
+   */
+  willInsertElement: function () {
+    this.set('displayLength', this.get('controller.viewProperties').findProperty('key', 'displayLength').getValue(this.get('controller')));
+    var filterConditions = App.db.getFilterConditions(this.get('controller.name'));
+    if (filterConditions) {
+
+      var childViews = this.get('childViews');
+
+      filterConditions.forEach(function(condition) {
+        var view = childViews.findProperty('column', condition.iColumn);
+        if (view) {
+          view.set('value', condition.value);
+          Em.run.next(function() {
+            view.showClearFilter();
+          });
+        }
+      });
+    } else {
+      this.clearFilters();
+    }
+  },
+
+  /**
+   * get query parameters computed in controller
+   * @return {Array}
+   */
+  getQueryParameters: function () {
+    return this.get('controller').getQueryParameters();
+  },
+  /**
+   * stub for filter function in TableView
+   */
+  filter: function () {
+    //Since filtering moved to server side, function is empty
+  },
+  /**
+   * save display length to local DB and server
+   */
+  saveDisplayLength: function() {
+    App.db.setDisplayLength(this.get('controller.name'), this.get('displayLength'));
+    if (!App.testMode) {
+      if (App.get('isAdmin')) {
+        this.get('controller').postUserPref(this.get('controller').displayLengthKey(), this.get('displayLength'));
+      }
+    }
+  },
 
   didInsertElement: function() {
-    this.initTriggers();
     this.addObserver('controller.clearFilters', this, this.clearFiltersObs);
     this.clearFiltersObs();
     this.addObserver('selectAllHosts', this, this.toggleAllHosts);
@@ -73,23 +119,17 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
     this.updateStatusCounters();
   },
 
-  willDestroyElement: function() {
-    this.set('isCountersUpdating', false);
-  },
-
   /**
-   * return filtered number of all content number information displayed on the page footer bar
-   * @returns {String}
+   * synchronize properties of view with controller to generate query parameters
    */
-  filteredContentInfo: function () {
-    return this.t('hosts.filters.filteredHostsInfo').format(this.get('filteredContent.length'), this.get('content').get('length'));
-  }.property('content.length', 'filteredContent.length'),
+  updateViewProperty: function (context, property) {
+    this.get('controller.viewProperties').findProperty('key', property).set('viewValue', this.get(property));
+    this.refresh();
+  }.observes('displayLength', 'startIndex'),
 
-  /**
-   * Select/deselect all visible hosts flag
-   * @property {bool}
-   */
-  selectAllHosts: false,
+  willDestroyElement: function() {
+    this.set('isCountersUpdating', false);
+  },
 
   /**
    * Set <code>selected</code> property for each App.Host
@@ -204,7 +244,7 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
     });
   },
 
-  sortView: sort.wrapperView,
+  sortView: sort.serverWrapperView,
   nameSort: sort.fieldView.extend({
     column: 1,
     name:'publicHostName',
@@ -338,11 +378,11 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
    */
   updateStatusCountersSuccessCallback: function (data) {
     var hostsCountMap = {
-      'health-status-LIVE': data.Clusters.health_report['Host/host_status/HEALTHY'],
-      'health-status-DEAD-RED': data.Clusters.health_report['Host/host_status/UNHEALTHY'],
-      'health-status-DEAD-ORANGE': data.Clusters.health_report['Host/host_status/ALERT'],
-      'health-status-DEAD-YELLOW': data.Clusters.health_report['Host/host_status/UNKNOWN'],
-      'health-status-WITH-ALERTS': data.alerts.summary.CRITICAL + data.alerts.summary.WARNING,
+      'HEALTHY': data.Clusters.health_report['Host/host_status/HEALTHY'],
+      'UNHEALTHY': data.Clusters.health_report['Host/host_status/UNHEALTHY'],
+      'ALERT': data.Clusters.health_report['Host/host_status/ALERT'],
+      'UNKNOWN': data.Clusters.health_report['Host/host_status/UNKNOWN'],
+      'health-status-WITH-ALERTS': (data.alerts) ? data.alerts.summary.CRITICAL + data.alerts.summary.WARNING : 0,
       'health-status-RESTART': data.Clusters.health_report['Host/stale_config'],
       'health-status-PASSIVE_STATE': data.Clusters.health_report['Host/maintenance_state'],
       'TOTAL': data.Clusters.total_hosts
@@ -364,7 +404,7 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
    */
   updateHostsCount: function(hostsCountMap) {
     this.get('categories').forEach(function(category) {
-      var hostsCount = (category.get('healthStatusValue').trim() === "") ? hostsCountMap['TOTAL'] : hostsCountMap[category.get('healthStatusValue')];
+      var hostsCount = (category.get('healthStatus').trim() === "") ? hostsCountMap['TOTAL'] : hostsCountMap[category.get('healthStatus')];
 
       if (!Em.isNone(hostsCount)) {
         category.set('hostsCount', hostsCount);
@@ -500,16 +540,16 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
     /**
      * switch active category label
      */
-    onCategoryChange: function() {
+    onCategoryChange: function () {
       this.get('categories').setEach('isActive', false);
-      var selected = this.get('categories').findProperty('healthStatusValue', this.get('value'));
+      var selected = this.get('categories').findProperty('healthStatus', this.get('value'));
       selected.set('isActive', true);
-      this.set('class', selected.get('class') + ' ' + this.get('value'));
+      this.set('class', selected.get('class') + ' ' + selected.get('healthClass'));
     }.observes('value'),
 
-    showClearFilter: function(){
+    showClearFilter: function () {
       var mockEvent = {
-        context: this.get('categories').findProperty('healthStatusValue', this.get('value'))
+        context: this.get('categories').findProperty('healthStatus', this.get('value'))
       };
       this.selectCategory(mockEvent);
     },
@@ -519,24 +559,13 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
      */
     selectCategory: function(event){
       var category = event.context;
-      var self = this;
-      this.set('value', category.get('healthStatusValue'));
+
+      this.set('value', category.get('healthStatus'));
+      this.get('parentView').resetFilterByColumns([0, 7, 8, 9]);
       if (category.get('isHealthStatus')) {
-        this.get('parentView').updateFilter(0, category.get('healthStatusValue'), 'string');
-        this.get('categories').filterProperty('isHealthStatus', false).forEach(function(c) {
-          self.get('parentView').updateFilter(c.get('column'), '', c.get('type'));
-        });
-      }
-      else {
-        this.get('parentView').updateFilter(0, '', 'string');
-        this.get('categories').filterProperty('isHealthStatus', false).forEach(function(c) {
-          if (c.get('column') === category.get('column')) {
-            self.get('parentView').updateFilter(category.get('column'), category.get('filterValue'), category.get('type'));
-          }
-          else {
-            self.get('parentView').updateFilter(c.get('column'), '', c.get('type'));
-          }
-        });
+        this.get('parentView').updateFilter(0, category.get('healthStatus'), 'string');
+      } else {
+        this.get('parentView').updateFilter(category.get('column'), category.get('filterValue'), category.get('type'));
       }
     },
     clearFilter: function() {
@@ -556,7 +585,7 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
     classNames: ['noDisplay'],
     showClearFilter: function(){
       var mockEvent = {
-        context: this.get('parentView.categories').findProperty('healthStatusValue', 'health-status-WITH-ALERTS')
+        context: this.get('parentView.categories').findProperty('healthStatus', 'health-status-WITH-ALERTS')
       };
       if(this.get('value')) {
         this.get('parentView.childViews').findProperty('column', 0).selectCategory(mockEvent);
@@ -573,7 +602,7 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
     classNames: ['noDisplay'],
     showClearFilter: function(){
       var mockEvent = {
-        context: this.get('parentView.categories').findProperty('healthStatusValue', 'health-status-RESTART')
+        context: this.get('parentView.categories').findProperty('healthStatus', 'health-status-RESTART')
       };
       if(this.get('value')) {
         this.get('parentView.childViews').findProperty('column', 0).selectCategory(mockEvent);
@@ -590,7 +619,7 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
     classNames: ['noDisplay'],
     showClearFilter: function(){
       var mockEvent = {
-        context: this.get('parentView.categories').findProperty('healthStatusValue', 'health-status-PASSIVE_STATE')
+        context: this.get('parentView.categories').findProperty('healthStatus', 'health-status-PASSIVE_STATE')
       };
       if(this.get('value')) {
         this.get('parentView.childViews').findProperty('column', 0).selectCategory(mockEvent);
@@ -607,7 +636,7 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
     class: ['noDisplay'],
     showClearFilter: function(){
       var mockEvent = {
-        context: this.get('parentView.categories').findProperty('healthStatusValue', 'health-status-SELECTED')
+        context: this.get('parentView.categories').findProperty('healthStatus', 'health-status-SELECTED')
       };
       if(this.get('value')) {
         this.get('parentView.childViews').findProperty('column', 0).selectCategory(mockEvent);
@@ -800,19 +829,7 @@ App.MainHostView = App.TableView.extend(App.TableServerProvider, {
    * associations between host property and column index
    * @type {Array}
    */
-  colPropAssoc: function(){
-    var associations = [];
-    associations[0] = 'healthClass';
-    associations[1] = 'publicHostName';
-    associations[2] = 'ip';
-    associations[3] = 'cpu';
-    associations[4] = 'memoryFormatted';
-    associations[5] = 'loadAvg';
-    associations[6] = 'hostComponents';
-    associations[7] = 'criticalAlertsCount';
-    associations[8] = 'componentsWithStaleConfigsCount';
-    associations[9] = 'componentsInPassiveStateCount';
-    associations[10] = 'selected';
-    return associations;
-  }.property()
+  colPropAssoc: function () {
+    return this.get('controller.colPropAssoc');
+  }.property('controller.colPropAssoc')
 });