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 2015/09/24 11:54:53 UTC

ambari git commit: AMBARI-13218 Web Client Expose Ability To Suspend and Resume Upgrade. (atkach)

Repository: ambari
Updated Branches:
  refs/heads/branch-2.1 c252681c6 -> 8d9430a77


AMBARI-13218 Web Client Expose Ability To Suspend and Resume Upgrade. (atkach)


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

Branch: refs/heads/branch-2.1
Commit: 8d9430a773107b644ac46ced61903745d9dc76e4
Parents: c252681
Author: Andrii Tkach <at...@hortonworks.com>
Authored: Thu Sep 24 12:47:28 2015 +0300
Committer: Andrii Tkach <at...@hortonworks.com>
Committed: Thu Sep 24 12:47:28 2015 +0300

----------------------------------------------------------------------
 ambari-web/app/app.js                           | 15 +++--
 .../main/admin/stack_and_upgrade_controller.js  | 49 ++++++++++++++-
 ambari-web/app/messages.js                      |  3 +
 ambari-web/app/models/upgrade_entity.js         |  5 +-
 ambari-web/app/templates/application.hbs        |  5 ++
 .../stack_upgrade/stack_upgrade_wizard.hbs      | 63 +++++++++++--------
 ambari-web/app/utils/db.js                      |  1 -
 ambari-web/app/utils/helper.js                  |  1 +
 .../stack_upgrade/upgrade_version_box_view.js   | 20 ++++--
 .../admin/stack_upgrade/upgrade_wizard_view.js  | 17 ++++-
 ambari-web/test/app_test.js                     | 60 ++++++++++++++++--
 .../admin/stack_and_upgrade_controller_test.js  | 66 ++++++++++++++++++++
 .../stack_upgrade/upgrade_wizard_view_test.js   | 17 ++++-
 13 files changed, 275 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/app/app.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/app.js b/ambari-web/app/app.js
index dfcfb95..63edd46 100644
--- a/ambari-web/app/app.js
+++ b/ambari-web/app/app.js
@@ -69,9 +69,9 @@ module.exports = Em.Application.create({
    * flag is true when upgrade process is aborted
    * @returns {boolean}
    */
-  upgradeAborted: function() {
-    return this.get('upgradeState') === "ABORTED";
-  }.property('upgradeState'),
+  upgradeAborted: function () {
+    return this.get('upgradeState') === "ABORTED" && !App.router.get('mainAdminStackAndUpgradeController.isSuspended');
+  }.property('upgradeState', 'router.mainAdminStackAndUpgradeController.isSuspended'),
 
   /**
    * RU is running
@@ -86,8 +86,8 @@ module.exports = Em.Application.create({
    * @returns {boolean}
    */
   upgradeIsNotFinished: function () {
-    return this.get('upgradeIsRunning') || this.get('upgradeAborted');
-  }.property('upgradeIsRunning', 'upgradeAborted'),
+    return this.get('upgradeIsRunning') || this.get('upgradeAborted') || App.router.get('mainAdminStackAndUpgradeController.isSuspended');
+  }.property('upgradeIsRunning', 'upgradeAborted', 'router.mainAdminStackAndUpgradeController.isSuspended'),
 
   /**
    * compute user access rights by permission type
@@ -101,7 +101,10 @@ module.exports = Em.Application.create({
    * @return {boolean}
    */
   isAccessible: function (type) {
-    if (!App.get('supports.opsDuringRollingUpgrade') && !['INIT', 'COMPLETED'].contains(this.get('upgradeState')) && !type.contains('upgrade_')) {
+    if (!App.router.get('mainAdminStackAndUpgradeController.isSuspended') &&
+        !App.get('supports.opsDuringRollingUpgrade') &&
+        !['INIT', 'COMPLETED'].contains(this.get('upgradeState')) &&
+        !type.contains('upgrade_')) {
       return false;
     }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js b/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
index 97910b7..880976f 100644
--- a/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
+++ b/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js
@@ -75,7 +75,7 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
   /**
    * properties that stored to localStorage to resume wizard progress
    */
-  wizardStorageProperties: ['upgradeId', 'upgradeVersion', 'currentVersion', 'isDowngrade'],
+  wizardStorageProperties: ['upgradeId', 'upgradeVersion', 'currentVersion', 'isDowngrade', 'isSuspended'],
 
   /**
    * mutable properties of Upgrade Task
@@ -153,6 +153,18 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
    */
   nonActiveStates: ['PENDING', 'ABORTED'],
 
+  /**
+   * status of Upgrade request
+   * @type {string}
+   */
+  requestStatus: function () {
+    if (this.get('isSuspended')) {
+      return 'SUSPENDED';
+    } else {
+      return App.get('upgradeState');
+    }
+  }.property('isSuspended', 'App.upgradeState'),
+
   init: function () {
     this.initDBProperties();
   },
@@ -987,5 +999,40 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
 
   loadRepositoriesErrorCallback: function (request, ajaxOptions, error) {
     console.log('Error message is: ' + request.responseText);
+  },
+
+  /**
+   * @returns {$.ajax}
+   */
+  suspendUpgrade: function () {
+    var self = this;
+    return this.abortUpgrade().done(function () {
+      App.set('upgradeState', 'ABORTED');
+      self.set('isSuspended', true);
+      self.setDBProperty('upgradeState', 'ABORTED');
+      self.setDBProperty('isSuspended', true);
+      App.clusterStatus.setClusterStatus({
+        wizardControllerName: self.get('name'),
+        localdb: App.db.data
+      });
+    });
+  },
+
+  /**
+   * @returns {$.ajax}
+   */
+  resumeUpgrade: function() {
+    var self = this;
+    this.retryUpgrade().done(function () {
+      App.set('upgradeState', 'PENDING');
+      App.propertyDidChange('upgradeAborted');
+      self.set('isSuspended', false);
+      self.setDBProperty('upgradeState', 'PENDING');
+      self.setDBProperty('isSuspended', false);
+      App.clusterStatus.setClusterStatus({
+        wizardControllerName: self.get('name'),
+        localdb: App.db.data
+      });
+    });
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 6d3b850..25c1672 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1440,6 +1440,7 @@ Em.I18n.translations = {
   'admin.stackVersions.version.upgrade.notFinalized.warning': "The upgrade has not been finalized yet. After the cluster is verified to be functional, do not forget to finalize the upgrade as soon as possible (within a couple of days is highly recommended) as running the cluster in unfinalized state causes extra resource requirements on HDFS.",
   'admin.stackVersions.version.upgrade.running': "Upgrade: In Process",
   'admin.stackVersions.version.upgrade.aborted': "Upgrade: Aborted",
+  'admin.stackVersions.version.upgrade.suspended': "Upgrade: Paused",
   'admin.stackVersions.version.downgrade.pause': "Downgrade: Action Required",
   'admin.stackVersions.version.downgrade.running': "Downgrade: In Process",
   'admin.stackVersions.version.downgrade.aborted': "Downgrade: Aborted",
@@ -1496,6 +1497,8 @@ Em.I18n.translations = {
   'admin.stackUpgrade.dialog.closePause': "Upgrade is paused. \n If you dismiss this window, you can resume Upgrade later.",
   'admin.stackUpgrade.dialog.aborted': "Upgrade is aborted. \n You can either downgrade or retry upgrade.",
   'admin.stackUpgrade.dialog.downgrade.aborted': "Downgrade is aborted. \n You can retry downgrade.",
+  'admin.stackUpgrade.dialog.suspended': "Upgrade is Paused",
+  'admin.stackUpgrade.dialog.resume': "Resume Upgrade",
   'admin.stackUpgrade.dialog.details.open': "show details",
   'admin.stackUpgrade.dialog.details.hide': "hide details",
   'admin.stackUpgrade.dialog.notActive': "Waiting to execute the next task...",

http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/app/models/upgrade_entity.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/upgrade_entity.js b/ambari-web/app/models/upgrade_entity.js
index 9c7f2d8..1733154 100644
--- a/ambari-web/app/models/upgrade_entity.js
+++ b/ambari-web/app/models/upgrade_entity.js
@@ -83,8 +83,11 @@ App.upgradeEntity = Em.Object.extend({
   }.property('isActive', 'hasExpandableItems'),
 
   upgradeGroupStatus: function () {
+    if (this.get('status') === 'ABORTED' && App.router.get('mainAdminStackAndUpgradeController.isSuspended')) {
+      return 'SUSPENDED';
+    }
     if (this.get('type') === 'GROUP') {
       return !this.get('isActive') && this.get('hasExpandableItems') ? 'SUBITEM_FAILED' : this.get('status');
     }
-  }.property('isExpandableGroup')
+  }.property('isExpandableGroup', 'App.router.mainAdminStackAndUpgradeController.isSuspended')
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/app/templates/application.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/application.hbs b/ambari-web/app/templates/application.hbs
index a72e3d6..586a0b7 100644
--- a/ambari-web/app/templates/application.hbs
+++ b/ambari-web/app/templates/application.hbs
@@ -139,6 +139,11 @@
                           <i class="icon-remove"></i>&nbsp;{{t admin.stackVersions.version.upgrade.aborted}}</span>
                     {{/if}}
                   {{/if}}
+                  {{#if App.router.mainAdminStackAndUpgradeController.isSuspended}}
+                      <span class="label upgrade-holding" {{action "openUpgradeDialog" target="App.router.mainAdminStackAndUpgradeController"}}>
+                          <i class="icon-pause"></i>&nbsp;{{t admin.stackVersions.version.upgrade.suspended}}
+                      </span>
+                  {{/if}}
                 </a>
                 </p>
                 {{#if App.router.mainAdminStackAndUpgradeController.isFinalizeItem}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_wizard.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_wizard.hbs b/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_wizard.hbs
index 7874175..f8c4d59 100644
--- a/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_wizard.hbs
+++ b/ambari-web/app/templates/main/admin/stack_upgrade/stack_upgrade_wizard.hbs
@@ -18,12 +18,12 @@
 
 <div id="stack-upgrade-dialog">
   <div {{bindAttr class="view.isLoaded::hidden :row-fluid"}}>
-    <div class="span3 task-list-main-warp">{{statusIcon controller.upgradeData.Upgrade.request_status}}
+    <div class="span3 task-list-main-warp">{{statusIcon controller.requestStatus}}
       &nbsp;{{view.upgradeStatusLabel}}</div>
     <div class="span8">
       {{view App.ProgressBarView
         progressBinding="view.overallProgress"
-        statusBinding="controller.upgradeData.Upgrade.request_status"
+        statusBinding="controller.requestStatus"
       }}
     </div>
     <div class="span1">
@@ -115,7 +115,7 @@
                 {{#if view.isDowngradeAvailable}}
                   <button class="btn btn-danger" {{bindAttr disabled="controller.requestInProgress"}} {{action confirmDowngrade view.manualItem target="controller"}}>{{t common.downgrade}}</button>
                 {{/if}}
-                <button class="btn" {{action closeWizard target="view.parentView"}}>{{t admin.stackUpgrade.finalize.later}}</button>
+                <button class="btn" {{action pauseUpgrade target="view"}}>{{t admin.stackUpgrade.finalize.later}}</button>
                 <button class="btn btn-success" {{bindAttr disabled="view.isManualProceedDisabled"}} {{action complete view.manualItem target="view"}}>
                   {{t common.finalize}}
                 </button>
@@ -153,30 +153,43 @@
             </div>
           </div>
         {{/if}}
-        {{#if App.upgradeAborted}}
-          {{#unless requestInProgress}}
-            <div class="box details-box">
-              <label class="message">
-                {{#if view.isDowngradeAvailable}}
-                  {{t admin.stackUpgrade.dialog.aborted}}
-                {{else}}
-                  {{t admin.stackUpgrade.dialog.downgrade.aborted}}
-                {{/if}}
-              </label>
-              <div class="button-row">
-                {{#if view.isDowngradeAvailable}}
+        {{#if isSuspended}}
+          <div class="box details-box">
+            <label class="message">
+              {{t admin.stackUpgrade.dialog.suspended}}
+            </label>
+            <div class="button-row">
+              <button class="btn btn-primary" {{action resumeUpgrade target="controller"}}>
+                {{t admin.stackUpgrade.dialog.resume}}
+              </button>
+            </div>
+          </div>
+        {{else}}
+          {{#if App.upgradeAborted}}
+            {{#unless requestInProgress}}
+              <div class="box details-box">
+                <label class="message">
+                    {{#if view.isDowngradeAvailable}}
+                      {{t admin.stackUpgrade.dialog.aborted}}
+                    {{else}}
+                      {{t admin.stackUpgrade.dialog.downgrade.aborted}}
+                    {{/if}}
+                </label>
+                <div class="button-row">
+                    {{#if view.isDowngradeAvailable}}
                   <button class="btn btn-danger" {{bindAttr disabled="controller.requestInProgress"}} {{action confirmDowngrade view.manualItem target="controller"}}>{{t common.downgrade}}</button>
-                {{/if}}
-                <button class="btn btn-success" {{action retryUpgrade target="controller"}}>
-                  {{#if view.isDowngradeAvailable}}
-                    {{t common.reUpgrade}}
-                  {{else}}
-                    {{t common.reDowngrade}}
-                  {{/if}}
-                </button>
+                    {{/if}}
+                    <button class="btn btn-success" {{action retryUpgrade target="controller"}}>
+                      {{#if view.isDowngradeAvailable}}
+                        {{t common.reUpgrade}}
+                      {{else}}
+                        {{t common.reDowngrade}}
+                      {{/if}}
+                    </button>
+                </div>
               </div>
-            </div>
-          {{/unless}}
+            {{/unless}}
+          {{/if}}
         {{/if}}
       </div>
       {{#each group in view.upgradeGroups}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/app/utils/db.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/db.js b/ambari-web/app/utils/db.js
index 495f360..d90f46a 100644
--- a/ambari-web/app/utils/db.js
+++ b/ambari-web/app/utils/db.js
@@ -36,7 +36,6 @@ var InitialData =  {
   'AddService' : {},
   'WidgetWizard' : {},
   'KerberosWizard': {},
-  'StackUpgrade' : {},
   'ReassignMaster' : {},
   'AddSecurity': {},
   'AddAlertDefinition': {

http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/app/utils/helper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/helper.js b/ambari-web/app/utils/helper.js
index f777ee6..7ced41d 100644
--- a/ambari-web/app/utils/helper.js
+++ b/ambari-web/app/utils/helper.js
@@ -814,6 +814,7 @@ App.registerBoundHelper('statusIcon', Em.View.extend({
     'QUEUED': 'icon-cog queued',
     'IN_PROGRESS': 'icon-cogs in_progress',
     'HOLDING': 'icon-pause',
+    'SUSPENDED': 'icon-pause',
     'ABORTED': 'icon-minus aborted',
     'TIMEDOUT': 'icon-time timedout',
     'HOLDING_TIMEDOUT': 'icon-time timedout',

http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js
index ed9c53b..2248150 100644
--- a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js
+++ b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js
@@ -125,6 +125,7 @@ App.UpgradeVersionBoxView = Em.View.extend({
     });
     var isInstalling = this.get('parentView.repoVersions').someProperty('status', 'INSTALLING');
     var isAborted = App.get('upgradeState') === 'ABORTED';
+    var isSuspended = App.router.get('mainAdminStackAndUpgradeController.isSuspended');
 
     if (status === 'CURRENT') {
       element.set('isLabel', true);
@@ -187,10 +188,17 @@ App.UpgradeVersionBoxView = Em.View.extend({
       }
     }
     else if (isAborted) {
-      element.set('isButton', true);
-      element.set('text', this.get('controller.isDowngrade') ? Em.I18n.t('common.reDowngrade') : Em.I18n.t('common.reUpgrade'));
-      element.set('action', this.get('controller.isDowngrade') ? 'confirmRetryDowngrade' : 'confirmRetryUpgrade');
-      element.set('isDisabled', this.get('controller.requestInProgress'));
+      if (isSuspended) {
+        element.set('isButton', true);
+        element.set('text', Em.I18n.t('admin.stackUpgrade.dialog.resume'));
+        element.set('action', 'resumeUpgrade');
+        element.set('isDisabled', this.get('controller.requestInProgress'));
+      } else {
+        element.set('isButton', true);
+        element.set('text', this.get('controller.isDowngrade') ? Em.I18n.t('common.reDowngrade') : Em.I18n.t('common.reUpgrade'));
+        element.set('action', this.get('controller.isDowngrade') ? 'confirmRetryDowngrade' : 'confirmRetryUpgrade');
+        element.set('isDisabled', this.get('controller.requestInProgress'));
+      }
     }
     return element;
   }.property(
@@ -199,7 +207,9 @@ App.UpgradeVersionBoxView = Em.View.extend({
     'isUpgrading',
     'controller.requestInProgress',
     'parentView.repoVersions.@each.status',
-    'isUpgradeAvailable'),
+    'isUpgradeAvailable',
+    'App.router.mainAdminStackAndUpgradeController.isSuspended'
+  ),
 
   didInsertElement: function () {
     this.checkUpgradeAvailability();

http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js
index fde7906..6d79514 100644
--- a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js
+++ b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_wizard_view.js
@@ -183,7 +183,7 @@ App.upgradeWizardView = Em.View.extend({
    */
   upgradeStatusLabel: function() {
     var labelKey = null;
-    switch (this.get('controller.upgradeData.Upgrade.request_status')) {
+    switch (App.get('upgradeState')) {
       case 'QUEUED':
       case 'PENDING':
       case 'IN_PROGRESS':
@@ -193,7 +193,11 @@ App.upgradeWizardView = Em.View.extend({
         labelKey = 'admin.stackUpgrade.state.completed';
         break;
       case 'ABORTED':
-        labelKey = 'admin.stackUpgrade.state.aborted';
+        if (this.get('controller.isSuspended')) {
+          labelKey = 'admin.stackUpgrade.state.paused';
+        } else {
+          labelKey = 'admin.stackUpgrade.state.aborted';
+        }
         break;
       case 'TIMEDOUT':
       case 'FAILED':
@@ -209,7 +213,7 @@ App.upgradeWizardView = Em.View.extend({
     } else {
       return "";
     }
-  }.property('controller.upgradeData.Upgrade.request_status', 'controller.isDowngrade'),
+  }.property('App.upgradeState', 'controller.isDowngrade', 'controller.isSuspended'),
 
   /**
    * toggle details box
@@ -353,5 +357,12 @@ App.upgradeWizardView = Em.View.extend({
   complete: function (event) {
     this.get('controller').setUpgradeItemStatus(event.context, 'COMPLETED');
     this.set('isManualDone', false);
+  },
+
+  pauseUpgrade: function() {
+    if (this.get('isFinalizeItem')) {
+      this.get('controller').suspendUpgrade();
+    }
+    this.get('parentView').closeWizard();
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/test/app_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/app_test.js b/ambari-web/test/app_test.js
index 416f3af..dd58d46 100644
--- a/ambari-web/test/app_test.js
+++ b/ambari-web/test/app_test.js
@@ -399,6 +399,14 @@ describe('App', function () {
   });
 
   describe("#isAccessible()", function() {
+
+    beforeEach(function () {
+      this.mock = sinon.stub(App.router, 'get');
+    });
+    afterEach(function () {
+      this.mock.restore();
+    });
+
     it("Upgrade running, element should be blocked", function() {
       App.set('upgradeState', "IN_PROGRESS");
       App.set('isAdmin', true);
@@ -475,6 +483,13 @@ describe('App', function () {
       App.set('upgradeState', "INIT");
       expect(App.isAccessible('')).to.be.false;
     });
+    it("ONLY_ADMIN type, isAdmin true, isOperator true, isSuspended true", function() {
+      App.set('upgradeState', "ABORTED");
+      App.set('isAdmin', true);
+      App.set('isOperator', false);
+      this.mock.returns(true);
+      expect(App.isAccessible('ONLY_ADMIN')).to.be.true;
+    });
   });
 
   describe('#isHadoop20Stack', function () {
@@ -561,44 +576,81 @@ describe('App', function () {
     var cases = [
       {
         upgradeState: 'INIT',
+        isSuspended: false,
+        upgradeAborted: false
+      },
+      {
+        upgradeState: 'INIT',
+        isSuspended: true,
+        upgradeAborted: false
+      },
+      {
+        upgradeState: 'ABORTED',
+        isSuspended: true,
         upgradeAborted: false
       },
       {
         upgradeState: 'ABORTED',
+        isSuspended: false,
         upgradeAborted: true
       }
     ];
 
+    beforeEach(function () {
+      this.mock = sinon.stub(App.router, 'get');
+    });
+    afterEach(function () {
+      this.mock.restore();
+    });
+
     cases.forEach(function (item) {
-      it(item.upgradeState, function () {
+      it(item.upgradeState + ", " + item.isSuspended, function () {
+        this.mock.returns(item.isSuspended);
         App.set('upgradeState', item.upgradeState);
+        App.propertyDidChange('upgradeAborted');
         expect(App.get('upgradeAborted')).to.equal(item.upgradeAborted);
       });
     });
-
   });
 
   describe('#upgradeIsNotFinished', function () {
 
+    beforeEach(function () {
+      this.mock = sinon.stub(App.router, 'get');
+    });
+    afterEach(function () {
+      this.mock.restore();
+    });
+
     var cases = [
       {
         upgradeState: 'INIT',
+        isSuspended: false,
         upgradeIsNotFinished: false
       },
       {
         upgradeState: 'IN_PROGRESS',
+        isSuspended: false,
         upgradeIsNotFinished: true
       },
       {
         upgradeState: 'HOLDING',
+        isSuspended: false,
         upgradeIsNotFinished: true
       },
       {
         upgradeState: 'HOLDING_TIMEDOUT',
+        isSuspended: false,
         upgradeIsNotFinished: true
       },
       {
         upgradeState: 'ABORTED',
+        isSuspended: false,
+        upgradeIsNotFinished: true
+      },
+      {
+        upgradeState: 'ABORTED',
+        isSuspended: true,
         upgradeIsNotFinished: true
       }
     ];
@@ -606,10 +658,10 @@ describe('App', function () {
     cases.forEach(function (item) {
       it(item.upgradeState, function () {
         App.set('upgradeState', item.upgradeState);
+        this.mock.returns(item.isSuspended);
+        App.propertyDidChange('upgradeIsNotFinished');
         expect(App.get('upgradeIsNotFinished')).to.equal(item.upgradeIsNotFinished);
       });
     });
-
   });
-
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js b/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js
index e0e2ff0..b034ac4 100644
--- a/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js
+++ b/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js
@@ -73,6 +73,21 @@ describe('App.MainAdminStackAndUpgradeController', function() {
     });
   });
 
+  describe("#requestStatus", function() {
+    it("isSuspended false", function() {
+      App.set('upgradeState', 'ABORTED');
+      controller.set('isSuspended', false);
+      controller.propertyDidChange('requestStatus');
+      expect(controller.get('requestStatus')).to.equal('ABORTED');
+    });
+    it("isSuspended true", function() {
+      App.set('upgradeState', 'ABORTED');
+      controller.set('isSuspended', true);
+      controller.propertyDidChange('requestStatus');
+      expect(controller.get('requestStatus')).to.equal('SUSPENDED');
+    });
+  });
+
   describe("#load()", function() {
     before(function(){
       sinon.stub(controller, 'loadUpgradeData').returns({
@@ -1215,4 +1230,55 @@ describe('App.MainAdminStackAndUpgradeController', function() {
 
   });
 
+  describe("#suspendUpgrade()", function() {
+    beforeEach(function () {
+      sinon.stub(controller, 'abortUpgrade').returns({
+        done: function (callback) {
+          callback();
+        }
+      });
+      sinon.stub(controller, 'setDBProperty', Em.K);
+      sinon.stub(App.clusterStatus, 'setClusterStatus', Em.K);
+    });
+    afterEach(function () {
+      controller.abortUpgrade.restore();
+      controller.setDBProperty.restore();
+      App.clusterStatus.setClusterStatus.restore();
+    });
+    it("", function() {
+      controller.suspendUpgrade();
+      expect(controller.abortUpgrade.calledOnce).to.be.true;
+      expect(App.get('upgradeState')).to.equal('ABORTED');
+      expect(controller.get('isSuspended')).to.be.true;
+      expect(controller.setDBProperty.calledWith('upgradeState', 'ABORTED')).to.be.true;
+      expect(controller.setDBProperty.calledWith('isSuspended', true)).to.be.true;
+      expect(App.clusterStatus.setClusterStatus.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#resumeUpgrade()", function() {
+    beforeEach(function () {
+      sinon.stub(controller, 'retryUpgrade').returns({
+        done: function (callback) {
+          callback();
+        }
+      });
+      sinon.stub(controller, 'setDBProperty', Em.K);
+      sinon.stub(App.clusterStatus, 'setClusterStatus', Em.K);
+    });
+    afterEach(function () {
+      controller.retryUpgrade.restore();
+      controller.setDBProperty.restore();
+      App.clusterStatus.setClusterStatus.restore();
+    });
+    it("", function() {
+      controller.resumeUpgrade();
+      expect(controller.retryUpgrade.calledOnce).to.be.true;
+      expect(App.get('upgradeState')).to.equal('PENDING');
+      expect(controller.get('isSuspended')).to.be.false;
+      expect(controller.setDBProperty.calledWith('upgradeState', 'PENDING')).to.be.true;
+      expect(controller.setDBProperty.calledWith('isSuspended', false)).to.be.true;
+      expect(App.clusterStatus.setClusterStatus.calledOnce).to.be.true;
+    });
+  });
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/8d9430a7/ambari-web/test/views/main/admin/stack_upgrade/upgrade_wizard_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_wizard_view_test.js b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_wizard_view_test.js
index b762500..69e8665 100644
--- a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_wizard_view_test.js
+++ b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_wizard_view_test.js
@@ -448,6 +448,12 @@ describe('App.upgradeWizardView', function () {
   });
 
   describe("#upgradeStatusLabel", function () {
+    beforeEach(function () {
+      this.mock = sinon.stub(App, 'get');
+    });
+    afterEach(function () {
+      this.mock.restore();
+    });
     var testCases = [
       {
         data: {
@@ -563,6 +569,14 @@ describe('App.upgradeWizardView', function () {
       },
       {
         data: {
+          status: 'ABORTED',
+          isDowngrade: false,
+          isSuspended: true
+        },
+        result: Em.I18n.t('admin.stackUpgrade.state.paused')
+      },
+      {
+        data: {
           status: 'TIMEDOUT',
           isDowngrade: true
         },
@@ -598,8 +612,9 @@ describe('App.upgradeWizardView', function () {
       }
     ].forEach(function (test) {
         it('status = ' + test.data.status + ", isDowngrade = " + test.data.isDowngrade, function () {
-          view.set('controller.upgradeData.Upgrade.request_status', test.data.status);
           view.set('controller.isDowngrade', test.data.isDowngrade);
+          view.set('controller.isSuspended', test.data.isSuspended);
+          this.mock.returns(test.data.status);
           view.propertyDidChange('upgradeStatusLabel');
           expect(view.get('upgradeStatusLabel')).to.equal(test.result);
         });