Kaynağa Gözat

AMBARI-10535. "Regenerate Keytabs" should restart services when complete (alexantonenko)

Alex Antonenko 10 yıl önce
ebeveyn
işleme
62e89232c7

+ 1 - 1
ambari-web/app/controllers/global/background_operations_controller.js

@@ -207,7 +207,7 @@ App.BackgroundOperationsController = Em.Controller.extend({
     var currentRequestIds = [];
     var countIssued = this.get('operationsCount');
     var countGot = data.itemTotal;
-   
+
     data.items.forEach(function (request) {
       if (this.isUpgradeRequest(request)) {
         if (!App.get('upgradeIsRunning') && !App.get('testMode')) {

+ 65 - 9
ambari-web/app/controllers/main/admin/kerberos.js

@@ -60,7 +60,7 @@ App.MainAdminKerberosController = App.KerberosWizardStep4Controller.extend({
   },
 
   /**
-   * Show confirmation popup and after confirmation send request to regenerate keytabs
+   * Show confirmation popup for regenerate keytabs
    * @method regenerateKeytabs
    * @return {App.ModalPopup}
    */
@@ -83,7 +83,37 @@ App.MainAdminKerberosController = App.KerberosWizardStep4Controller.extend({
 
       onPrimary: function () {
         this._super();
-        self.regenerateKeytabsRequest(this.get('regenerateKeytabsOnlyForMissing'));
+        return self.restartServicesAfterRegenerate(this.get('regenerateKeytabsOnlyForMissing'));
+      }
+    });
+  },
+
+  /**
+   * Show confirmation popup for restarting all services and after confirmation regenerate keytabs
+   *
+   * @param regenerateKeytabsOnlyForMissing {Boolean}
+   * @returns {*}
+   */
+  restartServicesAfterRegenerate: function (regenerateKeytabsOnlyForMissing) {
+    var self = this;
+
+    return App.ModalPopup.show({
+
+      /**
+       * True - automatically restart services, false - user will have to restart required services manually
+       * @type {boolean}
+       */
+      restartComponents: false,
+
+      header: Em.I18n.t('admin.kerberos.button.regenerateKeytabs'),
+
+      bodyClass: Em.View.extend({
+        templateName: require('templates/main/admin/kerberos/restart_services_after_regenerate_body')
+      }),
+
+      onPrimary: function () {
+        this._super();
+        self.regenerateKeytabsRequest(regenerateKeytabsOnlyForMissing, this.get('restartComponents'));
       }
     });
   },
@@ -91,14 +121,18 @@ App.MainAdminKerberosController = App.KerberosWizardStep4Controller.extend({
   /**
    * Send request to regenerate keytabs
    * @param {boolean} missingOnly determines type of regeneration - missing|all
+   * @param {boolean} withAutoRestart determines if the system should automatically restart all services or not after regeneration
    * @returns {$.ajax}
    */
-  regenerateKeytabsRequest: function (missingOnly) {
+  regenerateKeytabsRequest: function (missingOnly, withAutoRestart) {
+    missingOnly = missingOnly || false;
+
     return App.ajax.send({
       name: "admin.kerberos_security.regenerate_keytabs",
       sender: this,
       data: {
-        type: missingOnly ? 'missing' : 'all'
+        type: missingOnly ? 'missing' : 'all',
+        withAutoRestart: withAutoRestart || false
       },
       success: "regenerateKeytabsSuccess"
     });
@@ -107,15 +141,37 @@ App.MainAdminKerberosController = App.KerberosWizardStep4Controller.extend({
   /**
    * Success callback of <code>regenerateKeytabs</code>
    * show background operations popup if appropriate option is set
+   *
+   * @param data
+   * @param opt
+   * @param params
+   * @param request
    */
-  regenerateKeytabsSuccess: function () {
+  regenerateKeytabsSuccess: function (data, opt, params, request) {
+    var self = this;
     App.router.get('applicationController').dataLoading().done(function (initValue) {
       if (initValue) {
         App.router.get('backgroundOperationsController').showPopup();
       }
+      self.set('needsRestartAfterRegenerate', params.withAutoRestart);
     });
   },
 
+  /**
+   * Do request to server for restarting all services
+   * @method restartAllServices
+   * @return {$.ajax}
+   */
+  restartAllServices: function () {
+    if (!App.router.get('backgroundOperationsController.allOperationsCount')) {
+      if (this.get('needsRestartAfterRegenerate')) {
+        this.set('needsRestartAfterRegenerate', false);
+        App.router.get('mainServiceController').restartAllServices();
+      }
+    }
+  }.observes('controllers.backgroundOperationsController.allOperationsCount'),
+
+
   getUpdatedSecurityStatus: function () {
     this.getSecurityStatus();
     return this.get('securityEnabled');
@@ -202,7 +258,7 @@ App.MainAdminKerberosController = App.KerberosWizardStep4Controller.extend({
           self.loadClusterDescriptorConfigs().then(function() {
             dfd.resolve();
           }, function() {
-            // if kerberos descriptor doesn't exist in cluster artifacts we have to kerberize cluster. 
+            // if kerberos descriptor doesn't exist in cluster artifacts we have to kerberize cluster.
             // Show `Enable kerberos` button and set unsecure status.
             self.set('securityEnabled', false);
             dfd.resolve();
@@ -249,12 +305,12 @@ App.MainAdminKerberosController = App.KerberosWizardStep4Controller.extend({
     this.get('stepConfigs').clear();
     this._super(properties);
   },
-  
+
   /**
    * Override <code>App.KerberosWizardStep4Controller</code>
-   * 
+   *
    * @param {App.ServiceConfigProperty[]} configs
-   * @returns {App.ServiceConfigProperty[]} 
+   * @returns {App.ServiceConfigProperty[]}
    */
   prepareConfigProperties: function(configs) {
     var configProperties = configs.slice(0);

+ 76 - 0
ambari-web/app/controllers/main/service.js

@@ -152,6 +152,82 @@ App.MainServiceController = Em.ArrayController.extend({
     });
   },
 
+  /**
+   * Restart all services - stops all services, then starts them back
+   */
+  restartAllServices: function () {
+    this.silentStopAllServices();
+  },
+
+  /**
+   * Silent stop all services - without user confirmation
+   * @returns {$.ajax}
+   */
+  silentStopAllServices: function () {
+    return App.ajax.send({
+      name: 'common.services.update',
+      sender: this,
+      data: {
+        context: App.BackgroundOperationsController.CommandContexts.STOP_ALL_SERVICES,
+        ServiceInfo: {
+          state: 'INSTALLED'
+        }
+      },
+      success: 'silentStopSuccess'
+    });
+  },
+
+  /**
+   * Success callback for silent stop
+   */
+  silentStopSuccess: function () {
+    var self = this;
+
+    App.router.get('applicationController').dataLoading().done(function (initValue) {
+      if (initValue) {
+        App.router.get('backgroundOperationsController').showPopup();
+      }
+
+      Ember.run.later(function () {
+        self.set('shouldStart', true);
+      }, App.bgOperationsUpdateInterval);
+    });
+  },
+
+  /**
+   * Silent start all services - without user confirmation
+   */
+  silentStartAllServices: function () {
+    if (!App.router.get('backgroundOperationsController').get('allOperationsCount')) {
+      if (this.get('shouldStart')) {
+        this.set('shouldStart', false);
+        return App.ajax.send({
+          name: 'common.services.update',
+          sender: this,
+          data: {
+            context: App.BackgroundOperationsController.CommandContexts.START_ALL_SERVICES,
+            ServiceInfo: {
+              state: 'STARTED'
+            }
+          },
+          success: 'silentCallSuccessCallback'
+        });
+      }
+    }
+  }.observes('shouldStart', 'controllers.backgroundOperationsController.allOperationsCount'),
+
+  /**
+   * Success callback for silent start
+   */
+  silentCallSuccessCallback: function () {
+    // load data (if we need to show this background operations popup) from persist
+    App.router.get('applicationController').dataLoading().done(function (initValue) {
+      if (initValue) {
+        App.router.get('backgroundOperationsController').showPopup();
+      }
+    });
+  },
+
   /**
    * Success-callback for all-services request
    * @param {object} data

+ 3 - 1
ambari-web/app/messages.js

@@ -1019,8 +1019,10 @@ Em.I18n.translations = {
   'admin.kerberos.wizard.step7.notice.failed': 'Some services failed to start and execute tests successfully. Click Retry to attempt again or click Complete to dismiss the wizard and fix manually.',
   'admin.kerberos.wizard.step7.task0.title' : 'Start and Test Services',
 
-  'admin.kerberos.regenerate_keytabs.popup.body': 'You are about to regenerate keytabs for the hosts in the cluster. This will stop all the services in your cluster and regenerate the Kerberos keytabs. <strong>Are you sure you wish to proceed with keytab regeneration?</strong>',
+  'admin.kerberos.regenerate_keytabs.popup.body': 'Regenerating keytabs for <strong>all</strong> hosts in the cluster is a disruptive operation, and requires all components to be restarted. Optionally, keytabs can be regenerated <strong>only</strong> for missing hosts and components, and this operation requires selectively restarting those affected hosts and services.',
   'admin.kerberos.regenerate_keytabs.checkbox.label': ' Only regenerate keytabs for missing hosts and components',
+  'admin.kerberos.regenerate_keytabs.popup.restart.body': 'After keytab regerate is complete, services relying on them <strong>must</strong> be restarted. This can be done automatically, or manually.',
+  'admin.kerberos.regenerate_keytabs.checkbox.restart.label': 'Automatically restart components after keytab regeneration',
 
   'admin.kerberos.disable.step1.task0.title': 'Stop Services',
   'admin.kerberos.disable.step1.task1.title': 'Unkerberize Cluster',

+ 1 - 1
ambari-web/app/styles/stack_versions.less

@@ -398,4 +398,4 @@
       color: @blue;
     }
   }
-}
+}

+ 21 - 0
ambari-web/app/templates/main/admin/kerberos/restart_services_after_regenerate_body.hbs

@@ -0,0 +1,21 @@
+{{!
+* 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.
+}}
+<p class="alert alert-warning">{{t admin.kerberos.regenerate_keytabs.popup.restart.body}}</p>
+<p>
+  <label>{{view Em.Checkbox classNames="checkbox" checkedBinding="view.parentView.restartComponents"}} {{t admin.kerberos.regenerate_keytabs.checkbox.restart.label}}</label>
+</p>

+ 39 - 5
ambari-web/test/controllers/main/admin/kerberos_test.js

@@ -116,32 +116,66 @@ describe('App.MainAdminKerberosController', function() {
     beforeEach(function () {
       sinon.spy(App.ModalPopup, "show");
       sinon.stub(App.ajax, 'send', Em.K);
+      sinon.spy(controller, 'restartServicesAfterRegenerate');
+      sinon.spy(controller, 'restartAllServices');
     });
     afterEach(function () {
       App.ModalPopup.show.restore();
       App.ajax.send.restore();
+      controller.restartServicesAfterRegenerate.restore();
+      controller.restartAllServices.restore();
     });
 
-    it('confirm popup should be displayed', function () {
+    it('both confirmation popups should be displayed', function () {
       var popup = controller.regenerateKeytabs();
       expect(App.ModalPopup.show.calledOnce).to.be.true;
       popup.onPrimary();
-      expect(App.ajax.send.calledOnce).to.be.true;
+      expect(controller.restartServicesAfterRegenerate.calledOnce).to.be.true;
+      expect(App.ModalPopup.show.calledTwice).to.be.true;
     });
 
     it('user checked regeneration only for missing host/components', function () {
       var popup = controller.regenerateKeytabs();
       popup.set('regenerateKeytabsOnlyForMissing', true);
-      popup.onPrimary();
+
+      var popup2 = popup.onPrimary();
+      popup2.set('restartComponents', true)
+      popup2.onPrimary();
+
       expect(App.ajax.send.args[0][0].data.type).to.equal('missing');
     });
 
     it('user didn\'t check regeneration only for missing host/components', function () {
       var popup = controller.regenerateKeytabs();
-      popup.onPrimary();
+      popup.set('regenerateKeytabsOnlyForMissing', false);
+
+      var popup2 = popup.onPrimary();
+      popup2.set('restartComponents', true)
+      popup2.onPrimary();
+
       expect(App.ajax.send.args[0][0].data.type).to.equal('all');
     });
 
-  });
+    it('user checked restart services automatically', function () {
+      var popup = controller.regenerateKeytabs();
+      popup.set('regenerateKeytabsOnlyForMissing', true);
 
+      var popup2 = popup.onPrimary();
+      popup2.set('restartComponents', true)
+      popup2.onPrimary();
+
+      expect(App.ajax.send.args[0][0].data.withAutoRestart).to.be.true;
+    });
+
+    it('user didn\'t check restart services automatically', function () {
+      var popup = controller.regenerateKeytabs();
+      popup.set('regenerateKeytabsOnlyForMissing', true);
+
+      var popup2 = popup.onPrimary();
+      popup2.set('restartComponents', false)
+      popup2.onPrimary();
+
+      expect(App.ajax.send.args[0][0].data.withAutoRestart).to.be.false;
+    });
+  });
 });