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 2018/08/01 12:28:56 UTC

[ambari] branch trunk updated: AMBARI-24120 cluster version is in invalid state

This is an automated email from the ASF dual-hosted git repository.

atkach pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new e7771e0  AMBARI-24120 cluster version is in invalid state
e7771e0 is described below

commit e7771e0039618a8b779d2e22f910617f6d8c9dec
Author: Andrii Tkach <at...@apache.org>
AuthorDate: Wed Aug 1 13:23:02 2018 +0300

    AMBARI-24120 cluster version is in invalid state
---
 .../main/admin/stack_and_upgrade_controller.js     | 103 +++++++++++++++++++++
 ambari-web/app/messages.js                         |   9 +-
 .../app/models/stack_version/repository_version.js |   4 +
 ambari-web/app/styles/stack_versions.less          |  29 +++++-
 .../admin/stack_upgrade/upgrade_version_box.hbs    |   3 +
 .../admin/stack_upgrade/upgrade_version_column.hbs |  21 +----
 .../main/admin/stack_upgrade/versions.hbs          |  27 ++++++
 .../stack_upgrade/upgrade_version_box_view.js      |  44 +++++++--
 .../main/admin/stack_upgrade/versions_view.js      |  16 ++++
 .../admin/stack_and_upgrade_controller_test.js     |  63 +++++++++++++
 .../stack_upgrade/upgrade_version_box_view_test.js |  13 ++-
 11 files changed, 299 insertions(+), 33 deletions(-)

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 0a62f50..ac04c88 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
@@ -1599,6 +1599,109 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage,
       }
     });
   },
+  
+  /**
+   * TODO unify and move modal view into common/modal_popups
+   * @param {string[]} hosts
+   * @param {string} title
+   * @param {string} operation
+   * @param {Function} primary
+   */
+  showReinstallRemoveConfirmation: function({hosts, title, operation, primary = () => {}}) {
+    return App.ModalPopup.show({
+      header: title,
+      visibleHosts: hosts.join("\n"),
+      expanded: true,
+      onPrimary: function() {
+        primary(hosts);
+        this._super();
+      },
+    
+      bodyClass: Em.View.extend({
+        templateName: require('templates/main/host/bulk_operation_confirm_popup'),
+        message: Em.I18n.t('hosts.bulkOperation.confirmation.hosts').format(operation, hosts.length),
+        textareaVisible: false,
+        textTrigger: function() {
+          this.toggleProperty('textareaVisible');
+        },
+        putHostNamesToTextarea: function() {
+          var hostNames = this.get('parentView.visibleHosts');
+          if (this.get('textareaVisible')) {
+            var wrapper = $(".task-detail-log-maintext");
+            $('.task-detail-log-clipboard').html(hostNames).width(wrapper.width()).height(250);
+            Em.run.next(function() {
+              $('.task-detail-log-clipboard').select();
+            });
+          }
+        }.observes('textareaVisible')
+      })
+    });
+  },
+  
+  removeOutOfSyncComponents: function (event) {
+    const hosts = App.RepositoryVersion.find(event.context.repoId).get('stackVersion.outOfSyncHosts');
+    return this.showReinstallRemoveConfirmation({
+      hosts,
+      title: Em.I18n.t('admin.stackVersions.version.errors.outOfSync.remove.title'),
+      operation: Em.I18n.t('hosts.host.maintainance.removeFailedComponents.context'),
+      primary: () => {
+        App.get('router.mainAdminKerberosController').getKDCSessionState(() => {
+          App.ajax.send({
+            name: 'host.host_component.delete_components',
+            sender: this,
+            data: {
+              hosts,
+              data: JSON.stringify({
+                RequestInfo: {
+                  query: 'HostRoles/host_name.in(' + hosts.join(',') + ')&HostRoles/state=INSTALL_FAILED'
+                }
+              })
+            }
+          });
+        });
+      }
+    });
+  },
+  
+  reinstallOutOfSyncComponents: function (event) {
+    const hosts = App.RepositoryVersion.find(event.context.repoId).get('stackVersion.outOfSyncHosts');
+    return this.showReinstallRemoveConfirmation({
+      hosts,
+      title: Em.I18n.t('admin.stackVersions.version.errors.outOfSync.reinstall.title'),
+      operation: Em.I18n.t('hosts.host.maintainance.reinstallFailedComponents.context'),
+      primary: () => {
+        App.get('router.mainAdminKerberosController').getKDCSessionState(() => {
+          App.ajax.send({
+            name: 'common.host_components.update',
+            sender: this,
+            data: {
+              HostRoles: {
+                state: 'INSTALLED'
+              },
+              query: 'HostRoles/host_name.in(' + hosts.join(',') + ')&HostRoles/state=INSTALL_FAILED',
+              context: Em.I18n.t('hosts.host.maintainance.reinstallFailedComponents.context')
+            },
+            success: 'reinstallOutOfSyncComponentsSuccessCallback'
+          });
+        });
+      }
+    });
+  },
+  
+  reinstallOutOfSyncComponentsSuccessCallback: function (data, opt, params, req) {
+    if (!data && req.status == 200) {
+      return App.ModalPopup.show({
+        header: Em.I18n.t('rolling.nothingToDo.header'),
+        body: Em.I18n.t('rolling.nothingToDo.body').format(params.noOpsMessage || Em.I18n.t('hosts.host.maintainance.allComponents.context')),
+        secondary: false
+      });
+    }
+    return App.router.get('userSettingsController').dataLoading('show_bg').done(function (initValue) {
+      if (initValue) {
+        App.router.get('backgroundOperationsController').showPopup();
+      }
+    });
+  },
 
   /**
    * transform repo data into json for
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index d55a224..6883dc5 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1830,6 +1830,7 @@ Em.I18n.translations = {
     ' “Go to Dashboard” link in the Ambari Administration > Clusters section.',
   'admin.stackVersions.version.installNow': "Install Packages",
   'admin.stackVersions.version.reinstall': "Reinstall Packages",
+  'admin.stackVersions.version.installError': "Installation Error!",
   'admin.stackVersions.version.performUpgrade': "Perform Upgrade",
   'admin.stackVersions.version.preUpgradeCheck': 'Pre-Upgrade Check',
   'admin.stackVersions.version.upgrade.pause': "Upgrade: Action Required",
@@ -1847,7 +1848,12 @@ Em.I18n.translations = {
   'admin.stackUpgrade.state.paused.fail.body': "Upgrade could not be paused. Try again later.",
   'admin.stackDowngrade.state.paused.fail.header': "Pause Downgrade failed",
   'admin.stackDowngrade.state.paused.fail.body': "Downgrade could not be paused. Try again later.",
-
+  'admin.stackVersions.version.errors.outOfSync.title': 'Host component out of sync',
+  'admin.stackVersions.version.errors.outOfSync.desc': 'One of more host components did not report the version that Ambari expected.' +
+  ' Please re-install the failed host component, or remove it.',
+  'admin.stackVersions.version.errors.outOfSync.reinstall.title': 'Confirm Re-Install',
+  'admin.stackVersions.version.errors.outOfSync.remove.title': 'Confirm Remove',
+  
   'admin.stackVersions.version.service.notUpgradable': "The version of this service included in this repository is already installed in the cluster.",
   'admin.stackVersions.version.service.notSupported': "This service is unsupported in the current version of the stack.",
 
@@ -2883,6 +2889,7 @@ Em.I18n.translations = {
   'hosts.host.maintainance.stopAllComponents.context': 'Stop All Host Components',
   'hosts.host.maintainance.startAllComponents.context': 'Start All Host Components',
   'hosts.host.maintainance.reinstallFailedComponents.context': 'Reinstall Failed Components',
+  'hosts.host.maintainance.removeFailedComponents.context': 'Remove Failed Components',
   'hosts.host.recover.initAllComponents.context': 'Init All Host Components',
   'hosts.host.recover.installAllComponents.context': 'Install All Host Components',
   'hosts.host.recover.regenerateKeytabs.context': 'Regenerate keytabs',
diff --git a/ambari-web/app/models/stack_version/repository_version.js b/ambari-web/app/models/stack_version/repository_version.js
index d40b4f2..8a72ca4 100644
--- a/ambari-web/app/models/stack_version/repository_version.js
+++ b/ambari-web/app/models/stack_version/repository_version.js
@@ -34,6 +34,10 @@ App.RepositoryVersion = DS.Model.extend({
   displayNameSimple: function() {
     return this.get('stackVersionType') + '-' + this.get('repositoryVersion').split('-')[0];
   }.property('stackVersionType', 'repositoryVersion'),
+  
+  displayNameFull: function() {
+    return this.get('stackVersionType') + '-' + this.get('repositoryVersion');
+  }.property('stackVersionType', 'repositoryVersion'),
 
   isPatch: Em.computed.equal('type', 'PATCH'),
 
diff --git a/ambari-web/app/styles/stack_versions.less b/ambari-web/app/styles/stack_versions.less
index e40484d..72a1897 100644
--- a/ambari-web/app/styles/stack_versions.less
+++ b/ambari-web/app/styles/stack_versions.less
@@ -220,6 +220,9 @@
       i[disabled='disabled'] {
         color: inherit;
       }
+      i.glyphicon-warning-sign {
+        color: @health-status-red;
+      }
       .label {
         padding: 5px 20px;
         font-size: 14px;
@@ -357,7 +360,8 @@
         }
       }
       .btn.btn-primary:not(.dropdown-toggle) {
-        padding: 4px 5px;
+        padding-left: 5px;
+        padding-right: 5px;
         min-width: 70px;
       }
       .open .dropdown-menu {
@@ -410,6 +414,29 @@
   .nav.nav-tabs {
     margin-bottom: 20px;
   }
+  .stack-error-row {
+    .image-container {
+      display: inline-block;
+      vertical-align: top;
+      margin-top: 5px;
+      margin-right: 15px;
+      i {
+        vertical-align: middle;
+        font-size: 22px;
+      }
+    }
+    .message-container {
+      display: inline-block;
+      max-width: 70%;
+    }
+    .stack-name {
+      margin-left: 15px;
+    }
+    .btn-container {
+      line-height: 36px;
+      float: right;
+    }
+  }
 }
 
 .install-repo-confirmation,
diff --git a/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_box.hbs b/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_box.hbs
index d40483d..8f74f98 100644
--- a/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_box.hbs
+++ b/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_box.hbs
@@ -71,6 +71,9 @@
     </div>
   {{/if}}
   {{#if view.stateElement.isLabel}}
+    {{#if view.stateElement.iconClass}}
+      <i {{bindAttr class="view.stateElement.iconClass" disabled="view.stateElement.isDisabled"}}></i>
+    {{/if}}
     <span {{bindAttr class="view.stateElement.class"}}>{{view.stateElement.text}}</span>
   {{/if}}
   {{#if view.stateElement.isLink}}
diff --git a/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_column.hbs b/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_column.hbs
index 967a3ec..c0bcac0 100644
--- a/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_column.hbs
+++ b/ambari-web/app/templates/main/admin/stack_upgrade/upgrade_version_column.hbs
@@ -77,23 +77,10 @@
     </div>
   {{/if}}
   {{#if view.stateElement.isLabel}}
-    <div {{bindAttr class="view.stateElement.canBeReverted:btn-group :label-wrapper"}}>
-      <button {{bindAttr class="view.stateElement.class"}}>
-        <span class="state-label-text">{{view.stateElement.text}}</span>
-      </button>
-      {{#if view.stateElement.canBeReverted}}
-        <button {{bindAttr class="view.stateElement.class :dropdown-toggle"}} data-toggle="dropdown">
-          <span class="caret"></span>
-        </button>
-        <ul class="dropdown-menu">
-          <li>
-            <a {{action runAction view.stateElement.action target="view"}}>
-              {{view.stateElement.actionText}}
-            </a>
-          </li>
-        </ul>
-      {{/if}}
-    </div>
+    {{#if view.stateElement.iconClass}}
+      <i {{bindAttr class="view.stateElement.iconClass" disabled="view.stateElement.isDisabled"}}></i>
+    {{/if}}
+    <span {{bindAttr class="view.stateElement.class"}}>{{view.stateElement.text}}</span>
   {{/if}}
   {{#if view.stateElement.isLink}}
     {{#if view.stateElement.iconClass}}
diff --git a/ambari-web/app/templates/main/admin/stack_upgrade/versions.hbs b/ambari-web/app/templates/main/admin/stack_upgrade/versions.hbs
index b8c0761..a0f4d35 100644
--- a/ambari-web/app/templates/main/admin/stack_upgrade/versions.hbs
+++ b/ambari-web/app/templates/main/admin/stack_upgrade/versions.hbs
@@ -16,6 +16,33 @@
 * limitations under the License.
 }}
 
+{{#if view.stackVersionError}}
+  <div class="alert alert-warning" role="alert">
+    <div class="stack-error-row">
+      <div class="image-container">
+        <i class="glyphicon glyphicon-warning-sign"></i>
+      </div>
+      <div class="message-container">
+        <h4 class="display-inline">{{view.stackVersionError.title}}</h4>
+        <span class="stack-name">{{view.stackVersionError.stack}}</span>
+        <div>
+          {{view.stackVersionError.description}}
+        </div>
+      </div>
+      {{#havePermissions "AMBARI.MANAGE_STACK_VERSIONS"}}
+        <div class="btn-container">
+          <button class="btn btn-warning" {{action reinstallOutOfSyncComponents view.stackVersionError target="controller"}}>
+            {{t common.reinstall}}
+          </button>
+          <button class="btn btn-warning" {{action removeOutOfSyncComponents view.stackVersionError target="controller"}}>
+            {{t common.remove}}
+          </button>
+        </div>
+      {{/havePermissions}}
+    </div>
+  </div>
+{{/if}}
+
 <div id="versions-filter-section" class="btn-toolbar">
   {{#havePermissions "AMBARI.MANAGE_STACK_VERSIONS"}}
     <button class="btn btn-primary" {{action goToVersions target="view"}}  {{bindAttr disabled="App.router.wizardWatcherController.isNonWizardUser"}} id="manage-versions-link">
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 a52d3c6..83bf7aa 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
@@ -151,6 +151,17 @@ App.UpgradeVersionBoxView = Em.View.extend({
         isLabel: true,
         text: Em.I18n.t('common.current'),
         class: this.get('currentLabelClass')
+      },
+      'CURRENT_PATCH_REVERTABLE': {
+        isButtonGroup: true,
+        text: Em.I18n.t('common.current'),
+        action: null,
+        buttons: [
+          {
+            text: Em.I18n.t('common.revert'),
+            action: 'confirmRevertPatchUpgrade'
+          }
+        ]
       }
     };
   }.property(),
@@ -172,10 +183,11 @@ App.UpgradeVersionBoxView = Em.View.extend({
     var isSuspended = App.get('upgradeSuspended');
 
     if (status === 'CURRENT' && this.get('content.isPatch') && !this.get('isUpgrading')) {
-      element.setProperties(statePropertiesMap['CURRENT_PATCH']);
-      element.set('canBeReverted', this.get('content.stackVersion').get('supportsRevert'));
-      element.set('action', 'confirmRevertPatchUpgrade');
-      element.set('actionText', Em.I18n.t('common.revert'));
+      if (this.get('content.stackVersion.supportsRevert')) {
+        element.setProperties(statePropertiesMap['CURRENT_PATCH_REVERTABLE']);
+      } else {
+        element.setProperties(statePropertiesMap['CURRENT_PATCH']);
+      }
     }
     else if (['INSTALLING', 'CURRENT'].contains(status)) {
       element.setProperties(statePropertiesMap[status]);
@@ -271,14 +283,26 @@ App.UpgradeVersionBoxView = Em.View.extend({
     if (Em.get(currentVersion, 'stack_name') !== this.get('content.stackVersionType') || isVersionHigherThanCurrent) {
       switch (status){
         case 'OUT_OF_SYNC':
-          element.set('isButton', true);
-          element.set('text', this.get('isVersionColumnView') ? Em.I18n.t('common.reinstall') : Em.I18n.t('admin.stackVersions.version.reinstall'));
-          element.set('action', 'installRepoVersionPopup');
+          if (Em.isNone(currentVersion)) {
+            element.set('text', Em.I18n.t('admin.stackVersions.version.installError'));
+            element.set('iconClass', 'glyphicon glyphicon-warning-sign');
+            element.set('isLabel', true);
+          } else {
+            element.set('isButton', true);
+            element.set('text', this.get('isVersionColumnView') ? Em.I18n.t('common.reinstall') : Em.I18n.t('admin.stackVersions.version.reinstall'));
+            element.set('action', 'installRepoVersionPopup');
+          }
           break;
         case 'INSTALL_FAILED':
-          element.set('isButton', true);
-          element.set('text', this.get('isVersionColumnView') ? Em.I18n.t('common.reinstall') : Em.I18n.t('admin.stackVersions.version.reinstall'));
-          element.set('action', 'installRepoVersionPopup');
+          if (Em.isNone(currentVersion)) {
+            element.set('text', Em.I18n.t('admin.stackVersions.version.installError'));
+            element.set('iconClass', 'glyphicon glyphicon-warning-sign');
+            element.set('isLabel', true);
+          } else {
+            element.set('isButton', true);
+            element.set('text', this.get('isVersionColumnView') ? Em.I18n.t('common.reinstall') : Em.I18n.t('admin.stackVersions.version.reinstall'));
+            element.set('action', 'installRepoVersionPopup');
+          }
           break;
         default:
           var isVersionColumnView = this.get('isVersionColumnView');
diff --git a/ambari-web/app/views/main/admin/stack_upgrade/versions_view.js b/ambari-web/app/views/main/admin/stack_upgrade/versions_view.js
index 83203bb..0d4ad83 100644
--- a/ambari-web/app/views/main/admin/stack_upgrade/versions_view.js
+++ b/ambari-web/app/views/main/admin/stack_upgrade/versions_view.js
@@ -139,6 +139,22 @@ App.MainAdminStackVersionsView = Em.View.extend({
    * @type {Em.Array}
    */
   stackVersions: App.StackVersion.find(),
+  
+  /**
+   * @type {?Em.Object}
+   */
+  stackVersionError: function() {
+    const errorStack = this.get('repoVersions').filterProperty('status', 'OUT_OF_SYNC').findProperty('isStandard');
+    if (errorStack) {
+      return Em.Object.create({
+        repoId: errorStack.get('id'),
+        title: Em.I18n.t('admin.stackVersions.version.errors.outOfSync.title'),
+        description: Em.I18n.t('admin.stackVersions.version.errors.outOfSync.desc'),
+        stack: errorStack.get('displayNameFull')
+      })
+    }
+    return null;
+  }.property('repoVersions.@each.status'),
 
   /**
    * filter versions by category
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 019977c..cd67340 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
@@ -3785,4 +3785,67 @@ describe('App.MainAdminStackAndUpgradeController', function() {
       expect( controller.get('runningCheckRequests')).to.have.length(1);
     })
   });
+  
+  describe('#removeOutOfSyncComponents', function() {
+    beforeEach(function() {
+      sinon.stub(App.RepositoryVersion, 'find').returns(Em.Object.create({
+        stackVersion: {
+          outOfSyncHosts: ['host1']
+        }
+      }));
+      sinon.stub(App, 'get').returns({
+        getKDCSessionState: Em.clb
+      });
+    });
+    afterEach(function() {
+      App.RepositoryVersion.find.restore();
+      App.get.restore();
+    });
+    
+    it('App.ajax.send should be called', function() {
+      var modal = controller.removeOutOfSyncComponents({context: {repoId: 1}});
+      modal.onPrimary();
+      var args = testHelpers.findAjaxRequest('name', 'host.host_component.delete_components');
+      expect(args[0]).to.exists;
+      expect(args[0].data).to.be.eql({
+        hosts: ['host1'],
+        data: JSON.stringify({
+          RequestInfo: {
+            query: 'HostRoles/host_name.in(host1)&HostRoles/state=INSTALL_FAILED'
+          }
+        })
+      });
+    });
+  });
+  
+  describe('#reinstallOutOfSyncComponents', function() {
+    beforeEach(function() {
+      sinon.stub(App.RepositoryVersion, 'find').returns(Em.Object.create({
+        stackVersion: {
+          outOfSyncHosts: ['host1']
+        }
+      }));
+      sinon.stub(App, 'get').returns({
+        getKDCSessionState: Em.clb
+      });
+    });
+    afterEach(function() {
+      App.RepositoryVersion.find.restore();
+      App.get.restore();
+    });
+    
+    it('App.ajax.send should be called', function() {
+      var modal = controller.reinstallOutOfSyncComponents({context: {repoId: 1}});
+      modal.onPrimary();
+      var args = testHelpers.findAjaxRequest('name', 'common.host_components.update');
+      expect(args[0]).to.exists;
+      expect(args[0].data).to.be.eql({
+        HostRoles: {
+          state: 'INSTALLED'
+        },
+        query: 'HostRoles/host_name.in(host1)&HostRoles/state=INSTALL_FAILED',
+        context: Em.I18n.t('hosts.host.maintainance.reinstallFailedComponents.context')
+      });
+    });
+  });
 });
diff --git a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_box_view_test.js b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_box_view_test.js
index 9bee7af..a5d4377 100644
--- a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_box_view_test.js
+++ b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_box_view_test.js
@@ -463,8 +463,7 @@ describe('App.UpgradeVersionBoxView', function () {
         expected: {
           isLabel: true,
           text: Em.I18n.t('common.current'),
-          class: 'label label-success',
-          canBeReverted: false
+          class: 'label label-success'
         },
         title: 'current no-revertable patch version'
       },
@@ -478,9 +477,15 @@ describe('App.UpgradeVersionBoxView', function () {
           })
         },
         expected: {
-          status: 'CURRENT',
+          isButtonGroup: true,
           text: Em.I18n.t('common.current'),
-          action: 'confirmRevertPatchUpgrade'
+          action: null,
+          buttons: [
+            {
+              text: Em.I18n.t('common.revert'),
+              action: 'confirmRevertPatchUpgrade'
+            }
+          ]
         },
         title: 'current revertable patch version'
       },