Procházet zdrojové kódy

AMBARI-10905. FE work for "Update Kerberos Wizard to support manually enabling Kerberos" (alexantonenko)

Alex Antonenko před 10 roky
rodič
revize
78c7b43534
26 změnil soubory, kde provedl 529 přidání a 202 odebrání
  1. 1 1
      ambari-web/app/assets/test/tests.js
  2. 1 0
      ambari-web/app/controllers.js
  3. 26 1
      ambari-web/app/controllers/main/admin/kerberos/step1_controller.js
  4. 1 2
      ambari-web/app/controllers/main/admin/kerberos/step2_controller.js
  5. 51 30
      ambari-web/app/controllers/main/admin/kerberos/step5_controller.js
  6. 36 90
      ambari-web/app/controllers/main/admin/kerberos/step6_controller.js
  7. 110 7
      ambari-web/app/controllers/main/admin/kerberos/step7_controller.js
  8. 43 0
      ambari-web/app/controllers/main/admin/kerberos/step8_controller.js
  9. 41 6
      ambari-web/app/controllers/main/admin/kerberos/wizard_controller.js
  10. 24 13
      ambari-web/app/messages.js
  11. 79 23
      ambari-web/app/routes/add_kerberos_routes.js
  12. 5 2
      ambari-web/app/styles/application.less
  13. 1 2
      ambari-web/app/templates/main/admin/kerberos/step1.hbs
  14. 28 2
      ambari-web/app/templates/main/admin/kerberos/step5.hbs
  15. 1 1
      ambari-web/app/templates/main/admin/kerberos/step6.hbs
  16. 20 0
      ambari-web/app/templates/main/admin/kerberos/step8.hbs
  17. 1 0
      ambari-web/app/templates/main/admin/kerberos/wizard.hbs
  18. 10 0
      ambari-web/app/utils/ajax/ajax.js
  19. 1 0
      ambari-web/app/views.js
  20. 10 4
      ambari-web/app/views/common/configs/service_configs_by_category_view.js
  21. 1 7
      ambari-web/app/views/main/admin/kerberos/step5_view.js
  22. 1 2
      ambari-web/app/views/main/admin/kerberos/step6_view.js
  23. 4 5
      ambari-web/app/views/main/admin/kerberos/step7_view.js
  24. 31 0
      ambari-web/app/views/main/admin/kerberos/step8_view.js
  25. 0 2
      ambari-web/app/views/main/admin/kerberos/wizard_view.js
  26. 2 2
      ambari-web/test/controllers/main/admin/kerberos/step6_controller_test.js

+ 1 - 1
ambari-web/app/assets/test/tests.js

@@ -53,7 +53,7 @@ var files = ['test/init_model_test',
   'test/controllers/main/admin/kerberos/kerberos_wizard_controler_test',
   'test/controllers/main/admin/kerberos/step3_controller_test',
   'test/controllers/main/admin/kerberos/step4_controller_test',
-  'test/controllers/main/admin/kerberos/step5_controller_test',
+  'test/controllers/main/admin/kerberos/step6_controller_test',
   'test/controllers/main/admin/stack_and_upgrade_controller_test',
   'test/controllers/main/admin/serviceAccounts_controller_test',
   'test/controllers/main/admin/highAvailability_controller_test',

+ 1 - 0
ambari-web/app/controllers.js

@@ -71,6 +71,7 @@ require('controllers/main/admin/kerberos/step4_controller');
 require('controllers/main/admin/kerberos/step5_controller');
 require('controllers/main/admin/kerberos/step6_controller');
 require('controllers/main/admin/kerberos/step7_controller');
+require('controllers/main/admin/kerberos/step8_controller');
 require('controllers/main/admin/security');
 require('controllers/main/admin/security/security_progress_controller');
 require('controllers/main/admin/security/disable');

+ 26 - 1
ambari-web/app/controllers/main/admin/kerberos/step1_controller.js

@@ -71,6 +71,32 @@ App.KerberosWizardStep1Controller = Em.Controller.extend({
           checked: false
         })
       ]
+    }),
+    Em.Object.create({
+      displayName: Em.I18n.t('admin.kerberos.wizard.step1.option.manual'),
+      value: Em.I18n.t('admin.kerberos.wizard.step1.option.manual'),
+      preConditions: [
+        Em.Object.create({
+          displayText: Em.I18n.t('admin.kerberos.wizard.step1.option.manual.condition.1'),
+          checked: false
+        }),
+        Em.Object.create({
+          displayText: Em.I18n.t('admin.kerberos.wizard.step1.option.manual.condition.2'),
+          checked: false
+        }),
+        Em.Object.create({
+          displayText: Em.I18n.t('admin.kerberos.wizard.step1.option.manual.condition.3'),
+          checked: false
+        }),
+        Em.Object.create({
+          displayText: Em.I18n.t('admin.kerberos.wizard.step1.option.manual.condition.4'),
+          checked: false
+        }),
+        Em.Object.create({
+          displayText: Em.I18n.t('admin.kerberos.wizard.step1.option.manual.condition.5'),
+          checked: false
+        })
+      ]
     })
   ],
 
@@ -95,4 +121,3 @@ App.KerberosWizardStep1Controller = Em.Controller.extend({
     }
   }
 });
-

+ 1 - 2
ambari-web/app/controllers/main/admin/kerberos/step2_controller.js

@@ -282,7 +282,7 @@ App.KerberosWizardStep2Controller = App.WizardStep7Controller.extend({
   },
 
   /**
-   * shows popup with to warn user  
+   * shows popup with to warn user
    * @param primary
    */
   showConnectionInProgressPopup: function(primary) {
@@ -291,4 +291,3 @@ App.KerberosWizardStep2Controller = App.WizardStep7Controller.extend({
     App.showConfirmationPopup(primary, msg, null, null, primaryText)
   }
 });
-

+ 51 - 30
ambari-web/app/controllers/main/admin/kerberos/step5_controller.js

@@ -15,51 +15,72 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+ var stringUtils = require('utils/string_utils');
 
 App.KerberosWizardStep5Controller = App.KerberosProgressPageController.extend({
   name: 'kerberosWizardStep5Controller',
-  clusterDeployState: 'KERBEROS_DEPLOY',
-  commands: ['stopServices'],
+  csvData: [],
 
-  loadStep: function() {
-    this.checkComponentsRemoval();
-    this._super();
+  submit: function() {
+    App.router.send('next');
   },
 
   /**
-   * remove Application Timeline Server component if needed.
+   * get CSV data from the server
    */
-  checkComponentsRemoval: function() {
-    if (App.Service.find().someProperty('serviceName', 'YARN') && !App.get('doesATSSupportKerberos')
-      && !this.get('commands').contains('deleteATS') && App.HostComponent.find().findProperty('componentName', 'APP_TIMELINE_SERVER')) {
-      this.get('commands').pushObject('deleteATS');
-    }
+  getCSVData: function () {
+    App.ajax.send({
+      name: 'admin.kerberos.cluster.csv',
+      sender: this,
+      data: {},
+      success: 'getCSVDataSuccessCallback',
+      error: 'getCSVDataSuccessCallback'
+    })
   },
 
   /**
-   * Remove Application Timeline Server from the host.
-   * @returns {$.Deferred}
+   * get CSV data from server success callback
    */
-  deleteATS: function() {
-    return App.ajax.send({
-      name: 'common.delete.host_component',
-      sender: this,
-      data: {
-        componentName: 'APP_TIMELINE_SERVER',
-        hostName: App.HostComponent.find().findProperty('componentName', 'APP_TIMELINE_SERVER').get('hostName')
-      },
-      success: 'onDeleteATSSuccess',
-      error: 'onDeleteATSError'
-    });
+  getCSVDataSuccessCallback: function (data, opt, params) {
+    this.set('csvData', this.prepareCSVData(data.split('\n')));
+    this.downloadCSV();
   },
 
-  onDeleteATSSuccess: function() {
-    this.onTaskCompleted();
+  prepareCSVData: function (array) {
+    for (var i = 0; i < array.length; i += 1) {
+      array[i] = array[i].split(',');
+    }
+
+    return array;
   },
 
-  onDeleteATSError: function(error) {
-    if (error.responseText.indexOf('org.apache.ambari.server.controller.spi.NoSuchResourceException') !== -1) {
-      this.onDeleteATSSuccess();
+  /**
+   * download CSV file
+   */
+  downloadCSV: function () {
+    if ($.browser.msie && $.browser.version < 10) {
+      this.openInfoInNewTab();
+    } else {
+      try {
+        var blob = new Blob([stringUtils.arrayToCSV(this.get('csvData'))], {type: "text/csv;charset=utf-8;"});
+        saveAs(blob, "kerberos.csv");
+      } catch (e) {
+        this.openInfoInNewTab();
+      }
     }
-  }
+  },
+
+  /**
+   * open content of CSV file in new window
+   */
+  openInfoInNewTab: function () {
+    var newWindow = window.open('');
+    var newDocument = newWindow.document;
+    newDocument.write(stringUtils.arrayToCSV(this.get('hostComponents')));
+    newWindow.focus();
+  },
+
+  isSubmitDisabled: function () {
+    return !["COMPLETED", "FAILED"].contains(this.get('status'));
+  }.property('status')
 });

+ 36 - 90
ambari-web/app/controllers/main/admin/kerberos/step6_controller.js

@@ -19,116 +19,62 @@
 App.KerberosWizardStep6Controller = App.KerberosProgressPageController.extend({
   name: 'kerberosWizardStep6Controller',
   clusterDeployState: 'KERBEROS_DEPLOY',
-  isSingleRequestPage: true,
-  request: {},
-  commands: [],
-  contextForPollingRequest: Em.I18n.t('requestInfo.kerberizeCluster'),
+  commands: ['stopServices'],
 
-  /**
-   * Define whether show Back button
-   * @type {Boolean}
-   */
-  isBackButtonDisabled: true,
-
-  /**
-   * Start cluster kerberization. On retry just unkerberize and kerbrize cluster.
-   * @param {bool} isRetry
-   */
-  setRequest: function (isRetry) {
-    var self = this;
-    var kerberizeRequest = {
-      name: 'KERBERIZE_CLUSTER',
-      ajaxName: 'admin.kerberize.cluster',
-      ajaxData: {
-        data: {
-          Clusters: {
-            security_type: "KERBEROS"
-          }
+  stopServices: function () {
+    App.ajax.send({
+      name: 'common.services.update',
+      data: {
+        context: "Stop services",
+        "ServiceInfo": {
+          "state": "INSTALLED"
         }
-      }
-    };
-    if (isRetry) {
-      // on retry we have to unkerberize cluster
-      this.unkerberizeCluster().always(function() {
-        // clear current request object before start of kerberize process
-        self.set('request', kerberizeRequest);
-        self.clearStage();
-        self.loadStep();
-      });
-    } else {
-      this.set('request', kerberizeRequest);
-    }
-  },
-
-  /**
-   * Send request to unkerberisze cluster
-   * @returns {$.ajax}
-   */
-  unkerberizeCluster: function () {
-    return App.ajax.send({
-      name: 'admin.unkerberize.cluster',
+      },
       sender: this,
-      success: 'goToNextStep',
-      error: 'goToNextStep'
+      success: 'startPolling',
+      error: 'onTaskError'
     });
   },
 
-  goToNextStep: function() {
-    this.clearStage();
-    App.router.transitionTo('step6');
+  loadStep: function() {
+    this.checkComponentsRemoval();
+    this._super();
   },
 
-  postKerberosDescriptor: function (kerberosDescriptor) {
-    return App.ajax.send({
-      name: 'admin.kerberos.cluster.artifact.create',
-      sender: this,
-      data: {
-        artifactName: 'kerberos_descriptor',
-        data: {
-          artifact_data: kerberosDescriptor
-        }
-      }
-    });
+  /**
+   * remove Application Timeline Server component if needed.
+   */
+  checkComponentsRemoval: function() {
+    if (App.Service.find().someProperty('serviceName', 'YARN') && !App.get('doesATSSupportKerberos')
+      && !this.get('commands').contains('deleteATS') && App.HostComponent.find().findProperty('componentName', 'APP_TIMELINE_SERVER')) {
+      this.get('commands').pushObject('deleteATS');
+    }
   },
 
   /**
-   * Send request to update kerberos descriptor
-   * @param kerberosDescriptor
-   * @returns {$.ajax|*}
+   * Remove Application Timeline Server from the host.
+   * @returns {$.Deferred}
    */
-  putKerberosDescriptor: function (kerberosDescriptor) {
+  deleteATS: function() {
     return App.ajax.send({
-      name: 'admin.kerberos.cluster.artifact.update',
+      name: 'common.delete.host_component',
       sender: this,
       data: {
-        artifactName: 'kerberos_descriptor',
-        data: {
-          artifact_data: kerberosDescriptor
-        }
+        componentName: 'APP_TIMELINE_SERVER',
+        hostName: App.HostComponent.find().findProperty('componentName', 'APP_TIMELINE_SERVER').get('hostName')
       },
-      success: 'unkerberizeCluster',
-      error: 'unkerberizeCluster'
+      success: 'onDeleteATSSuccess',
+      error: 'onDeleteATSError'
     });
   },
 
-  retry: function () {
-    this.set('showRetry', false);
-    this.get('tasks').setEach('status', 'PENDING');
-    App.router.send('retry');
+  onDeleteATSSuccess: function() {
+    this.onTaskCompleted();
   },
 
-
-  /**
-   * Enable or disable previous steps according to tasks statuses
-   */
-  enableDisablePreviousSteps: function () {
-    var wizardController = App.router.get(this.get('content.controllerName'));
-    if (this.get('tasks').someProperty('status', 'FAILED')) {
-      wizardController.enableStep(4);
-      this.set('isBackButtonDisabled', false);
-    } else {
-      wizardController.setLowerStepsDisable(6);
-      this.set('isBackButtonDisabled', true);
+  onDeleteATSError: function(error) {
+    if (error.responseText.indexOf('org.apache.ambari.server.controller.spi.NoSuchResourceException') !== -1) {
+      this.onDeleteATSSuccess();
     }
-  }.observes('tasks.@each.status')
+  }
 });

+ 110 - 7
ambari-web/app/controllers/main/admin/kerberos/step7_controller.js

@@ -19,13 +19,116 @@
 App.KerberosWizardStep7Controller = App.KerberosProgressPageController.extend({
   name: 'kerberosWizardStep7Controller',
   clusterDeployState: 'KERBEROS_DEPLOY',
-  commands: ['startAllServices'],
+  isSingleRequestPage: true,
+  request: {},
+  commands: [],
+  contextForPollingRequest: Em.I18n.t('requestInfo.kerberizeCluster'),
 
-  startAllServices: function () {
-    this.startServices(true);
+  /**
+   * Define whether show Back button
+   * @type {Boolean}
+   */
+  isBackButtonDisabled: true,
+
+  /**
+   * Start cluster kerberization. On retry just unkerberize and kerbrize cluster.
+   * @param {bool} isRetry
+   */
+  setRequest: function (isRetry) {
+    var self = this;
+    var kerberizeRequest = {
+      name: 'KERBERIZE_CLUSTER',
+      ajaxName: 'admin.kerberize.cluster',
+      ajaxData: {
+        data: {
+          Clusters: {
+            security_type: "KERBEROS"
+          }
+        }
+      }
+    };
+    if (isRetry) {
+      // on retry we have to unkerberize cluster
+      this.unkerberizeCluster().always(function() {
+        // clear current request object before start of kerberize process
+        self.set('request', kerberizeRequest);
+        self.clearStage();
+        self.loadStep();
+      });
+    } else {
+      this.set('request', kerberizeRequest);
+    }
+  },
+
+  /**
+   * Send request to unkerberisze cluster
+   * @returns {$.ajax}
+   */
+  unkerberizeCluster: function () {
+    return App.ajax.send({
+      name: 'admin.unkerberize.cluster',
+      sender: this,
+      success: 'goToNextStep',
+      error: 'goToNextStep'
+    });
+  },
+
+  goToNextStep: function() {
+    this.clearStage();
+    App.router.transitionTo('step7');
+  },
+
+  postKerberosDescriptor: function (kerberosDescriptor) {
+    return App.ajax.send({
+      name: 'admin.kerberos.cluster.artifact.create',
+      sender: this,
+      data: {
+        artifactName: 'kerberos_descriptor',
+        data: {
+          artifact_data: kerberosDescriptor
+        }
+      }
+    });
+  },
+
+  /**
+   * Send request to update kerberos descriptor
+   * @param kerberosDescriptor
+   * @returns {$.ajax|*}
+   */
+  putKerberosDescriptor: function (kerberosDescriptor) {
+    return App.ajax.send({
+      name: 'admin.kerberos.cluster.artifact.update',
+      sender: this,
+      data: {
+        artifactName: 'kerberos_descriptor',
+        data: {
+          artifact_data: kerberosDescriptor
+        }
+      },
+      success: 'unkerberizeCluster',
+      error: 'unkerberizeCluster'
+    });
   },
 
-  isSubmitDisabled: function () {
-    return !["COMPLETED", "FAILED"].contains(this.get('status'));
-  }.property('status')
-});
+  retry: function () {
+    this.set('showRetry', false);
+    this.get('tasks').setEach('status', 'PENDING');
+    App.router.send('retry');
+  },
+
+
+  /**
+   * Enable or disable previous steps according to tasks statuses
+   */
+  enableDisablePreviousSteps: function () {
+    var wizardController = App.router.get(this.get('content.controllerName'));
+    if (this.get('tasks').someProperty('status', 'FAILED')) {
+      wizardController.enableStep(4);
+      this.set('isBackButtonDisabled', false);
+    } else {
+      wizardController.setLowerStepsDisable(6);
+      this.set('isBackButtonDisabled', true);
+    }
+  }.observes('tasks.@each.status')
+});

+ 43 - 0
ambari-web/app/controllers/main/admin/kerberos/step8_controller.js

@@ -0,0 +1,43 @@
+/**
+ * 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.
+ */
+
+App.KerberosWizardStep8Controller = App.KerberosProgressPageController.extend({
+  name: 'kerberosWizardStep8Controller',
+  clusterDeployState: 'KERBEROS_DEPLOY',
+  commands: ['startServices'],
+
+  startServices: function () {
+    App.ajax.send({
+      name: 'common.services.update',
+      sender: this,
+      data: {
+        "context": "Start services",
+        "ServiceInfo": {
+          "state": "STARTED"
+        },
+        urlParams: "params/run_smoke_test=true"
+      },
+      success: 'startPolling',
+      error: 'onTaskError'
+    });
+  },
+
+  isSubmitDisabled: function () {
+    return !["COMPLETED", "FAILED"].contains(this.get('status'));
+  }.property('status')
+});

+ 41 - 6
ambari-web/app/controllers/main/admin/kerberos/wizard_controller.js

@@ -21,9 +21,11 @@ var App = require('app');
 
 App.KerberosWizardController = App.WizardController.extend({
 
+  exceptionsOnSkipClient: ['realm', 'kdc_type', 'kdc_host', 'executable_search_paths'],
+
   name: 'kerberosWizardController',
 
-  totalSteps: 7,
+  totalSteps: 8,
 
   isKerberosWizard: true,
 
@@ -32,6 +34,8 @@ App.KerberosWizardController = App.WizardController.extend({
    */
   hideBackButton: true,
 
+  skipClientInstall: false,
+
   kerberosDescriptorConfigs: null,
 
   content: Em.Object.create({
@@ -136,8 +140,14 @@ App.KerberosWizardController = App.WizardController.extend({
   },
 
   saveKerberosOption: function (stepController) {
-    this.setDBProperty('kerberosOption', stepController.get('selectedItem'));
-    this.set('content.kerberosOption', stepController.get('selectedItem'));
+    // the server does not support this kdc_type and will fail on install
+    //TODO: make sure the server supports all kdc_types
+    var selectedItem = stepController.get('selectedItem');
+    if (selectedItem === Em.I18n.t('admin.kerberos.wizard.step1.option.manual')) {
+      selectedItem = Em.I18n.t('admin.kerberos.wizard.step1.option.kdc');
+    }
+    this.setDBProperty('kerberosOption', selectedItem);
+    this.set('content.kerberosOption', selectedItem);
   },
 
   /**
@@ -166,7 +176,32 @@ App.KerberosWizardController = App.WizardController.extend({
 
   loadKerberosDescriptorConfigs: function () {
     var kerberosDescriptorConfigs = this.getDBProperty('kerberosDescriptorConfigs');
-    this.kerberosDescriptorConfigs =  kerberosDescriptorConfigs;
+    this.set('kerberosDescriptorConfigs', kerberosDescriptorConfigs);
+  },
+
+
+
+  /**
+   * Overide the visibility of a list of form items with a new value
+   *
+   * @param {Array} itemsArray
+   * @param newValue
+   */
+  overrideVisibility: function (itemsArray, newValue) {
+    var self = this;
+    newValue = newValue || false;
+
+    for (var i=0; i < itemsArray.length; i += 1) {
+      if (self.get('exceptionsOnSkipClient').indexOf(itemsArray[i].get('name')) < 0) {
+        itemsArray[i].set('isVisible', newValue);
+
+        // if it was required, but we're making it not visible, also
+        // make the input value not required any more
+        if (itemsArray[i].get('isRequiredByAgent') && !newValue) {
+          itemsArray[i].set('isRequiredByAgent', newValue)
+        }
+      }
+    }
   },
 
   loadKerberosOption: function () {
@@ -175,7 +210,7 @@ App.KerberosWizardController = App.WizardController.extend({
 
   saveKerberosDescriptorConfigs: function (kerberosDescriptorConfigs) {
     this.setDBProperty('kerberosDescriptorConfigs',kerberosDescriptorConfigs);
-    this.kerberosDescriptorConfigs =  kerberosDescriptorConfigs;
+    this.set('kerberosDescriptorConfigs', kerberosDescriptorConfigs);
   },
 
 
@@ -216,7 +251,7 @@ App.KerberosWizardController = App.WizardController.extend({
         }
       }
     ],
-    '5': [
+    '6': [
       {
         type: 'sync',
         callback: function () {

+ 24 - 13
ambari-web/app/messages.js

@@ -986,9 +986,10 @@ Em.I18n.translations = {
   'admin.kerberos.wizard.step2.header': 'Configure Kerberos',
   'admin.kerberos.wizard.step3.header': 'Install and Test Kerberos Client',
   'admin.kerberos.wizard.step4.header': 'Configure Identities',
-  'admin.kerberos.wizard.step5.header': 'Stop Services',
-  'admin.kerberos.wizard.step6.header': 'Kerberize Cluster',
-  'admin.kerberos.wizard.step7.header': 'Start and Test Services',
+  'admin.kerberos.wizard.step5.header': 'Confirm Configuration',
+  'admin.kerberos.wizard.step6.header': 'Stop Services',
+  'admin.kerberos.wizard.step7.header': 'Kerberize Cluster',
+  'admin.kerberos.wizard.step8.header': 'Start and Test Services',
   'admin.kerberos.wizard.step1.info.body': 'Welcome to the Ambari Security Wizard. Use this wizard to enable kerberos security in your cluster. </br>Let\'s get started.',
   'admin.kerberos.wizard.step1.alert.body': 'Note: This process requires services to be restarted and cluster downtime. As well, depending on the options you select, might require support from your Security administrators. Please plan accordingly.',
   'admin.kerberos.wizard.step1.body.text': 'What type of KDC do you plan on using?',
@@ -996,6 +997,12 @@ Em.I18n.translations = {
   'admin.kerberos.wizard.step1.option.kdc.condition.1': 'Ambari Server and cluster hosts have network access to both the KDC and KDC admin hosts.',
   'admin.kerberos.wizard.step1.option.kdc.condition.2': 'KDC administrative credentials are on-hand.',
   'admin.kerberos.wizard.step1.option.kdc.condition.3': 'The Java Cryptography Extensions (JCE) have been setup on the Ambari Server host and all hosts in the cluster.',
+  'admin.kerberos.wizard.step1.option.manual': 'Manage Kerberos principals and keytabs manually',
+  'admin.kerberos.wizard.step1.option.manual.condition.1': 'Hosts in my cluster can reach my KDC server',
+  'admin.kerberos.wizard.step1.option.manual.condition.2': 'I have the Kerberos Client utilities (such as kinit) installed on my hosts',
+  'admin.kerberos.wizard.step1.option.manual.condition.3': 'JCE is installed on the Ambari Server and all cluster hosts',
+  'admin.kerberos.wizard.step1.option.manual.condition.4': 'I plan to create the Service and Ambari principals in my KDC',
+  'admin.kerberos.wizard.step1.option.manual.condition.5': 'I plan to create keytabs for the principals and distribute to the hosts in my cluster',
   'admin.kerberos.wizard.step1.option.ad': 'Existing Active Directory',
   'admin.kerberos.wizard.step1.option.ad.condition.1': 'Ambari Server and cluster hosts have network access to the Domain Controllers.',
   'admin.kerberos.wizard.step1.option.ad.condition.2': 'Active Directory secure LDAP (LDAPS) connectivity has been configured.',
@@ -1010,16 +1017,20 @@ Em.I18n.translations = {
   'admin.kerberos.wizard.step3.notice.completed': 'Kerberos service has been installed and tested successfully.',
   'admin.kerberos.wizard.progressPage.notice.inProgress': 'Please wait while cluster is being kerberized',
   'admin.kerberos.wizard.step4.info.body': 'Configure principal name and keytab location for service users and hadoop service components.',
-  'admin.kerberos.wizard.step5.task0.title' : 'Stop Services',
-  'admin.kerberos.wizard.step5.task1.title' : 'Delete ATS',
-  'admin.kerberos.wizard.step5.notice.inProgress': 'Please wait while services are being stopped.',
-  'admin.kerberos.wizard.step5.notice.completed': 'Services have been successfully stopped.',
-  'admin.kerberos.wizard.step6.notice.inProgress': 'Please wait while cluster is being kerberized.',
-  'admin.kerberos.wizard.step6.notice.completed': 'Kerberos has successfully been enabled on the cluster.',
-  'admin.kerberos.wizard.step7.notice.inProgress': 'Please wait while services are being started and tested.',
-  'admin.kerberos.wizard.step7.notice.completed': 'Services have been successfully tested with kerberos environment.',
-  '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.wizard.step5.info.body': 'Please review the configuration before continuing the setup process',
+  'admin.kerberos.wizard.step5.realm.label': 'Realm Name',
+  'admin.kerberos.wizard.step5.exitWizard': 'Exit Wizard',
+  'admin.kerberos.wizard.step5.downloadCSV': 'Download CSV',
+  'admin.kerberos.wizard.step6.task0.title' : 'Stop Services',
+  'admin.kerberos.wizard.step6.task1.title' : 'Delete ATS',
+  'admin.kerberos.wizard.step6.notice.inProgress': 'Please wait while services are being stopped.',
+  'admin.kerberos.wizard.step6.notice.completed': 'Services have been successfully stopped.',
+  'admin.kerberos.wizard.step7.notice.inProgress': 'Please wait while cluster is being kerberized.',
+  'admin.kerberos.wizard.step7.notice.completed': 'Kerberos has successfully been enabled on the cluster.',
+  'admin.kerberos.wizard.step8.notice.inProgress': 'Please wait while services are being started and tested.',
+  'admin.kerberos.wizard.step8.notice.completed': 'Services have been successfully tested with kerberos environment.',
+  'admin.kerberos.wizard.step8.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.step8.task0.title' : 'Start and Test Services',
 
   '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',

+ 79 - 23
ambari-web/app/routes/add_kerberos_routes.js

@@ -135,6 +135,9 @@ module.exports = App.WizardRoute.extend({
     next: function (router) {
       var kerberosWizardController = router.get('kerberosWizardController');
       var kerberosStep1controller = router.get('kerberosWizardStep1Controller');
+      var skipClientInstall = kerberosStep1controller.get('selectedOption.value') === Em.I18n.t('admin.kerberos.wizard.step1.option.manual');
+      kerberosWizardController.set('skipClientInstall', skipClientInstall);
+
       kerberosWizardController.saveKerberosOption(kerberosStep1controller);
       kerberosWizardController.setDBProperty('serviceConfigProperties', null);
       kerberosWizardController.setDBProperty('advancedServiceConfig', null);
@@ -169,9 +172,21 @@ module.exports = App.WizardRoute.extend({
     next: function (router) {
       var kerberosWizardController = router.get('kerberosWizardController');
       var kerberosWizardStep2Controller = router.get('kerberosWizardStep2Controller');
+
+      if (kerberosWizardController.get('skipClientInstall')) {
+        kerberosWizardStep2Controller.get('stepConfigs')[0].get('configs').findProperty('name', 'manage_identities').set('value', 'false');
+        kerberosWizardStep2Controller.get('stepConfigs')[0].get('configs').findProperty('name', 'install_packages').set('value', 'false');
+        kerberosWizardStep2Controller.get('stepConfigs')[0].get('configs').findProperty('name', 'manage_krb5_conf').set('value', 'false');
+      }
+
       kerberosWizardController.saveServiceConfigProperties(kerberosWizardStep2Controller);
       kerberosWizardController.clearTasksData();
-      router.transitionTo('step3');
+      if (kerberosWizardController.get('skipClientInstall')) {
+        kerberosWizardController.setDBProperty('kerberosDescriptorConfigs', null);
+        router.transitionTo('step4');
+      } else {
+        router.transitionTo('step3');
+      }
     }
   }),
 
@@ -217,13 +232,14 @@ module.exports = App.WizardRoute.extend({
     unroutePath: function () {
       return false;
     },
-    back: Em.Router.transitionTo('step3'),
+    back: function (router) {
+      if (router.get('kerberosWizardController.skipClientInstall')) {
+        router.transitionTo('step2');
+      } else {
+        router.transitionTo('step3');
+      }
+    },
     next: function (router) {
-      var kerberosWizardController = router.get('kerberosWizardController');
-      var kerberosWizardStep4Controller = router.get('kerberosWizardStep4Controller');
-      kerberosWizardController.saveServiceConfigProperties(kerberosWizardStep4Controller);
-      kerberosWizardController.setDBProperty('tasksStatuses', null);
-      kerberosWizardController.setDBProperty('tasksRequestIds', null);
       router.transitionTo('step5');
     }
   }),
@@ -241,23 +257,30 @@ module.exports = App.WizardRoute.extend({
         controller.connectOutlet('kerberosWizardStep5', controller.get('content'));
       });
     },
+
     unroutePath: function () {
       return false;
     },
+
+    exitWizard: function (router) {
+      var popup = router.get('kerberosWizardController.popup');
+      popup.onClose();
+    },
+
+    downloadCSV: function (router) {
+      var kerberosWizardStep5Controller = router.get('kerberosWizardStep5Controller');
+      kerberosWizardStep5Controller.getCSVData();
+    },
+
     back: Em.Router.transitionTo('step4'),
+
     next: function (router) {
       var kerberosWizardController = router.get('kerberosWizardController');
+      var kerberosWizardStep4Controller = router.get('kerberosWizardStep4Controller');
+      kerberosWizardController.saveServiceConfigProperties(kerberosWizardStep4Controller);
       kerberosWizardController.setDBProperty('tasksStatuses', null);
       kerberosWizardController.setDBProperty('tasksRequestIds', null);
-      var step6Controller = router.get('kerberosWizardStep6Controller');
-      var kerberosDescriptor = kerberosWizardController.get('kerberosDescriptorConfigs');
-      step6Controller.postKerberosDescriptor(kerberosDescriptor).always(function (data, result, request) {
-        if (result === 'error' && data.status === 409) {
-          step6Controller.putKerberosDescriptor(kerberosDescriptor);
-        } else {
-          step6Controller.unkerberizeCluster();
-        }
-      });
+      router.transitionTo('step6');
     }
   }),
 
@@ -267,24 +290,30 @@ module.exports = App.WizardRoute.extend({
     connectOutlets: function (router) {
       console.log('in kerberosWizardController.step6:connectOutlets');
       var controller = router.get('kerberosWizardController');
-      var stepController = router.get('kerberosWizardStep6Controller');
       controller.dataLoading().done(function () {
         router.get('kerberosWizardController').setCurrentStep('6');
         controller.setLowerStepsDisable(6);
         controller.loadAllPriorSteps();
-        stepController.setRequest();
         controller.connectOutlet('kerberosWizardStep6', controller.get('content'));
       });
     },
-    retry: function (router) {
-      router.get('kerberosWizardStep6Controller').setRequest(true);
-    },
     unroutePath: function () {
       return false;
     },
     back: Em.Router.transitionTo('step4'),
     next: function (router) {
-      router.transitionTo('step7');
+      var kerberosWizardController = router.get('kerberosWizardController');
+      kerberosWizardController.setDBProperty('tasksStatuses', null);
+      kerberosWizardController.setDBProperty('tasksRequestIds', null);
+      var step7Controller = router.get('kerberosWizardStep7Controller');
+      var kerberosDescriptor = kerberosWizardController.get('kerberosDescriptorConfigs');
+      step7Controller.postKerberosDescriptor(kerberosDescriptor).always(function (data, result, request) {
+        if (result === 'error' && data.status === 409) {
+          step7Controller.putKerberosDescriptor(kerberosDescriptor);
+        } else {
+          step7Controller.unkerberizeCluster();
+        }
+      });
     }
   }),
 
@@ -294,17 +323,44 @@ module.exports = App.WizardRoute.extend({
     connectOutlets: function (router) {
       console.log('in kerberosWizardController.step7:connectOutlets');
       var controller = router.get('kerberosWizardController');
+      var step7Controller = router.get('kerberosWizardStep7Controller');
       controller.dataLoading().done(function () {
         router.get('kerberosWizardController').setCurrentStep('7');
         controller.setLowerStepsDisable(7);
         controller.loadAllPriorSteps();
+        step7Controller.setRequest();
         controller.connectOutlet('kerberosWizardStep7', controller.get('content'));
       });
     },
+    retry: function (router) {
+      router.get('kerberosWizardStep7Controller').setRequest(true);
+    },
+    unroutePath: function () {
+      return false;
+    },
+    back: Em.Router.transitionTo('step4'),
+    next: function (router) {
+      router.transitionTo('step8');
+    }
+  }),
+
+  step8: Em.Route.extend({
+    route: '/step8',
+
+    connectOutlets: function (router) {
+      console.log('in kerberosWizardController.step8:connectOutlets');
+      var controller = router.get('kerberosWizardController');
+      controller.dataLoading().done(function () {
+        router.get('kerberosWizardController').setCurrentStep('8');
+        controller.setLowerStepsDisable(8);
+        controller.loadAllPriorSteps();
+        controller.connectOutlet('kerberosWizardStep8', controller.get('content'));
+      });
+    },
     unroutePath: function () {
       return false;
     },
-    back: Em.Router.transitionTo('step6'),
+    back: Em.Router.transitionTo('step7'),
     next: function (router) {
       var controller = router.get('kerberosWizardController');
       controller.finish();

+ 5 - 2
ambari-web/app/styles/application.less

@@ -1466,6 +1466,9 @@ a:focus {
 }
 
 /*****start styles for host component popup*****/
+#modal {
+  outline: none;
+}
 .host-progress-popup {
   .modal-body, .modal-footer, .modal-header {
     min-width: 600px;
@@ -3012,7 +3015,7 @@ table.graphs {
   }
   .filter-input-width{
     width:65%;
-    
+
     &.rack-input {
       width: 85%;
     }
@@ -5698,4 +5701,4 @@ input[type="radio"].align-checkbox, input[type="checkbox"].align-checkbox {
 
 .config-widget-left-popover {
   margin-left: -10px;
-}
+}

+ 1 - 2
ambari-web/app/templates/main/admin/kerberos/step1.hbs

@@ -44,8 +44,7 @@
     {{/each}}
   </div>
 
-
   <div class="btn-area">
     <a id="submit-kerberos-step1" class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action "next" target="controller"}}>{{t common.next}} &rarr;</a>
   </div>
-</div>
+</div>

+ 28 - 2
ambari-web/app/templates/main/admin/kerberos/step5.hbs

@@ -15,7 +15,33 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 }}
-
 <div id="kerberos-wizard-step5">
-  {{template "templates/common/progress"}}
+  <div id="confirm-configuration">
+    <h2>{{t admin.kerberos.wizard.step5.header}}</h2>
+
+    <p class="alert alert-info">
+      {{t admin.kerberos.wizard.step5.info.body}}
+    </p>
+
+    <div class="well pre-scrollable">
+      <p><strong>{{t installer.step0.clusterName.tooltip.title}}</strong>: {{App.router.clusterController.clusterName}}</p>
+      <p><strong>{{t admin.kerberos.wizard.step1.option.manual}}</strong>: {{App.router.kerberosWizardController.skipClientInstall}}</p>
+      {{#each App.router.kerberosWizardController.content.serviceConfigProperties}}
+        {{#if value}}
+          <p><strong>{{name}}</strong>: {{value}}</p>
+        {{/if}}
+      {{/each}}
+    </div>
+
+    <div class="additional btn-area">
+      <button class="btn btn-danger" {{action exitWizard}}>{{t admin.kerberos.wizard.step5.exitWizard}}</button>
+      <button class="btn btn-primary pull-right" {{action downloadCSV}}>{{t admin.kerberos.wizard.step5.downloadCSV}}</button>
+    </div>
+
+    <div class="btn-area">
+      <button id="back-kerberos-step5" class="btn" {{action back}}>&larr; {{t common.back}}</button>
+      <button id="submit-kerberos-step5" class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}}
+        {{action submit target="controller"}}>{{t common.next}} &rarr;</button>
+    </div>
+  </div>
 </div>

+ 1 - 1
ambari-web/app/templates/main/admin/kerberos/step6.hbs

@@ -17,4 +17,4 @@
 }}
 <div id="kerberos-wizard-step6">
   {{template "templates/common/progress"}}
-</div>
+</div>

+ 20 - 0
ambari-web/app/templates/main/admin/kerberos/step8.hbs

@@ -0,0 +1,20 @@
+{{!
+* 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.
+}}
+<div id="kerberos-wizard-step8">
+  {{template "templates/common/progress"}}
+</div>

+ 1 - 0
ambari-web/app/templates/main/admin/kerberos/wizard.hbs

@@ -32,6 +32,7 @@
               <li {{bindAttr class="isStep5:active view.isStep5Disabled:disabled"}}><a href="javascript:void(null);"  {{action gotoStep5 target="controller"}}>{{t admin.kerberos.wizard.step5.header}}</a></li>
               <li {{bindAttr class="isStep6:active view.isStep6Disabled:disabled"}}><a href="javascript:void(null);"  {{action gotoStep6 target="controller"}}>{{t admin.kerberos.wizard.step6.header}}</a></li>
               <li {{bindAttr class="isStep7:active view.isStep7Disabled:disabled"}}><a href="javascript:void(null);"  {{action gotoStep7 target="controller"}}>{{t admin.kerberos.wizard.step7.header}}</a></li>
+              <li {{bindAttr class="isStep8:active view.isStep8Disabled:disabled"}}><a href="javascript:void(null);"  {{action gotoStep8 target="controller"}}>{{t admin.kerberos.wizard.step8.header}}</a></li>
             </ul>
           </div>
         </div>

+ 10 - 0
ambari-web/app/utils/ajax/ajax.js

@@ -1427,6 +1427,16 @@ var urls = {
       }
     }
   },
+  'admin.kerberos.cluster.csv': {
+    'real': '/clusters/{clusterName}/kerberos_identities?fields=*&format=csv',
+    'mock': '',
+    'format': function(data) {
+      return {
+        dataType: 'text',
+        data: data.data
+      }
+    }
+  },
   'admin.poll.kerberize.cluster.request': {
     'real': '/clusters/{clusterName}/requests/{requestId}?fields=stages/Stage/context,stages/Stage/status,stages/Stage/progress_percent,stages/tasks/*,Requests/*',
     'mock': '/data/wizard/kerberos/kerberize_cluster.json'

+ 1 - 0
ambari-web/app/views.js

@@ -174,6 +174,7 @@ require('views/main/admin/kerberos/step4_view');
 require('views/main/admin/kerberos/step5_view');
 require('views/main/admin/kerberos/step6_view');
 require('views/main/admin/kerberos/step7_view');
+require('views/main/admin/kerberos/step8_view');
 
 require('views/main/admin/security');
 require('views/main/admin/security/disable');

+ 10 - 4
ambari-web/app/views/common/configs/service_configs_by_category_view.js

@@ -45,6 +45,7 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri
    */
   categoryConfigs: function () {
     var categoryConfigs = this.get('categoryConfigsAll');
+
     return this.orderContentAtLast(this.sortByIndex(categoryConfigs)).filterProperty('isVisible', true);
   }.property('categoryConfigsAll.@each.isVisible').cacheable(),
 
@@ -55,9 +56,14 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri
    * MySQL etc. database options don't show up, because
    * they were not visible initially.
    */
-  categoryConfigsAll: function () {
-    return this.get('serviceConfigs').filterProperty('category', this.get('category.name'));
-  }.property('serviceConfigs.@each').cacheable(),
+   categoryConfigsAll: function () {
+     var configs = this.get('serviceConfigs').filterProperty('category', this.get('category.name'));
+
+     if (this.get('service.serviceName') === 'KERBEROS' && App.router.get('kerberosWizardController.skipClientInstall')) {
+       App.router.get('kerberosWizardController').overrideVisibility(configs, false);
+     }
+     return configs;
+   }.property('serviceConfigs.@each').cacheable(),
 
   /**
    * If added/removed a serverConfigObject, this property got updated.
@@ -146,7 +152,7 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri
       this.affectedProperties = serviceConfigModificationHandler.getDependentConfigChanges(changedProperty, this.get("controller.selectedServiceNames"), stepConfigs, securityEnabled);
     }
     changedProperty.set("editDone", false); // Turn off flag
-    
+
     if (this.affectedProperties.length > 0 && !this.get("controller.miscModalVisible")) {
       this.newAffectedProperties = this.affectedProperties;
       var self = this;

+ 1 - 7
ambari-web/app/views/main/admin/kerberos/step5_view.js

@@ -20,11 +20,5 @@ var App = require('app');
 
 App.KerberosWizardStep5View = App.KerberosProgressPageView.extend({
 
-  templateName: require('templates/main/admin/kerberos/step5'),
-
-  noticeCompleted: Em.I18n.t('admin.kerberos.wizard.step5.notice.completed'),
-
-  submitButtonText: Em.I18n.t('common.next') + '&rarr;',
-
-  showBackButton: true
+  templateName: require('templates/main/admin/kerberos/step5')
 });

+ 1 - 2
ambari-web/app/views/main/admin/kerberos/step6_view.js

@@ -27,5 +27,4 @@ App.KerberosWizardStep6View = App.KerberosProgressPageView.extend({
   submitButtonText: Em.I18n.t('common.next') + '&rarr;',
 
   showBackButton: true
-
-});
+});

+ 4 - 5
ambari-web/app/views/main/admin/kerberos/step7_view.js

@@ -15,6 +15,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 var App = require('app');
 
 App.KerberosWizardStep7View = App.KerberosProgressPageView.extend({
@@ -23,10 +24,8 @@ App.KerberosWizardStep7View = App.KerberosProgressPageView.extend({
 
   noticeCompleted: Em.I18n.t('admin.kerberos.wizard.step7.notice.completed'),
 
-  noticeFailed: Em.I18n.t('admin.kerberos.wizard.step7.notice.failed'),
-
-  submitButtonText: Em.I18n.t('common.complete'),
+  submitButtonText: Em.I18n.t('common.next') + '&rarr;',
 
-  showBackButton: false
+  showBackButton: true
 
-});
+});

+ 31 - 0
ambari-web/app/views/main/admin/kerberos/step8_view.js

@@ -0,0 +1,31 @@
+/**
+ * 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');
+
+App.KerberosWizardStep8View = App.KerberosProgressPageView.extend({
+
+  templateName: require('templates/main/admin/kerberos/step8'),
+
+  noticeCompleted: Em.I18n.t('admin.kerberos.wizard.step8.notice.completed'),
+
+  noticeFailed: Em.I18n.t('admin.kerberos.wizard.step8.notice.failed'),
+
+  submitButtonText: Em.I18n.t('common.complete'),
+
+  showBackButton: false
+});

+ 0 - 2
ambari-web/app/views/main/admin/kerberos/wizard_view.js

@@ -22,5 +22,3 @@ App.KerberosWizardView = Em.View.extend(App.WizardMenuMixin, {
 
   templateName: require('templates/main/admin/kerberos/wizard')
 });
-
-

+ 2 - 2
ambari-web/test/controllers/main/admin/kerberos/step5_controller_test.js → ambari-web/test/controllers/main/admin/kerberos/step6_controller_test.js

@@ -18,7 +18,7 @@
 
 var App = require('app');
 
-describe('App.KerberosWizardStep5Controller', function() {
+describe('App.KerberosWizardStep6Controller', function() {
   describe('#checkComponentsRemoval', function() {
 
     var tests = [
@@ -31,7 +31,7 @@ describe('App.KerberosWizardStep5Controller', function() {
 
     tests.forEach(function(test) {
       it('YARN installed: {0}, ATS supported: {1} list of commands should be {2}'.format(test.yarnInstalled, test.doesATSSupportKerberos, test.commands.toString()), function () {
-        var controller = App.KerberosWizardStep5Controller.create({ commands: ['stopServices'] });
+        var controller = App.KerberosWizardStep6Controller.create({ commands: ['stopServices'] });
         sinon.stub(App, 'get').withArgs('doesATSSupportKerberos').returns(test.doesATSSupportKerberos);
         sinon.stub(App.Service, 'find').returns(test.yarnInstalled ? [Em.Object.create({ serviceName: 'YARN'})] : []);
         sinon.stub(App.HostComponent, 'find').returns(test.ATSInstalled ? [Em.Object.create({ componentName: 'APP_TIMELINE_SERVER'})] : []);