You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by on...@apache.org on 2014/02/18 12:52:53 UTC

git commit: AMBARI-4707. Refactor host components view. (onechiporenko)

Repository: ambari
Updated Branches:
  refs/heads/trunk 65249796f -> 746e68fc6


AMBARI-4707. Refactor host components view. (onechiporenko)


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

Branch: refs/heads/trunk
Commit: 746e68fc6ff6d743f0a069901dcb9c90fe0cda48
Parents: 6524979
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Tue Feb 18 13:50:05 2014 +0200
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Tue Feb 18 13:50:05 2014 +0200

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |   1 +
 .../main/host/details/host_component.hbs        |  99 +---
 ambari-web/app/templates/main/host/summary.hbs  |   2 +-
 ambari-web/app/utils/ajax.js                    |  22 +-
 ambari-web/app/views.js                         |   4 +
 .../main/host/details/host_component_view.js    | 472 +------------------
 .../host_component_views/datanode_view.js       | 127 +++++
 .../host_component_views/decommissionable.js    | 253 ++++++++++
 .../host_component_views/nodemanager_view.js    |  71 +++
 .../host_component_views/regionserver_view.js   |  52 ++
 .../host_component_views/tasktracker_view.js    |  74 +++
 ambari-web/app/views/main/host/summary.js       |  21 +
 .../host/details/host_component_view_test.js    | 138 +++++-
 .../decommissionable_test.js                    | 201 ++++++++
 14 files changed, 975 insertions(+), 562 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index fd7cb29..4bf8c78 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -100,6 +100,7 @@ require('test/views/main/dashboard/widgets/pie_chart_widget_test');
 require('test/views/main/dashboard/widgets/namenode_cpu_test');
 require('test/views/main/host/summary_test');
 require('test/views/main/host/details/host_component_view_test');
+require('test/views/main/host/details/host_component_views/decommissionable_test');
 require('test/views/common/configs/services_config_test');
 require('test/views/wizard/step9_view_test');
 require('test/models/host_test');

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/app/templates/main/host/details/host_component.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/host/details/host_component.hbs b/ambari-web/app/templates/main/host/details/host_component.hbs
index ee29b88..10c772a 100644
--- a/ambari-web/app/templates/main/host/details/host_component.hbs
+++ b/ambari-web/app/templates/main/host/details/host_component.hbs
@@ -32,7 +32,7 @@
     {{component.displayName}}
   {{/if}}
   &nbsp;/&nbsp;
-  <a href="#" {{action routeToService component.service target="controller"  }}>{{component.service.displayName}}</a>
+  <a href="#" {{action routeToService component.service target="controller"}}>{{component.service.displayName}}</a>
   &nbsp;
   {{#if component.staleConfigs}}
     <i class="text-warning icon-refresh"></i>
@@ -46,69 +46,19 @@
         <span class="caret pull-right"></span>
       </a>
       <ul class="dropdown-menu">
-        {{#if view.isDataNode}}
-          {{#if view.isDataNodeDecommissionAvailable}}
-            <li {{bindAttr class="view.noActionAvailable"}}>
-              <a href="javascript:void(null)" data-toggle="modal" {{action "decommission" view.content target="controller"}}>
-                {{t common.decommission}}
-              </a>
-            </li>
-          {{/if}}
-          {{#if view.isDataNodeRecommissionAvailable}}
-            <li {{bindAttr class="view.noActionAvailable"}}>
-              <a href="javascript:void(null)" data-toggle="modal" {{action "recommission" view.content target="controller"}}>
-                {{t common.recommission}}
-              </a>
-            </li>
-          {{/if}}
-        {{/if}}
-        {{#if view.isNodeManager}}
-          {{#if view.isNodeManagerDecommissionAvailable}}
-            <li {{bindAttr class="view.noActionAvailable"}}>
-              <a href="javascript:void(null)" data-toggle="modal" {{action "decommission" view.content target="controller"}}>
-                {{t common.decommission}}
-              </a>
-            </li>
-          {{/if}}
-          {{#if view.isNodeManagerRecommissionAvailable}}
-            <li {{bindAttr class="view.noActionAvailable"}}>
-              <a href="javascript:void(null)" data-toggle="modal" {{action "recommission" view.content target="controller"}}>
-                {{t common.recommission}}
-              </a>
-            </li>
-          {{/if}}
-        {{/if}}
-        {{#if view.isTaskTracker}}
-          {{#if view.isTaskTrackerDecommissionAvailable}}
-            <li {{bindAttr class="view.noActionAvailable"}}>
-              <a href="javascript:void(null)" data-toggle="modal" {{action "decommission" view.content target="controller"}}>
-                {{t common.decommission}}
-              </a>
-            </li>
-          {{/if}}
-          {{#if view.isTaskTrackerRecommissionAvailable}}
-            <li {{bindAttr class="view.noActionAvailable"}}>
-              <a href="javascript:void(null)" data-toggle="modal" {{action "recommission" view.content target="controller"}}>
-                {{t common.recommission}}
-              </a>
-            </li>
-          {{/if}}
+        {{#if view.isComponentDecommissionAvailable}}
+          <li {{bindAttr class="view.noActionAvailable"}}>
+            <a href="javascript:void(null)" data-toggle="modal" {{action "decommission" view.content target="controller"}}>
+              {{t common.decommission}}
+            </a>
+          </li>
         {{/if}}
-        {{#if view.isRegionServer}}
-          {{#if view.isRegionServerDecommissionAvailable}}
-            <li {{bindAttr class="view.noActionAvailable"}}>
-              <a href="javascript:void(null)" data-toggle="modal" {{action "decommission" view.content target="controller"}}>
-                {{t common.decommission}}
-              </a>
-            </li>
-          {{/if}}
-          {{#if view.isRegionServerRecommissionAvailable}}
-            <li {{bindAttr class="view.noActionAvailable"}}>
-              <a href="javascript:void(null)" data-toggle="modal" {{action "recommission" view.content target="controller"}}>
-                {{t common.recommission}}
-              </a>
-            </li>
-          {{/if}}
+        {{#if view.isComponentRecommissionAvailable}}
+          <li {{bindAttr class="view.noActionAvailable"}}>
+            <a href="javascript:void(null)" data-toggle="modal" {{action "recommission" view.content target="controller"}}>
+              {{t common.recommission}}
+            </a>
+          </li>
         {{/if}}
         {{#if view.isDeletableComponent}}
           <li {{bindAttr class="view.isDeleteComponentDisabled:disabled"}}>
@@ -126,56 +76,49 @@
         {{/if}}
         {{#unless view.isInstalling}}
           {{#if view.isStart}}
-            <li {{bindAttr class=" view.isDecommissioning:hidden view.noActionAvailable"}}>
-              <a href="javascript:void(null)"
-                 data-toggle="modal" {{action "stopComponent" view.content target="controller"}}>
+            <li {{bindAttr class="view.isComponentDecommissioning:hidden view.noActionAvailable"}}>
+              <a href="javascript:void(null)" data-toggle="modal" {{action "stopComponent" view.content target="controller"}}>
                 {{t common.stop}}
               </a>
             </li>
           {{/if}}
           {{#unless view.isStart}}
             <li {{bindAttr class="view.isUpgradeFailed:hidden view.isInstallFailed:hidden view.isDecommissioning:hidden view.noActionAvailable"}}>
-              <a href="javascript:void(null)"
-                 data-toggle="modal" {{action "startComponent" view.content target="controller"}}>
+              <a href="javascript:void(null)" data-toggle="modal" {{action "startComponent" view.content target="controller"}}>
                 {{t common.start}}
               </a>
             </li>
           {{/unless}}
           {{#if view.isUpgradeFailed}}
             <li {{bindAttr class="view.noActionAvailable"}}>
-              <a href="javascript:void(null)"
-                 data-toggle="modal" {{action "upgradeComponent" view.content target="controller"}}>
+              <a href="javascript:void(null)" data-toggle="modal" {{action "upgradeComponent" view.content target="controller"}}>
                 {{t common.reUpgrade}}
               </a>
             </li>
           {{/if}}
           {{#if view.isInstallFailed}}
             <li {{bindAttr class="view.noActionAvailable"}}>
-              <a href="javascript:void(null)"
-                 data-toggle="modal" {{action "installComponent" view.content target="controller"}}>
+              <a href="javascript:void(null)" data-toggle="modal" {{action "installComponent" view.content target="controller"}}>
                 {{t common.reinstall}}
               </a>
             </li>
           {{/if}}
           {{#if view.isReassignable}}
             <li {{bindAttr class="view.noActionAvailable"}}>
-              <a href="javascript:void(null)"
-                 data-toggle="modal" {{action "moveComponent" view.content target="controller"}}>
+              <a href="javascript:void(null)" data-toggle="modal" {{action "moveComponent" view.content target="controller"}}>
                 {{t common.move}}
               </a>
             </li>
           {{/if}}
           {{#if view.isActive}}
             <li rel='passiveTooltip' {{bindAttr class="view.noActionAvailable" title="view.passiveImpliedTextStatus"}}>
-              <a href="javascript:void(null)" {{bindAttr class="view.isImplied:disabled"}}
-                 data-toggle="modal" {{action "turnOnOffPassiveConfirmation" view.content target="controller"}}>
+              <a href="javascript:void(null)" {{bindAttr class="view.isImplied:disabled"}} data-toggle="modal" {{action "turnOnOffPassiveConfirmation" view.content target="controller"}}>
                 {{t passiveState.turnOn}}
               </a>
             </li>
           {{else}}
             <li rel='passiveTooltip' {{bindAttr class="view.noActionAvailable" title="view.passiveImpliedTextStatus"}}>
-              <a href="javascript:void(null)" {{bindAttr class="view.isImplied:disabled"}}
-                 data-toggle="modal" {{action "turnOnOffPassiveConfirmation" view.content target="controller"}}>
+              <a href="javascript:void(null)" {{bindAttr class="view.isImplied:disabled"}} data-toggle="modal" {{action "turnOnOffPassiveConfirmation" view.content target="controller"}}>
                 {{t passiveState.turnOff}}
               </a>
             </li>

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/app/templates/main/host/summary.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/host/summary.hbs b/ambari-web/app/templates/main/host/summary.hbs
index 83c0ade..2b04ea9 100644
--- a/ambari-web/app/templates/main/host/summary.hbs
+++ b/ambari-web/app/templates/main/host/summary.hbs
@@ -58,7 +58,7 @@
 
           {{#each component in view.sortedComponents}}
             <div class="row-fluid">
-              {{view App.HostComponentView contentBinding="component"}}
+              {{view component.view contentBinding="component"}}
             </div>
           {{/each}}
         {{/if}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/app/utils/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax.js b/ambari-web/app/utils/ajax.js
index 0823b9b..2ada34c 100644
--- a/ambari-web/app/utils/ajax.js
+++ b/ambari-web/app/utils/ajax.js
@@ -348,23 +348,11 @@ var urls = {
   },
   'host.host_component.slave_desired_admin_state': {
     'real': '/clusters/{clusterName}/hosts/{hostName}/host_components/{componentName}/?fields=HostRoles/desired_admin_state',
-    'mock': '',
-    'type': 'GET'
-  },
-  'host.host_component.datanodes_decommission_status': {
-    'real': '/clusters/{clusterName}/services/HDFS/components/NAMENODE/?fields=ServiceComponentInfo',
-    'mock': '',
-    'type': 'GET'
-  },
-  'host.host_component.nodemanager_decommission_status': {
-    'real': '/clusters/{clusterName}/services/YARN/components/RESOURCEMANAGER/?fields=ServiceComponentInfo',
-    'mock': '',
-    'type': 'GET'
+    'mock': ''
   },
-  'host.host_component.tasktracker_decommission_status': {
-    'real': '/clusters/{clusterName}/services/MAPREDUCE/components/JOBTRACKER/?fields=ServiceComponentInfo',
-    'mock': '',
-    'type': 'GET'
+  'host.host_component.decommission_status': {
+    'real': '/clusters/{clusterName}/services/{serviceName}/components/{componentName}/?fields=ServiceComponentInfo',
+    'mock': ''
   },
   'host.host_component.decommission_slave': {
     'real' : '/clusters/{clusterName}/requests',
@@ -1683,7 +1671,7 @@ var ajax = Em.Object.extend({
    * Send ajax request
    *
    * @param {Object} config
-   * @return Object jquery ajax object
+   * @return {$.ajax} jquery ajax object
    *
    * config fields:
    *  name - url-key in the urls-object *required*

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index 88cf9b1..6f88eca 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -43,6 +43,10 @@ require('views/main/host');
 require('views/main/host/hosts_table_menu_view');
 require('views/main/host/details');
 require('views/main/host/details/host_component_view');
+require('views/main/host/details/host_component_views/datanode_view');
+require('views/main/host/details/host_component_views/nodemanager_view');
+require('views/main/host/details/host_component_views/regionserver_view');
+require('views/main/host/details/host_component_views/tasktracker_view');
 require('views/main/host/menu');
 require('views/main/host/summary');
 require('views/main/host/configs');

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/app/views/main/host/details/host_component_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/details/host_component_view.js b/ambari-web/app/views/main/host/details/host_component_view.js
index 8b26434..31e9b99 100644
--- a/ambari-web/app/views/main/host/details/host_component_view.js
+++ b/ambari-web/app/views/main/host/details/host_component_view.js
@@ -57,44 +57,13 @@ App.HostComponentView = Em.View.extend({
    * @type {String}
    */
   componentTextStatus: function () {
-    var workStatus = this.get("workStatus");
     var componentTextStatus = this.get('content.componentTextStatus');
     var hostComponent = this.get('hostComponent');
     if (hostComponent) {
       componentTextStatus = hostComponent.get('componentTextStatus');
-      if(this.get("isDataNode") && this.get('isDataNodeRecommissionAvailable')){
-        if(this.get('isDataNodeDecommissioning')){
-          componentTextStatus = Em.I18n.t('hosts.host.decommissioning');
-        } else {
-          componentTextStatus = Em.I18n.t('hosts.host.decommissioned');
-        }
-      }
-      if(this.get("isNodeManager") && this.get('isNodeManagerRecommissionAvailable')){
-        if(this.get('isNodeManagerDecommissioning')){
-          componentTextStatus = Em.I18n.t('hosts.host.decommissioning');
-        } else {
-          componentTextStatus = Em.I18n.t('hosts.host.decommissioned');
-        }
-      }
-      if(this.get("isTaskTracker") && this.get('isTaskTrackerRecommissionAvailable')){
-        if(this.get('isTaskTrackerDecommissioning')){
-          componentTextStatus = Em.I18n.t('hosts.host.decommissioning');
-        } else {
-          componentTextStatus = Em.I18n.t('hosts.host.decommissioned');
-        }
-      }
-      if(this.get("isRegionServer") && this.get('isRegionServerRecommissionAvailable')){
-        if(this.get('isRegionServerDecommissioning')){
-          componentTextStatus = Em.I18n.t('hosts.host.decommissioning');
-        } else {
-          componentTextStatus = Em.I18n.t('hosts.host.decommissioned');
-        }
-      }
     }
     return componentTextStatus;
-  }.property('content.passiveState','workStatus','isDataNodeRecommissionAvailable', 'isDataNodeDecommissioning', 'isNodeManagerRecommissionAvailable', 'isNodeManagerDecommissioning',
-      'isTaskTrackerRecommissionAvailable', 'isTaskTrackerDecommissioning', 'isRegionServerRecommissionAvailable', 'isRegionServerDecommissioning'),
-
+  }.property('content.passiveState','workStatus'),
 
   /**
    * Returns message for health tooltip
@@ -143,38 +112,10 @@ App.HostComponentView = Em.View.extend({
       return 'icon-medkit';
     }
 
-    //If the component is DataNode
-    if (this.get('isDataNode')) {
-      if (this.get('isDataNodeRecommissionAvailable') && (this.get('isStart') || this.get('workStatus') == 'INSTALLED')) {
-        return 'health-status-DEAD-ORANGE';
-      }
-    }
-
-    //If the component is NodeManager
-    if (this.get('isNodeManager')) {
-      if (this.get('isNodeManagerRecommissionAvailable') && (this.get('isStart') || this.get('workStatus') == 'INSTALLED')) {
-        return 'health-status-DEAD-ORANGE';
-      }
-    }
-
-    //If the component is TaskTracker
-    if (this.get('isTaskTracker')) {
-      if (this.get('isTaskTrackerRecommissionAvailable') && (this.get('isStart') || this.get('workStatus') == 'INSTALLED')) {
-        return 'health-status-DEAD-ORANGE';
-      }
-    }
-
-    //If the component is RegionServer
-    if (this.get('isRegionServer')) {
-      if (this.get('isRegionServerRecommissionAvailable') && (this.get('isStart') || this.get('workStatus') == 'INSTALLED')) {
-        return 'health-status-DEAD-ORANGE';
-      }
-    }
-
     //For all other cases
     return 'health-status-' + App.HostComponentStatus.getKeyName(this.get('workStatus'));
 
-  }.property('content.passiveState','workStatus', 'isDataNodeRecommissionAvailable', 'isNodeManagerRecommissionAvailable', 'isTaskTrackerRecommissionAvailable', 'isRegionServerRecommissionAvailable'),
+  }.property('content.passiveState','workStatus'),
 
   /**
    * CSS-class for disabling drop-down menu with list of host component actions
@@ -239,14 +180,13 @@ App.HostComponentView = Em.View.extend({
   }.property('workStatus'),
 
   /**
-   * For Stopping or Starting states, also for decommissioning
+   * For Stopping or Starting states
    * @type {bool}
    */
   isInProgress: function () {
     return (this.get('workStatus') === App.HostComponentStatus.stopping ||
-      this.get('workStatus') === App.HostComponentStatus.starting) ||
-      this.get('isDecommissioning');
-  }.property('workStatus', 'isDecommissioning'),
+      this.get('workStatus') === App.HostComponentStatus.starting);
+  }.property('workStatus'),
 
   /**
    * For ACTIVE <code>passiveState</code> of host component
@@ -265,15 +205,6 @@ App.HostComponentView = Em.View.extend({
   }.property('parentView.content.passiveState', 'content.service.passiveState'),
 
   /**
-   *
-   * @type {bool}
-   */
-  isDecommissioning: function () {
-    return ( (this.get('isDataNode') && this.get("isDataNodeDecommissioning")) || (this.get('isRegionServer') && this.get("isRegionServerDecommissioning"))
-      || (this.get('isNodeManager') && this.get("isNodeManagerDecommissioning")) || (this.get('isTaskTracker') && this.get('isTaskTrackerDecommissioning')));
-  }.property("workStatus", "isDataNodeDecommissioning", "isRegionServerDecommissioning", "isNodeManagerDecommissioning", "isTaskTrackerDecommissioning"),
-
-  /**
    * Shows whether we need to show Delete button
    * @type {bool}
    */
@@ -319,18 +250,6 @@ App.HostComponentView = Em.View.extend({
     if (this.get('isInProgress')) {
       this.doBlinking();
     }
-    if (this.get('isDataNode')){
-      this.loadDataNodeDecommissionStatus();
-    }
-    if (this.get('isNodeManager')){
-      this.loadNodeManagerDecommissionStatus();
-    }
-    if (this.get('isTaskTracker')){
-      this.loadTaskTrackerDecommissionStatus();
-    }
-    if (this.get('isRegionServer')){
-      this.loadRegionServerDecommissionStatus();
-    }
   },
 
   /**
@@ -340,12 +259,6 @@ App.HostComponentView = Em.View.extend({
     var workStatus = this.get('workStatus');
     var self = this;
     var pulsate = [ App.HostComponentStatus.starting, App.HostComponentStatus.stopping, App.HostComponentStatus.installing].contains(workStatus);
-    if (!pulsate && (this.get('isDataNode') || this.get('isRegionServer') || this.get('isNodeManager') || this.get('isTaskTracker'))) {
-      var component = this.get('content');
-      if (component && workStatus != "INSTALLED") {
-        pulsate = this.get('isDecommissioning');
-      }
-    }
     if (pulsate && !self.get('isBlinking')) {
       self.set('isBlinking', true);
       uiEffects.pulsate(self.$('.components-health'), 1000, function () {
@@ -354,383 +267,14 @@ App.HostComponentView = Em.View.extend({
       });
     }
   },
+
   /**
-   * Start blinking when host component is starting/stopping/decommissioning
+   * Start blinking when host component is starting/stopping
    */
   startBlinking: function () {
     this.$('.components-health').stop(true, true);
     this.$('.components-health').css({opacity: 1.0});
     this.doBlinking();
-  }.observes('workStatus','isDataNodeRecommissionAvailable', 'isDecommissioning', 'isRegionServerRecommissionAvailable',
-      'isNodeManagerRecommissionAvailable', 'isTaskTrackerRecommissionAvailable'),
-
-  isDataNode: function () {
-    return this.get('content.componentName') === 'DATANODE';
-  }.property('content'),
-
-  isNodeManager: function () {
-    return this.get('content.componentName') === 'NODEMANAGER';
-  }.property('content'),
-
-  isTaskTracker: function () {
-    return this.get('content.componentName') === 'TASKTRACKER';
-  }.property('content'),
-
-  isRegionServer: function () {
-    return this.get('content.componentName') === 'HBASE_REGIONSERVER';
-  }.property('content'),
-
-  isDataNodeDecommissioning: null,
-  isDataNodeDecommissionAvailable: null,
-  isDataNodeRecommissionAvailable: null,
-
-  updateDecommissionStatus: function() {
-    if (this.get('isDataNode'))
-      Em.run.once(this, 'loadDataNodeDecommissionStatus');
-    if (this.get('isNodeManager'))
-      Em.run.once(this, 'loadNodeManagerDecommissionStatus');
-    if (this.get('isTaskTracker'))
-      Em.run.once(this, 'loadTaskTrackerDecommissionStatus');
-    if (this.get('isRegionServer'))
-      Em.run.once(this, 'loadRegionServerDecommissionStatus');
-  }.observes('content.workStatus', 'content.passiveState'),
-
-  /**
-   * load Recommission/Decommission status from adminState of each live node
-   */
-  loadDataNodeDecommissionStatus: function () {
-    var clusterName = App.router.get('clusterController.clusterName');
-    var hostName = App.router.get('mainHostDetailsController.content.hostName');
-    var componentName = 'NAMENODE';
-    var slaveType = 'DATANODE';
-    var version = App.get('currentStackVersionNumber');
-    var dfd = $.Deferred();
-    var self = this;
-    this.getDNDecommissionStatus(clusterName, hostName, componentName).done(function () {
-      var curObj = self.get('decommissionedStatusObject');
-      self.set('decommissionedStatusObject', null);
-      // HDP-2 stack
-      if (version.charAt(0) == 2) {
-        if (curObj) {
-          var liveNodesJson = App.parseJSON(curObj.LiveNodes);
-          if (liveNodesJson && liveNodesJson[hostName] ) {
-            switch(liveNodesJson[hostName].adminState) {
-              case "In Service":
-                self.set('isDataNodeRecommissionAvailable', false);
-                self.set('isDataNodeDecommissioning', false);
-                self.set('isDataNodeDecommissionAvailable', self.get('isStart'));
-                break;
-              case "Decommission In Progress":
-                self.set('isDataNodeRecommissionAvailable', true);
-                self.set('isDataNodeDecommissioning', true);
-                self.set('isDataNodeDecommissionAvailable', false);
-                break;
-              case "Decommissioned":
-                self.set('isDataNodeRecommissionAvailable', true);
-                self.set('isDataNodeDecommissioning', false);
-                self.set('isDataNodeDecommissionAvailable', false);
-                break;
-            }
-          } else {
-            // if namenode is down, get desired_admin_state to decide if the user had issued a decommission
-            var deferred = $.Deferred();
-            self.getDesiredAdminState(clusterName, hostName, slaveType).done( function () {
-              var desired_admin_state = self.get('desiredAdminState');
-              self.set('desiredAdminState', null);
-              switch(desired_admin_state) {
-                case "INSERVICE":
-                  self.set('isDataNodeRecommissionAvailable', false);
-                  self.set('isDataNodeDecommissioning', false);
-                  self.set('isDataNodeDecommissionAvailable', self.get('isStart'));
-                  break;
-                case "DECOMMISSIONED":
-                  self.set('isDataNodeRecommissionAvailable', true);
-                  self.set('isDataNodeDecommissioning', false);
-                  self.set('isDataNodeDecommissionAvailable', false);
-                  break;
-              }
-              deferred.resolve(desired_admin_state);
-            });
-          }
-        }
-      }
-      // HDP-1 stack
-      if (version.charAt(0) == 1) {
-        if (curObj) {
-          var liveNodesJson = App.parseJSON(curObj.LiveNodes);
-          var decomNodesJson = App.parseJSON(curObj.DecomNodes);
-          var deadNodesJson = App.parseJSON(curObj.DeadNodes);
-          if (decomNodesJson && decomNodesJson[hostName] ) {
-            self.set('isDataNodeRecommissionAvailable', true);
-            self.set('isDataNodeDecommissioning', true);
-            self.set('isDataNodeDecommissionAvailable', false);
-          } else if (deadNodesJson && deadNodesJson[hostName] ) {
-            self.set('isDataNodeRecommissionAvailable', true);
-            self.set('isDataNodeDecommissioning', false);
-            self.set('isDataNodeDecommissionAvailable', false);
-          } else if (liveNodesJson && liveNodesJson[hostName] ) {
-            self.set('isDataNodeRecommissionAvailable', false);
-            self.set('isDataNodeDecommissioning', false);
-            self.set('isDataNodeDecommissionAvailable', self.get('isStart'));
-          } else {
-            // if namenode is down, get desired_admin_state to decide if the user had issued a decommission
-            var deferred = $.Deferred();
-            self.getDesiredAdminState(clusterName, hostName, slaveType).done( function () {
-              var desired_admin_state = self.get('desiredAdminState');
-              self.set('desiredAdminState', null);
-              switch(desired_admin_state) {
-                case "INSERVICE":
-                  self.set('isDataNodeRecommissionAvailable', false);
-                  self.set('isDataNodeDecommissioning', false);
-                  self.set('isDataNodeDecommissionAvailable', self.get('isStart'));
-                  break;
-                case "DECOMMISSIONED":
-                  self.set('isDataNodeRecommissionAvailable', true);
-                  self.set('isDataNodeDecommissioning', false);
-                  self.set('isDataNodeDecommissionAvailable', false);
-                  break;
-              }
-              deferred.resolve(desired_admin_state);
-            });
-          }
-        }
-      }
-      dfd.resolve(curObj);
-    });
-    return dfd.promise();
-  },
-
-  /**
-   * get datanodes decommission status: from NAMENODE component, liveNodes property
-   */
-  getDNDecommissionStatus: function(clusterName, hostName, componentName){
-    return App.ajax.send({
-      name: 'host.host_component.datanodes_decommission_status',
-      sender: this,
-      data: {
-        clusterName: clusterName,
-        hostName: hostName,
-        componentName: componentName
-      },
-      success: 'getDNDecommissionStatusSuccessCallback',
-      error: 'getDNDecommissionStatusErrorCallback'
-    });
-  },
-
-  decommissionedStatusObject: null,
-  getDNDecommissionStatusSuccessCallback: function (response, request, data) {
-    var statusObject = response.ServiceComponentInfo;
-    if ( statusObject != null) {
-      this.set('decommissionedStatusObject', statusObject);
-      return statusObject;
-    }
-  },
-  getDNDecommissionStatusErrorCallback: function (request, ajaxOptions, error) {
-    console.log('ERROR: '+ error);
-    this.set('decommissionedStatusObject', null);
-    return null;
-  },
-
-  /**
-   * get desired_admin_state status of DataNode, TaskTracker, NodeManager and RegionServer
-   */
-  getDesiredAdminState: function(clusterName, hostName, componentName){
-    return App.ajax.send({
-      name: 'host.host_component.slave_desired_admin_state',
-      sender: this,
-      data: {
-        clusterName: clusterName,
-        hostName: hostName,
-        componentName: componentName
-      },
-      success: 'getDesiredAdminStateSuccessCallback',
-      error: 'getDesiredAdminStateErrorCallback'
-    });
-  },
-  desiredAdminState: null,
-  getDesiredAdminStateSuccessCallback: function (response, request, data) {
-    var status = response.HostRoles.desired_admin_state;
-    if ( status != null) {
-      this.set('desiredAdminState', status);
-      return status;
-    }
-  },
-  getDesiredAdminStateErrorCallback: function (request, ajaxOptions, error) {
-    console.log('ERROR: '+ error);
-    this.set('desiredAdminState', null);
-    return null;
-  },
-
-  isNodeManagerDecommissionAvailable: null,
-  isNodeManagerRecommissionAvailable: null,
-  isNodeManagerDecommissioning: null,
-  /**
-   * load Recommission/Decommission status for nodeManager from nodeManagers list
-   */
-  loadNodeManagerDecommissionStatus: function () {
-    var clusterName = App.router.get('clusterController.clusterName');
-    var hostName = App.router.get('mainHostDetailsController.content.hostName');
-    var componentName = 'RESOURCEMANAGER';
-    var slaveType = 'NODEMANAGER';
-    var dfd = $.Deferred();
-    var self = this;
-
-    this.getDesiredAdminState(clusterName, hostName, slaveType).done( function () {
-      var desired_admin_state = self.get('desiredAdminState');
-      self.set('desiredAdminState', null);
-      switch(desired_admin_state) {
-        case "INSERVICE":
-          // can be decommissioned if already started
-          self.set('isNodeManagerRecommissionAvailable', false);
-          self.set('isNodeManagerDecommissioning', false);
-          self.set('isNodeManagerDecommissionAvailable', self.get('isStart'));
-          break;
-        case "DECOMMISSIONED":
-          var deferred = $.Deferred();
-          self.getNMDecommissionStatus(clusterName, hostName, componentName).done( function() {
-            var curObj = self.get('decommissionedStatusObject');
-            self.set('decommissionedStatusObject', null);
-            if (curObj && curObj.rm_metrics) {
-              var nodeManagersArray = App.parseJSON(curObj.rm_metrics.cluster.nodeManagers);
-              if (nodeManagersArray.findProperty('HostName', hostName)){
-                // decommisioning ..
-                self.set('isNodeManagerRecommissionAvailable', true);
-                self.set('isNodeManagerDecommissioning', true);
-                self.set('isNodeManagerDecommissionAvailable', false);
-              } else {
-                // decommissioned ..
-                self.set('isNodeManagerRecommissionAvailable', true);
-                self.set('isNodeManagerDecommissioning', false);
-                self.set('isNodeManagerDecommissionAvailable', false);
-              }
-            }
-            deferred.resolve(curObj);
-          });
-          break;
-      }
-      dfd.resolve(desired_admin_state);
-    });
-    return dfd.promise();
-  },
-
-  /**
-   * get NodeManager decommission status: from RESOURCEMANAGER component, rm_metrics/nodeManagers property
-   */
-  getNMDecommissionStatus: function(clusterName, hostName, componentName){
-    return App.ajax.send({
-      name: 'host.host_component.nodemanager_decommission_status',
-      sender: this,
-      data: {
-        clusterName: clusterName,
-        hostName: hostName,
-        componentName: componentName
-      },
-      success: 'getDNDecommissionStatusSuccessCallback',
-      error: 'getDNDecommissionStatusErrorCallback'
-    });
-  },
-
-  isTaskTrackerDecommissionAvailable: null,
-  isTaskTrackerRecommissionAvailable: null,
-  isTaskTrackerDecommissioning: null,
-  /**
-   * load Recommission/Decommission status for TaskTracker from JobTracker/AliveNodes list
-   */
-  loadTaskTrackerDecommissionStatus: function () {
-    var clusterName = App.router.get('clusterController.clusterName');
-    var hostName = App.router.get('mainHostDetailsController.content.hostName');
-    var componentName = 'JOBTRACKER';
-    var slaveType = 'TASKTRACKER';
-    var dfd = $.Deferred();
-    var self = this;
-    this.getDesiredAdminState(clusterName, hostName, slaveType).done( function () {
-      var desired_admin_state = self.get('desiredAdminState');
-      self.set('desiredAdminState', null);
-      switch(desired_admin_state) {
-        case "INSERVICE":
-          // can be decommissioned if already started
-          self.set('isTaskTrackerRecommissionAvailable', false);
-          self.set('isTaskTrackerDecommissioning', false);
-          self.set('isTaskTrackerDecommissionAvailable', self.get('isStart'));
-          break;
-        case "DECOMMISSIONED":
-          var deferred = $.Deferred();
-          self.getTTDecommissionStatus(clusterName, hostName, componentName).done( function() {
-            var curObj = self.get('decommissionedStatusObject');
-            self.set('decommissionedStatusObject', null);
-            if (curObj) {
-              var aliveNodesArray = App.parseJSON(curObj.AliveNodes);
-              if (aliveNodesArray != null) {
-                if (aliveNodesArray.findProperty('hostname', hostName)){
-                  //decommissioning ..
-                  self.set('isTaskTrackerRecommissionAvailable', true);
-                  self.set('isTaskTrackerDecommissioning', true);
-                  self.set('isTaskTrackerDecommissionAvailable', false);
-                } else {
-                  //decommissioned
-                  self.set('isTaskTrackerRecommissionAvailable', true);
-                  self.set('isTaskTrackerDecommissioning', false);
-                  self.set('isTaskTrackerDecommissionAvailable', false);
-                }
-              }
-
-            }
-            deferred.resolve(curObj);
-          });
-          break;
-      }
-      dfd.resolve(desired_admin_state);
-    });
-    return dfd.promise();
-  },
-
-  /**
-   * get TaskTracker decommission status: from JobTracker component, AliveNodes property
-   */
-  getTTDecommissionStatus: function(clusterName, hostName, componentName){
-    return App.ajax.send({
-      name: 'host.host_component.tasktracker_decommission_status',
-      sender: this,
-      data: {
-        clusterName: clusterName,
-        hostName: hostName,
-        componentName: componentName
-      },
-      success: 'getDNDecommissionStatusSuccessCallback',
-      error: 'getDNDecommissionStatusErrorCallback'
-    });
-  },
-
-  isRegionServerDecommissioning: null,
-  isRegionServerDecommissionAvailable: null,
-  isRegionServerRecommissionAvailable: null,
-  /**
-   * load Recommission/Decommission status of RegionServer
-   */
-  loadRegionServerDecommissionStatus: function () {
-    var clusterName = App.router.get('clusterController.clusterName');
-    var hostName = App.router.get('mainHostDetailsController.content.hostName');
-    var slaveType = 'HBASE_REGIONSERVER';
-    var self = this;
-    var deferred = $.Deferred();
-    self.getDesiredAdminState(clusterName, hostName, slaveType).done( function () {
-      var desired_admin_state = self.get('desiredAdminState');
-      self.set('desiredAdminState', null);
-      switch(desired_admin_state) {
-        case "INSERVICE":
-          self.set('isRegionServerRecommissionAvailable', false);
-          self.set('isRegionServerDecommissioning', false);
-          self.set('isRegionServerDecommissionAvailable', self.get('isStart'));
-          break;
-        case "DECOMMISSIONED":
-          self.set('isRegionServerRecommissionAvailable', true);
-          self.set('isRegionServerDecommissioning', self.get('isStart'));
-          self.set('isRegionServerDecommissionAvailable', false);
-          break;
-      }
-      deferred.resolve(desired_admin_state);
-    });
-    return deferred.promise();
-  }
+  }.observes('workStatus')
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/app/views/main/host/details/host_component_views/datanode_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/details/host_component_views/datanode_view.js b/ambari-web/app/views/main/host/details/host_component_views/datanode_view.js
new file mode 100644
index 0000000..a2b1c04
--- /dev/null
+++ b/ambari-web/app/views/main/host/details/host_component_views/datanode_view.js
@@ -0,0 +1,127 @@
+/**
+ * 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');
+require('views/main/host/details/host_component_views/decommissionable');
+
+App.DataNodeComponentView = App.HostComponentView.extend(App.Decommissionable, {
+
+  componentForCheckDecommission: 'NAMENODE',
+
+  /**
+   * load Recommission/Decommission status from adminState of each live node
+   */
+  loadComponentDecommissionStatus: function () {
+    var hostName = this.get('content.host.hostName');
+    var dfd = $.Deferred();
+    var self = this;
+    this.getDecommissionStatus().done(function () {
+      var curObj = self.get('decommissionedStatusObject');
+      self.set('decommissionedStatusObject', null);
+      // HDP-2 stack
+      if (App.get('isHadoop2Stack')) {
+        if (curObj) {
+          var liveNodesJson = App.parseJSON(curObj.LiveNodes);
+          if (liveNodesJson && liveNodesJson[hostName] ) {
+            switch(liveNodesJson[hostName].adminState) {
+              case "In Service":
+                self.set('isComponentRecommissionAvailable', false);
+                self.set('isComponentDecommissioning', false);
+                self.set('isComponentDecommissionAvailable', self.get('isStart'));
+                break;
+              case "Decommission In Progress":
+                self.set('isComponentRecommissionAvailable', true);
+                self.set('isComponentDecommissioning', true);
+                self.set('isComponentDecommissionAvailable', false);
+                break;
+              case "Decommissioned":
+                self.set('isComponentRecommissionAvailable', true);
+                self.set('isComponentDecommissioning', false);
+                self.set('isComponentDecommissionAvailable', false);
+                break;
+            }
+          } else {
+            // if namenode is down, get desired_admin_state to decide if the user had issued a decommission
+            var deferred = $.Deferred();
+            self.getDesiredAdminState().done(function () {
+              var desired_admin_state = self.get('desiredAdminState');
+              self.set('desiredAdminState', null);
+              switch(desired_admin_state) {
+                case "INSERVICE":
+                  self.set('isComponentRecommissionAvailable', false);
+                  self.set('isComponentDecommissioning', false);
+                  self.set('isComponentDecommissionAvailable', self.get('isStart'));
+                  break;
+                case "DECOMMISSIONED":
+                  self.set('isComponentRecommissionAvailable', true);
+                  self.set('isComponentDecommissioning', false);
+                  self.set('isComponentDecommissionAvailable', false);
+                  break;
+              }
+              deferred.resolve(desired_admin_state);
+            });
+          }
+        }
+      }
+      else {
+        if (curObj) {
+          var liveNodesJson = App.parseJSON(curObj.LiveNodes);
+          var decomNodesJson = App.parseJSON(curObj.DecomNodes);
+          var deadNodesJson = App.parseJSON(curObj.DeadNodes);
+          if (decomNodesJson && decomNodesJson[hostName] ) {
+            self.set('isComponentRecommissionAvailable', true);
+            self.set('isComponentDecommissioning', true);
+            self.set('isComponentDecommissionAvailable', false);
+          } else if (deadNodesJson && deadNodesJson[hostName] ) {
+            self.set('isComponentRecommissionAvailable', true);
+            self.set('isComponentDecommissioning', false);
+            self.set('isComponentDecommissionAvailable', false);
+          } else if (liveNodesJson && liveNodesJson[hostName] ) {
+            self.set('isComponentRecommissionAvailable', false);
+            self.set('isComponentDecommissioning', false);
+            self.set('isComponentDecommissionAvailable', self.get('isStart'));
+          } else {
+            // if namenode is down, get desired_admin_state to decide if the user had issued a decommission
+            var deferred = $.Deferred();
+            self.getDesiredAdminState().done( function () {
+              var desired_admin_state = self.get('desiredAdminState');
+              self.set('desiredAdminState', null);
+              switch(desired_admin_state) {
+                case "INSERVICE":
+                  self.set('isComponentRecommissionAvailable', false);
+                  self.set('isComponentDecommissioning', false);
+                  self.set('isComponentDecommissionAvailable', self.get('isStart'));
+                  break;
+                case "DECOMMISSIONED":
+                  self.set('isComponentRecommissionAvailable', true);
+                  self.set('isComponentDecommissioning', false);
+                  self.set('isComponentDecommissionAvailable', false);
+                  break;
+              }
+              deferred.resolve(desired_admin_state);
+            });
+          }
+        }
+      }
+      dfd.resolve(curObj);
+    });
+    return dfd.promise();
+  }
+
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/app/views/main/host/details/host_component_views/decommissionable.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/details/host_component_views/decommissionable.js b/ambari-web/app/views/main/host/details/host_component_views/decommissionable.js
new file mode 100644
index 0000000..b17f2c9
--- /dev/null
+++ b/ambari-web/app/views/main/host/details/host_component_views/decommissionable.js
@@ -0,0 +1,253 @@
+/**
+ * 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');
+var uiEffects = require('utils/ui_effects');
+
+/**
+ * Mixin for <code>App.HostComponentView</code>
+ * Contains code for processing components with allowed decommission
+ * @type {Em.Mixin}
+ */
+App.Decommissionable = Em.Mixin.create({
+
+  /**
+   * Should be redeclared in views that use this mixin
+   * @type {String}
+   */
+  componentForCheckDecommission: '',
+
+  /**
+   * Received from server object with data about decommission
+   * @type {Object}
+   */
+  decommissionedStatusObject: null,
+
+  /**
+   * Received from server desired_admin_state value
+   * @type {String}
+   */
+  desiredAdminState: null,
+
+  /**
+   * Is component in decommission process right know
+   * @type {bool}
+   */
+  isComponentDecommissioning: null,
+
+  /**
+   * May conponent be decommissioned
+   * @type {bool}
+   */
+  isComponentDecommissionAvailable: null,
+
+  /**
+   * May component be recommissioned
+   * @type {bool}
+   */
+  isComponentRecommissionAvailable: null,
+
+  /**
+   * Recalculated component status based on decommission
+   * @type {string}
+   */
+  statusClass: function () {
+
+    //Class when install failed
+    if (this.get('workStatus') === App.HostComponentStatus.install_failed) {
+      return 'health-status-color-red icon-cog';
+    }
+
+    //Class when installing
+    if (this.get('workStatus') === App.HostComponentStatus.installing) {
+      return 'health-status-color-blue icon-cog';
+    }
+
+    //Class when maintenance
+    if (this.get('content.passiveState') != "ACTIVE") {
+      return 'icon-medkit';
+    }
+
+    if (this.get('isComponentRecommissionAvailable') && (this.get('isStart') || this.get('workStatus') == 'INSTALLED')) {
+      return 'health-status-DEAD-ORANGE';
+    }
+
+    //For all other cases
+    return 'health-status-' + App.HostComponentStatus.getKeyName(this.get('workStatus'));
+
+  }.property('content.passiveState','workStatus', 'isComponentRecommissionAvailable', 'isComponentDecommissioning'),
+
+  /**
+   * Return host component text status
+   * @type {String}
+   */
+  componentTextStatus: function () {
+    var componentTextStatus = this.get('content.componentTextStatus');
+    var hostComponent = this.get('hostComponent');
+    if (hostComponent) {
+      componentTextStatus = hostComponent.get('componentTextStatus');
+      if(this.get('isComponentRecommissionAvailable')){
+        if(this.get('isComponentDecommissioning')){
+          componentTextStatus = Em.I18n.t('hosts.host.decommissioning');
+        } else {
+          componentTextStatus = Em.I18n.t('hosts.host.decommissioned');
+        }
+      }
+    }
+    return componentTextStatus;
+  }.property('content.passiveState','workStatus','isComponentRecommissionAvailable','isComponentDecommissioning'),
+
+  /**
+   * For Stopping or Starting states, also for decommissioning
+   * @type {bool}
+   */
+  isInProgress: function () {
+    return (this.get('workStatus') === App.HostComponentStatus.stopping ||
+      this.get('workStatus') === App.HostComponentStatus.starting) ||
+      this.get('isDecommissioning');
+  }.property('workStatus', 'isDecommissioning'),
+
+  /**
+   * Get desired_admin_state status from server
+   */
+  getDesiredAdminState: function(){
+    return App.ajax.send({
+      name: 'host.host_component.slave_desired_admin_state',
+      sender: this,
+      data: {
+        hostName: this.get('content.host.hostName'),
+        componentName: this.get('content.componentName')
+      },
+      success: 'getDesiredAdminStateSuccessCallback',
+      error: 'getDesiredAdminStateErrorCallback'
+    });
+  },
+
+  /**
+   * Set received value or null to <code>desiredAdminState</code>
+   * @param {Object} response
+   * @returns {String|null}
+   */
+  getDesiredAdminStateSuccessCallback: function (response) {
+    var status = response.HostRoles.desired_admin_state;
+    if ( status != null) {
+      this.set('desiredAdminState', status);
+      return status;
+    }
+    return null;
+  },
+
+  /**
+   * Set null to <code>desiredAdminState</code> if server returns error
+   * @returns {null}
+   */
+  getDesiredAdminStateErrorCallback: function () {
+    this.set('desiredAdminState', null);
+    return null;
+  },
+
+  /**
+   * Get component decommission status from server
+   * @returns {$.ajax}
+   */
+  getDecommissionStatus: function() {
+    return App.ajax.send({
+      name: 'host.host_component.decommission_status',
+      sender: this,
+      data: {
+        hostName: this.get('content.host.hostName'),
+        componentName: this.get('componentForCheckDecommission'),
+        serviceName: this.get('content.service.serviceName')
+      },
+      success: 'getDecommissionStatusSuccessCallback',
+      error: 'getDecommissionStatusErrorCallback'
+    });
+  },
+
+  /**
+   * Set received value or null to <code>decommissionedStatusObject</code>
+   * @param {Object} response
+   * @returns {Object|null}
+   */
+  getDecommissionStatusSuccessCallback: function (response) {
+    var statusObject = response.ServiceComponentInfo;
+    if ( statusObject != null) {
+      this.set('decommissionedStatusObject', statusObject);
+      return statusObject;
+    }
+    return null;
+  },
+
+  /**
+   * Set null to <code>decommissionedStatusObject</code> if server returns error
+   * @returns {null}
+   */
+  getDecommissionStatusErrorCallback: function () {
+    this.set('decommissionedStatusObject', null);
+    return null;
+  },
+
+  /**
+   * Do blinking for 1 minute
+   */
+  doBlinking: function () {
+    var workStatus = this.get('workStatus');
+    var self = this;
+    var pulsate = [App.HostComponentStatus.starting, App.HostComponentStatus.stopping, App.HostComponentStatus.installing].contains(workStatus);
+    if (!pulsate) {
+      var component = this.get('content');
+      if (component && workStatus != "INSTALLED") {
+        pulsate = this.get('isDecommissioning');
+      }
+    }
+    if (pulsate && !self.get('isBlinking')) {
+      self.set('isBlinking', true);
+      uiEffects.pulsate(self.$('.components-health'), 1000, function () {
+        self.set('isBlinking', false);
+        self.doBlinking();
+      });
+    }
+  },
+
+  /**
+   * Start blinking when host component is starting/stopping/decommissioning
+   */
+  startBlinking: function () {
+    this.$('.components-health').stop(true, true);
+    this.$('.components-health').css({opacity: 1.0});
+    this.doBlinking();
+  }.observes('workStatus','isComponentRecommissionAvailable', 'isDecommissioning'),
+
+  /**
+   * Should be redeclared in views that use this mixin
+   */
+  loadComponentDecommissionStatus: function() {},
+
+  didInsertElement: function() {
+    this._super();
+    this.loadComponentDecommissionStatus();
+  },
+
+  /**
+   * Update Decommission status only one time when component was changed
+   */
+  updateDecommissionStatus: function() {
+    Em.run.once(this, 'loadComponentDecommissionStatus');
+  }.observes('content.workStatus', 'content.passiveState')
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/app/views/main/host/details/host_component_views/nodemanager_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/details/host_component_views/nodemanager_view.js b/ambari-web/app/views/main/host/details/host_component_views/nodemanager_view.js
new file mode 100644
index 0000000..16fadc9
--- /dev/null
+++ b/ambari-web/app/views/main/host/details/host_component_views/nodemanager_view.js
@@ -0,0 +1,71 @@
+/**
+ * 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');
+require('views/main/host/details/host_component_views/decommissionable');
+
+App.NodeManagerComponentView = App.HostComponentView.extend(App.Decommissionable, {
+
+  componentForCheckDecommission: 'RESOURCEMANAGER',
+
+  /**
+   * load Recommission/Decommission status for nodeManager from nodeManagers list
+   */
+  loadComponentDecommissionStatus: function () {
+    var hostName = this.get('content.host.hostName');
+    var dfd = $.Deferred();
+    var self = this;
+    this.getDesiredAdminState().done( function () {
+      var desired_admin_state = self.get('desiredAdminState');
+      self.set('desiredAdminState', null);
+      switch(desired_admin_state) {
+        case "INSERVICE":
+          // can be decommissioned if already started
+          self.set('isComponentRecommissionAvailable', false);
+          self.set('isComponentDecommissioning', false);
+          self.set('isComponentDecommissionAvailable', self.get('isStart'));
+          break;
+        case "DECOMMISSIONED":
+          var deferred = $.Deferred();
+          self.getDecommissionStatus().done( function() {
+            var curObj = self.get('decommissionedStatusObject');
+            self.set('decommissionedStatusObject', null);
+            if (curObj && curObj.rm_metrics) {
+              var nodeManagersArray = App.parseJSON(curObj.rm_metrics.cluster.nodeManagers);
+              if (nodeManagersArray.findProperty('HostName', hostName)){
+                // decommisioning ..
+                self.set('isComponentRecommissionAvailable', true);
+                self.set('isComponentDecommissioning', true);
+                self.set('isComponentDecommissionAvailable', false);
+              } else {
+                // decommissioned ..
+                self.set('isComponentRecommissionAvailable', true);
+                self.set('isComponentDecommissioning', false);
+                self.set('isComponentDecommissionAvailable', false);
+              }
+            }
+            deferred.resolve(curObj);
+          });
+          break;
+      }
+      dfd.resolve(desired_admin_state);
+    });
+    return dfd.promise();
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/app/views/main/host/details/host_component_views/regionserver_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/details/host_component_views/regionserver_view.js b/ambari-web/app/views/main/host/details/host_component_views/regionserver_view.js
new file mode 100644
index 0000000..0d166dd
--- /dev/null
+++ b/ambari-web/app/views/main/host/details/host_component_views/regionserver_view.js
@@ -0,0 +1,52 @@
+/**
+ * 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');
+require('views/main/host/details/host_component_views/decommissionable');
+
+App.RegionServerComponentView = App.HostComponentView.extend(App.Decommissionable, {
+
+  /**
+   * load Recommission/Decommission status of RegionServer
+   */
+  loadComponentDecommissionStatus: function () {
+    var hostName = this.get('content.host.hostName');
+    var slaveType = 'HBASE_REGIONSERVER';
+    var self = this;
+    var deferred = $.Deferred();
+    self.getDesiredAdminState().done( function () {
+      var desired_admin_state = self.get('desiredAdminState');
+      self.set('desiredAdminState', null);
+      switch(desired_admin_state) {
+        case "INSERVICE":
+          self.set('isComponentRecommissionAvailable', false);
+          self.set('isComponentDecommissioning', false);
+          self.set('isComponentDecommissionAvailable', self.get('isStart'));
+          break;
+        case "DECOMMISSIONED":
+          self.set('isComponentRecommissionAvailable', true);
+          self.set('isComponentDecommissioning', self.get('isStart'));
+          self.set('isComponentDecommissionAvailable', false);
+          break;
+      }
+      deferred.resolve(desired_admin_state);
+    });
+    return deferred.promise();
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/app/views/main/host/details/host_component_views/tasktracker_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/details/host_component_views/tasktracker_view.js b/ambari-web/app/views/main/host/details/host_component_views/tasktracker_view.js
new file mode 100644
index 0000000..7948ef4
--- /dev/null
+++ b/ambari-web/app/views/main/host/details/host_component_views/tasktracker_view.js
@@ -0,0 +1,74 @@
+/**
+ * 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');
+require('views/main/host/details/host_component_views/decommissionable');
+
+App.TaskTrackerComponentView = App.HostComponentView.extend(App.Decommissionable, {
+
+  componentForCheckDecommission: 'JOBTRACKER',
+
+  /**
+   * load Recommission/Decommission status for TaskTracker from JobTracker/AliveNodes list
+   */
+  loadComponentDecommissionStatus: function () {
+    var hostName = this.get('content.host.hostName');
+    var dfd = $.Deferred();
+    var self = this;
+    this.getDesiredAdminState().done( function () {
+      var desired_admin_state = self.get('desiredAdminState');
+      self.set('desiredAdminState', null);
+      switch(desired_admin_state) {
+        case "INSERVICE":
+          // can be decommissioned if already started
+          self.set('isComponentRecommissionAvailable', false);
+          self.set('isComponentDecommissioning', false);
+          self.set('isComponentDecommissionAvailable', self.get('isStart'));
+          break;
+        case "DECOMMISSIONED":
+          var deferred = $.Deferred();
+          self.getDecommissionStatus().done( function() {
+            var curObj = self.get('decommissionedStatusObject');
+            self.set('decommissionedStatusObject', null);
+            if (curObj) {
+              var aliveNodesArray = App.parseJSON(curObj.AliveNodes);
+              if (aliveNodesArray != null) {
+                if (aliveNodesArray.findProperty('hostname', hostName)){
+                  //decommissioning ..
+                  self.set('isComponentRecommissionAvailable', true);
+                  self.set('isComponentDecommissioning', true);
+                  self.set('isComponentDecommissionAvailable', false);
+                } else {
+                  //decommissioned
+                  self.set('isComponentRecommissionAvailable', true);
+                  self.set('isComponentDecommissioning', false);
+                  self.set('isComponentDecommissionAvailable', false);
+                }
+              }
+
+            }
+            deferred.resolve(curObj);
+          });
+          break;
+      }
+      dfd.resolve(desired_admin_state);
+    });
+    return dfd.promise();
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/app/views/main/host/summary.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/summary.js b/ambari-web/app/views/main/host/summary.js
index cb95d79..d367e89 100644
--- a/ambari-web/app/views/main/host/summary.js
+++ b/ambari-web/app/views/main/host/summary.js
@@ -23,6 +23,25 @@ App.MainHostSummaryView = Em.View.extend({
   templateName: require('templates/main/host/summary'),
 
   /**
+   * List of custom view for some host components
+   * @type {Em.Object}
+   * Format:
+   *  <code>
+   *    {
+   *      COMPONENT_NAME1: VIEW1,
+   *      COMPONENT_NAME2: VIEW2
+   *      ....
+   *    }
+   *  </code>
+   */
+  hostComponentViewMap: Em.Object.create({
+    'DATANODE': App.DataNodeComponentView,
+    'NODEMANAGER': App.NodeManagerComponentView,
+    'HBASE_REGIONSERVER': App.RegionServerComponentView,
+    'TASKTRACKER': App.TaskTrackerComponentView
+  }),
+
+  /**
    * @type {bool}
    */
   isStopCommand:true,
@@ -107,6 +126,7 @@ App.MainHostSummaryView = Em.View.extend({
   sortedComponentsFormatter: function() {
     var updatebleProperties = Em.A(['workStatus', 'passiveState', 'staleConfigs', 'haStatus']);
     var self = this;
+    var hostComponentViewMap = this.get('hostComponentViewMap');
     // Remove deleted components
     this.get('sortedComponents').forEach(function(sortedComponent, index) {
       if (!self.get('content.hostComponents').findProperty('id', sortedComponent.get('id'))) {
@@ -125,6 +145,7 @@ App.MainHostSummaryView = Em.View.extend({
         }
         else {
           // Add new component
+          component.set('view', hostComponentViewMap[component.get('componentName')] ? hostComponentViewMap[component.get('componentName')] : App.HostComponentView);
           if (component.get('isMaster')) {
             // Masters should be before slaves
             var lastMasterIndex = 0, atLeastOneMasterExists = false;

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/test/views/main/host/details/host_component_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/host/details/host_component_view_test.js b/ambari-web/test/views/main/host/details/host_component_view_test.js
index 226ba1f..394133e 100644
--- a/ambari-web/test/views/main/host/details/host_component_view_test.js
+++ b/ambari-web/test/views/main/host/details/host_component_view_test.js
@@ -36,14 +36,19 @@ describe('App.HostComponentView', function() {
 
     var tests = Em.A([
       {
-        content: Em.Object.create({passiveState: 'PASSIVE'}),
+        content: Em.Object.create({componentTextStatus: 'status', passiveState: 'PASSIVE'}),
         m: 'PASSIVE state',
         e: Em.I18n.t('hosts.component.passive.short.mode')
       },
       {
-        content: Em.Object.create({passiveState: 'IMPLIED'}),
+        content: Em.Object.create({componentTextStatus: 'status', passiveState: 'IMPLIED'}),
         m: 'IMPLIED state',
         e: Em.I18n.t('hosts.component.passive.short.mode')
+      },
+      {
+        content: Em.Object.create({componentTextStatus: 'status', passiveState: 'ACTIVE'}),
+        m: 'ACTIVE state',
+        e: 'status'
       }
     ]);
 
@@ -313,4 +318,133 @@ describe('App.HostComponentView', function() {
 
   });
 
+  describe('#componentTextStatus', function() {
+
+    var tests = Em.A([
+      {
+        content: Em.Object.create({componentTextStatus: 'status'}),
+        hostComponent: null,
+        e: 'status',
+        m: 'get content status'
+      },
+      {
+        content: Em.Object.create({componentTextStatus: 'status'}),
+        hostComponent: Em.Object.create({componentTextStatus: 'new_status'}),
+        e: 'new_status',
+        m: 'get hostComponent status'
+      }
+    ]);
+
+    tests.forEach(function(test) {
+      it(test.m, function() {
+        hostComponentView = App.HostComponentView.create({
+          startBlinking: function(){},
+          doBlinking: function(){},
+          getDesiredAdminState: function(){return $.ajax({});},
+          content: test.content,
+          hostComponent: test.hostComponent
+        });
+        expect(hostComponentView.get('componentTextStatus')).to.equal(test.e);
+      });
+    });
+
+  });
+
+  describe('#workStatus', function() {
+
+    var tests = Em.A([
+      {
+        content: Em.Object.create({workStatus: 'status'}),
+        hostComponent: null,
+        e: 'status',
+        m: 'get content workStatus'
+      },
+      {
+        content: Em.Object.create({workStatus: 'status'}),
+        hostComponent: Em.Object.create({workStatus: 'new_status'}),
+        e: 'new_status',
+        m: 'get hostComponent workStatus'
+      }
+    ]);
+
+    tests.forEach(function(test) {
+      it(test.m, function() {
+        hostComponentView = App.HostComponentView.create({
+          startBlinking: function(){},
+          doBlinking: function(){},
+          getDesiredAdminState: function(){return $.ajax({});},
+          content: test.content,
+          hostComponent: test.hostComponent
+        });
+        expect(hostComponentView.get('workStatus')).to.equal(test.e);
+      });
+    });
+
+  });
+
+  describe('#statusClass', function() {
+
+    var tests = Em.A([
+      {
+        content: Em.Object.create({workStatus: App.HostComponentStatus.install_failed,passiveState: 'ACTIVE'}),
+        e: 'health-status-color-red icon-cog'
+      },
+      {
+        content: Em.Object.create({workStatus: App.HostComponentStatus.installing, passiveState: 'ACTIVE'}),
+        e: 'health-status-color-blue icon-cog'
+      },
+      {
+        content: Em.Object.create({workStatus: 'STARTED', passiveState: 'PASSIVE'}),
+        e: 'icon-medkit'
+      },
+      {
+        content: Em.Object.create({workStatus: 'STARTED', passiveState: 'IMPLIED'}),
+        e: 'icon-medkit'
+      },
+      {
+        content: Em.Object.create({workStatus: 'STARTED', passiveState: 'ACTIVE'}),
+        e: 'health-status-started'
+      }
+    ]);
+
+    tests.forEach(function(test) {
+      it(test.content.get('workStatus') + ' ' + test.content.get('passiveState'), function() {
+        hostComponentView = App.HostComponentView.create({
+          startBlinking: function(){},
+          doBlinking: function(){},
+          getDesiredAdminState: function(){return $.ajax({});},
+          content: test.content
+        });
+        expect(hostComponentView.get('statusClass')).to.equal(test.e);
+      });
+    });
+
+  });
+
+  describe('#isInProgress', function() {
+
+    var tests = Em.A([
+      {
+        workStatus: App.HostComponentStatus.stopping,
+        e: true
+      },
+      {
+        workStatus: App.HostComponentStatus.starting,
+        e: true
+      },
+      {
+        workStatus: 'other_status',
+        e: false
+      }
+    ]);
+
+    tests.forEach(function(test) {
+      it(test.workStatus, function() {
+        hostComponentView.set('content', Em.Object.create({workStatus: test.workStatus}));
+        expect(hostComponentView.get('isInProgress')).to.equal(test.e);
+      });
+    });
+
+  });
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/746e68fc/ambari-web/test/views/main/host/details/host_component_views/decommissionable_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/host/details/host_component_views/decommissionable_test.js b/ambari-web/test/views/main/host/details/host_component_views/decommissionable_test.js
new file mode 100644
index 0000000..edbe8ca
--- /dev/null
+++ b/ambari-web/test/views/main/host/details/host_component_views/decommissionable_test.js
@@ -0,0 +1,201 @@
+/**
+ * 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');
+require('models/host_component');
+require('views/main/host/details/host_component_view');
+require('views/main/host/details/host_component_views/decommissionable');
+
+var hostComponentView;
+
+describe('App.Decommissionable', function() {
+
+  beforeEach(function() {
+    hostComponentView = App.HostComponentView.create(App.Decommissionable, {
+      startBlinking: function(){},
+      doBlinking: function(){},
+      getDesiredAdminState: function(){return $.ajax({});}
+    });
+  });
+
+  describe('#componentTextStatus', function() {
+
+    var tests = Em.A([
+      {
+        content: Em.Object.create({componentTextStatus: 'status'}),
+        hostComponent: null,
+        isComponentRecommissionAvailable: false,
+        isComponentDecommissioning: false,
+        e: 'status',
+        m: 'get content status'
+      },
+      {
+        content: Em.Object.create({componentTextStatus: 'status'}),
+        hostComponent: Em.Object.create({componentTextStatus: 'new_status'}),
+        isComponentRecommissionAvailable: false,
+        isComponentDecommissioning: false,
+        e: 'new_status',
+        m: 'get hostComponent status'
+      },
+      {
+        content: Em.Object.create({componentTextStatus: 'status'}),
+        hostComponent: Em.Object.create({componentTextStatus: 'new_status'}),
+        isComponentRecommissionAvailable: false,
+        isComponentDecommissioning: false,
+        e: 'new_status',
+        m: 'get hostComponent status'
+      },
+      {
+        content: Em.Object.create({componentTextStatus: 'status'}),
+        hostComponent: Em.Object.create({componentTextStatus: 'new_status'}),
+        isComponentRecommissionAvailable: true,
+        isComponentDecommissioning: true,
+        e: Em.I18n.t('hosts.host.decommissioning'),
+        m: 'get decommissioning status'
+      },
+      {
+        content: Em.Object.create({componentTextStatus: 'status'}),
+        hostComponent: Em.Object.create({componentTextStatus: 'new_status'}),
+        isComponentRecommissionAvailable: true,
+        isComponentDecommissioning: false,
+        e: Em.I18n.t('hosts.host.decommissioned'),
+        m: 'get decommissioned status'
+      }
+    ]);
+
+    tests.forEach(function(test) {
+      it(test.m, function() {
+        hostComponentView = App.HostComponentView.create(App.Decommissionable, {
+          startBlinking: function(){},
+          doBlinking: function(){},
+          getDesiredAdminState: function(){return $.ajax({});},
+          content: test.content,
+          hostComponent: test.hostComponent,
+          isComponentRecommissionAvailable: test.isComponentRecommissionAvailable,
+          isComponentDecommissioning: test.isComponentDecommissioning
+        });
+        expect(hostComponentView.get('componentTextStatus')).to.equal(test.e);
+      });
+    });
+
+  });
+
+  describe('#statusClass', function() {
+
+    var tests = Em.A([
+      {
+        content: Em.Object.create({workStatus: App.HostComponentStatus.install_failed,passiveState: 'ACTIVE'}),
+        isComponentRecommissionAvailable: false,
+        e: 'health-status-color-red icon-cog'
+      },
+      {
+        content: Em.Object.create({workStatus: App.HostComponentStatus.installing, passiveState: 'ACTIVE'}),
+        isComponentRecommissionAvailable: false,
+        e: 'health-status-color-blue icon-cog'
+      },
+      {
+        content: Em.Object.create({workStatus: 'STARTED', passiveState: 'PASSIVE'}),
+        isComponentRecommissionAvailable: false,
+        e: 'icon-medkit'
+      },
+      {
+        content: Em.Object.create({workStatus: 'STARTED', passiveState: 'IMPLIED'}),
+        isComponentRecommissionAvailable: false,
+        e: 'icon-medkit'
+      },
+      {
+        content: Em.Object.create({workStatus: 'STARTED', passiveState: 'ACTIVE'}),
+        isComponentRecommissionAvailable: false,
+        e: 'health-status-started'
+      },
+      {
+        content: Em.Object.create({workStatus: 'STARTED', passiveState: 'ACTIVE'}),
+        isComponentRecommissionAvailable: true,
+        e: 'health-status-DEAD-ORANGE'
+      },
+      {
+        content: Em.Object.create({workStatus: 'STARTING', passiveState: 'ACTIVE'}),
+        isComponentRecommissionAvailable: true,
+        e: 'health-status-DEAD-ORANGE'
+      },
+      {
+        content: Em.Object.create({workStatus: 'INSTALLED', passiveState: 'ACTIVE'}),
+        isComponentRecommissionAvailable: true,
+        e: 'health-status-DEAD-ORANGE'
+      }
+
+    ]);
+
+    tests.forEach(function(test) {
+      it(test.content.get('workStatus') + ' ' + test.content.get('passiveState') + ' ' + test.isComponentRecommissionAvailable?'true':'false', function() {
+        hostComponentView = App.HostComponentView.create(App.Decommissionable,{
+          startBlinking: function(){},
+          doBlinking: function(){},
+          getDesiredAdminState: function(){return $.ajax({});},
+          isComponentRecommissionAvailable: test.isComponentRecommissionAvailable,
+          content: test.content
+        });
+        expect(hostComponentView.get('statusClass')).to.equal(test.e);
+      });
+    });
+
+  });
+
+  describe('#isInProgress', function() {
+
+    var tests = Em.A([
+      {
+        workStatus: App.HostComponentStatus.stopping,
+        isDecommissioning: false,
+        e: true
+      },
+      {
+        workStatus: App.HostComponentStatus.starting,
+        isDecommissioning: false,
+        e: true
+      },
+      {
+        workStatus: 'other_status',
+        isDecommissioning: false,
+        e: false
+      },
+      {
+        workStatus: 'other_status',
+        isDecommissioning: true,
+        e: true
+      }
+    ]);
+
+    tests.forEach(function(test) {
+      it(test.workStatus + ' ' + test.isDecommissioning?'true':'false', function() {
+
+        hostComponentView = App.HostComponentView.create(App.Decommissionable,{
+          startBlinking: function(){},
+          doBlinking: function(){},
+          getDesiredAdminState: function(){return $.ajax({});},
+          isDecommissioning: test.isDecommissioning,
+          content: Em.Object.create({workStatus: test.workStatus})
+        });
+
+        expect(hostComponentView.get('isInProgress')).to.equal(test.e);
+      });
+    });
+
+  });
+
+});