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

jaimin pushed a commit to branch branch-feature-AMBARI-14714-ui
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/branch-feature-AMBARI-14714-ui 
by this push:
     new efae1bc  [AMBARI-22826] Mpack related changes to Add Hosts Page. (#200)
efae1bc is described below

commit efae1bc0c47c9b50b0d1a63f2e03c0b571f929a3
Author: Ishan Bhatt <[email protected]>
AuthorDate: Fri Jan 26 17:27:29 2018 -0800

    [AMBARI-22826] Mpack related changes to Add Hosts Page. (#200)
---
 ambari-web/app/controllers/wizard.js               |   8 +-
 .../app/controllers/wizard/step2_controller.js     | 187 ++++++++++++++-------
 ambari-web/app/messages.js                         |  23 ++-
 ambari-web/app/styles/wizard.less                  | 119 ++++++++++++-
 ambari-web/app/templates/wizard/step2.hbs          | 147 +++++++++-------
 ambari-web/app/utils/ajax/ajax.js                  |   4 +
 ambari-web/app/views/wizard/step2_view.js          |  12 +-
 ambari-web/test/controllers/wizard/step2_test.js   | 117 ++++---------
 ambari-web/test/views/wizard/step2_view_test.js    |  30 +---
 9 files changed, 387 insertions(+), 260 deletions(-)

diff --git a/ambari-web/app/controllers/wizard.js 
b/ambari-web/app/controllers/wizard.js
index 7ef227c..f094851 100644
--- a/ambari-web/app/controllers/wizard.js
+++ b/ambari-web/app/controllers/wizard.js
@@ -704,8 +704,8 @@ App.WizardController = 
Em.Controller.extend(App.LocalStorage, App.ThemesMappingM
 
   installOptionsTemplate: {
     hostNames: "", //string
-    manualInstall: false, //true, false
-    useSsh: true, //bool
+    manualInstall: true, //true, false
+    useSsh: false, //bool
     javaHome: App.defaultJavaHome, //string
     localRepo: false, //true, false
     sshKey: "", //string
@@ -717,8 +717,8 @@ App.WizardController = 
Em.Controller.extend(App.LocalStorage, App.ThemesMappingM
 
   installWindowsOptionsTemplate: {
     hostNames: "", //string
-    manualInstall: false, //true, false
-    useSsh: true, //bool
+    manualInstall: true, //true, false
+    useSsh: false, //bool
     javaHome: App.defaultJavaHome, //string
     localRepo: false, //true, false
     sshKey: "", //string
diff --git a/ambari-web/app/controllers/wizard/step2_controller.js 
b/ambari-web/app/controllers/wizard/step2_controller.js
index c6da054..7caa3c6 100644
--- a/ambari-web/app/controllers/wizard/step2_controller.js
+++ b/ambari-web/app/controllers/wizard/step2_controller.js
@@ -25,6 +25,14 @@ App.WizardStep2Controller = App.WizardStepController.extend({
 
   name: 'wizardStep2Controller',
 
+  parsedHostsText: 
Em.I18n.t('installer.step2.parsedHostsPlaceholder').format(0),
+
+  preRegisteredHostFound: 
Em.I18n.t('installer.step2.preRegistered.hostCount').format(0),
+
+  manuallyInstalledHosts: [],
+
+  noPreRegisteredHosts: true,
+
   stepName: 'step2',
 
   /**
@@ -55,6 +63,8 @@ App.WizardStep2Controller = App.WizardStepController.extend({
    */
   inputtedAgainHostNames: [],
 
+  filterText: null,
+
   /**
    * Is Installer Controller used
    * @type {bool}
@@ -130,12 +140,24 @@ App.WizardStep2Controller = 
App.WizardStepController.extend({
     return !App.get('isHadoopWindowsStack');
   }.property('App.isHadoopWindowsStack'),
 
+  useSshRegistration: function () {
+    this.set('content.installOptions.manualInstall', false);
+    this.set('content.installOptions.useSsh', true);
+  },
+
+  useManualInstall: function () {
+    if (!this.get('content.installOptions.manualInstall')) {
+      this.getManuallyInstalledHosts();
+    }
+    this.set('content.installOptions.manualInstall', true);
+    this.set('content.installOptions.useSsh', false);
+  },
   /**
    * Error-message if <code>sshKey</code> is empty, null otherwise
    * @type {string|null}
    */
   sshKeyError: function () {
-    if (this.get('hasSubmitted') && this.get('manualInstall') === false && 
this.get('useSSH') && Em.isBlank(this.get('sshKey'))) {
+    if (this.get('hasSubmitted') && this.get('manualInstall') === false && 
!this.get('manualInstall') && Em.isBlank(this.get('sshKey'))) {
       return Em.I18n.t('installer.step2.sshKey.error.required');
     }
     return null;
@@ -174,11 +196,13 @@ App.WizardStep2Controller = 
App.WizardStepController.extend({
     return null;
   }.property('agentUser', 'hasSubmitted', 'manualInstall'),
 
+  preRegisteredHostsError: Em.computed.and('manualInstall' 
,'noPreRegisteredHosts'),
+
   /**
    * is Submit button disabled
    * @type {bool}
    */
-  isSubmitDisabled: Em.computed.or('hostsError', 'sshKeyError', 
'sshUserError', 'sshPortError', 'agentUserError', 
'App.router.btnClickInProgress'),
+  isSubmitDisabled: Em.computed.or('hostsError', 'sshKeyError', 
'sshUserError', 'sshPortError', 'agentUserError', 
'App.router.btnClickInProgress', 'preRegisteredHostsError'),
 
   loadStep: function () {
     //save initial hostNames value to check later if changes were made
@@ -198,21 +222,87 @@ App.WizardStep2Controller = 
App.WizardStepController.extend({
   }.property('content.hosts'),
 
   /**
+  * get hosts that are installed manually
+  return
+  */
+  getManuallyInstalledHosts: function () {
+    App.ajax.send({
+      name: 'hosts.confirmed.install',
+      sender: this,
+      success: 'getManuallyInstalledHostsSuccessCallback'
+    });
+  },
+
+  getManuallyInstalledHostsSuccessCallback(response) {
+    var installedHosts = [],
+          self = this;
+    if (response.items.length > 0) {
+      response.items.forEach(function (item, indx) {
+        installedHosts.push(Em.Object.create({
+          'controller': self,
+          'hostName': item.Hosts.host_name,
+          'cpuCount': item.Hosts.cpu_count,
+          'memory': (parseFloat(item.Hosts.total_mem) / (1024 * 
1024)).toFixed(2) + " GB",
+          'freeSpace': (parseFloat(item.Hosts.disk_info[0].available) / (1024 
* 1024)).toFixed(2) + " GB",
+          'isVisible': true,
+
+          filterRow: function() {
+            var filter = self.get('filterText');
+            if(filter && 
!(item.Hosts.host_name.toUpperCase().indexOf(filter.toUpperCase()) > -1)) {
+              this.set('isVisible', false);
+            } else {
+              this.set('isVisible', true);
+            }
+          }.observes('controller.filterText')
+        }));
+      });
+      this.set('preRegisteredHostFound', 
Em.I18n.t('installer.step2.preRegistered.hostCount').format(installedHosts.length));
+      this.set('manuallyInstalledHosts', installedHosts);
+      this.set('noPreRegisteredHosts', false);
+    } else {
+      this.set('preRegisteredHostFound', 
Em.I18n.t('installer.step2.preRegistered.hostCount').format(0));
+      this.set('noPreRegisteredHosts', true);
+      this.set('manuallyInstalledHosts', []);
+    }
+  },
+
+  deleteRegisteredHost: function (event) {
+    var hostName = event.context;
+    App.ajax.send({
+      name: 'common.delete.registered.host',
+      sender: this,
+      data: {
+        hostName: event.context
+      },
+      success: 'deleteRegisteredHostSuccessCallback'
+    });
+  },
+
+  deleteRegisteredHostSuccessCallback: function (response) {
+    this.getManuallyInstalledHosts();
+  },
+
+  /**
    * Set not installed hosts to the hostNameArr
    * @method updateHostNameArr
    */
   updateHostNameArr: function () {
-    this.set('hostNameArr', this.get('hostNames').trim().split(new 
RegExp("\\s+", "g")));
-    this.parseHostNamesAsPatternExpression();
-    this.get('inputtedAgainHostNames').clear();
-    var tempArr = [],
-        hostNameArr = this.get('hostNameArr');
-    for (var i = 0; i < hostNameArr.length; i++) {
-      if (!this.get('installedHostNames').contains(hostNameArr[i])) {
-        tempArr.push(hostNameArr[i]);
-      }
-      else {
-        this.get('inputtedAgainHostNames').push(hostNameArr[i]);
+    var tempArr = [];
+    if (this.get('manualInstall')) {
+      tempArr = this.get('manuallyInstalledHosts').mapProperty('hostName');
+    } else {
+      this.set('hostNameArr', this.get('hostNames').trim().split(new 
RegExp("\\s+", "g")));
+      this.parseHostNamesAsPatternExpression();
+      this.get('inputtedAgainHostNames').clear();
+
+      var hostNameArr = this.get('hostNameArr');
+      for (var i = 0; i < hostNameArr.length; i++) {
+        if (!this.get('installedHostNames').contains(hostNameArr[i])) {
+          tempArr.push(hostNameArr[i]);
+        }
+        else {
+          this.get('inputtedAgainHostNames').push(hostNameArr[i]);
+        }
       }
     }
     this.set('hostNameArr', tempArr);
@@ -237,12 +327,22 @@ App.WizardStep2Controller = 
App.WizardStepController.extend({
     return result;
   },
 
+  parseHosts: function () {
+    var hostNames = this.get('hostNames').trim().split(new RegExp("\\s+", 
"g"));
+    if (hostNames[0] == "") {
+      this.set('parsedHostsText', 
Em.I18n.t('installer.step2.parsedHostsPlaceholder').format(0));
+    } else {
+      var parsedHostNames = this.parseHostNamesAsPatternExpression(hostNames);
+      this.set('parsedHostsText', 
(Em.I18n.t('installer.step2.parsedHostsPlaceholder').format(parsedHostNames.length)
 + '\n' + parsedHostNames.join('\n')));
+    }
+  }.observes('hostNames'),
+
   /**
    * Set hostsError if host names don't pass validation
    * @method checkHostError
    */
   checkHostError: function () {
-    if (Em.isEmpty(this.get('hostNames').trim())) {
+    if (!this.get('manualInstall') && 
Em.isEmpty(this.get('hostNames').trim())) {
       this.set('hostsError', 
Em.I18n.t('installer.step2.hostName.error.required'));
     }
     else {
@@ -314,10 +414,6 @@ App.WizardStep2Controller = 
App.WizardStepController.extend({
       return false;
     }
 
-    if (this.get('isPattern')) {
-      this.hostNamePatternPopup(this.get('hostNameArr'));
-      return false;
-    }
     if (this.get('inputtedAgainHostNames.length')) {
       this.installedHostsPopup();
     }
@@ -332,11 +428,13 @@ App.WizardStep2Controller = 
App.WizardStepController.extend({
    * push hosts that match pattern in hostNameArr
    * @method parseHostNamesAsPatternExpression
    */
-  parseHostNamesAsPatternExpression: function () {
+  parseHostNamesAsPatternExpression: function (hostNamesToBeParsed) {
     this.set('isPattern', false);
     var hostNames = [];
 
-    this.get('hostNameArr').forEach(function (a) {
+    var hostNameArr = hostNamesToBeParsed || this.get('hostNameArr');
+
+    hostNameArr.forEach(function (a) {
       var hn,
           allPatterns = a.match(/\[\d*\-\d*\]/g),
           patternsNumber = allPatterns ? allPatterns.length : 0;
@@ -352,7 +450,11 @@ App.WizardStep2Controller = 
App.WizardStepController.extend({
       }
     }, this);
 
-    this.set('hostNameArr', hostNames.uniq());
+    if(hostNamesToBeParsed) {
+      return hostNames;
+    } else {
+      this.set('hostNameArr', hostNames.uniq());
+    }
   },
 
   /**
@@ -406,12 +508,6 @@ App.WizardStep2Controller = 
App.WizardStepController.extend({
       this.warningPopup();
       return false;
     }
-
-    if (this.get('manualInstall') === true) {
-      this.manualInstallPopup();
-      return false;
-    }
-
     this.saveHosts();
     App.router.send('next');
     return true;
@@ -491,43 +587,6 @@ App.WizardStep2Controller = 
App.WizardStepController.extend({
   },
 
   /**
-   * Show notify that installation is manual
-   * save hosts
-   * @return {App.ModalPopup}
-   * @method manualInstallPopup
-   */
-  manualInstallPopup: function () {
-    var self = this;
-    return App.ModalPopup.show({
-      header: Em.I18n.t('installer.step2.manualInstall.popup.header'),
-      onPrimary: function () {
-        this.hide();
-        self.saveHosts();
-        App.router.send('next');
-      },
-      bodyClass: Em.View.extend({
-        templateName: require('templates/wizard/step2ManualInstallPopup')
-      })
-    });
-  },
-
-  /**
-   * Warn to manually install ambari-agent on each host
-   * @method manualInstallWarningPopup
-   */
-  manualInstallWarningPopup: function () {
-    if (!this.get('content.installOptions.useSsh')) {
-      App.ModalPopup.show({
-        header: Em.I18n.t('common.warning'),
-        body: Em.I18n.t('installer.step2.manualInstall.info'),
-        encodeBody: false,
-        secondary: null
-      });
-    }
-    this.set('content.installOptions.manualInstall', 
!this.get('content.installOptions.useSsh'));
-  }.observes('content.installOptions.useSsh'),
-
-  /**
    * Load java.home value frin server
    * @method setAmbariJavaHome
    */
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 55e2f17..70705ce 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -229,6 +229,8 @@ Em.I18n.translations = {
   'common.more': 'More...',
   'common.move':'Move',
   'common.mpack': 'Management Pack',
+  'common.freeStorage': 'Free Storage',
+  'common.noHostsFound': 'No Hosts found.',
   'common.na': 'n/a',
   'common.name':'Name',
   'common.next':'Next',
@@ -734,10 +736,11 @@ Em.I18n.translations = {
   'installer.step1.checkAtLeastOneAttention': '<b>Attention:</b> Please check 
at least one repository.',
   'installer.step1.retryRepoUrls': 'Click <b>here</b> to retry.',
 
-  'installer.step2.header':'Install Options',
-  'installer.step2.body':'Enter the list of hosts to be included in the 
cluster and provide your SSH key.',
-  'installer.step2.targetHosts':'Target Hosts',
-  'installer.step2.targetHosts.info':'Enter a list of hosts using the Fully 
Qualified Domain Name (FQDN), one per line',
+  'installer.step2.header':'Add Hosts',
+  'installer.step2.registration.body1' : 'Ambari Agents can be automatically 
installed using SSH, or they can be manually installed and registered with the 
Ambari Server.',
+  'installer.step2.registration.body2' : 'Please choose the installation type 
below:',
+  'installer.step2.enterHosts':'Enter Hosts',
+  'installer.step2.enterHosts.info':'Enter a list of hosts using the Fully 
Qualified Domain Name (FQDN), one per line',
   'installer.step2.hostPattern.tooltip.title':'Pattern Expressions',
   'installer.step2.hostPattern.tooltip.content':'You can use pattern 
expressions to specify a number of target hosts. For example, to specify 
host01.domain thru host10.domain, enter host[01-10].domain in the target hosts 
textarea.',
   'installer.step2.hostName.error.required':'You must specify at least one 
host name',
@@ -768,15 +771,18 @@ Em.I18n.translations = {
   'installer.step2.javaHome.tooltip.title' : 'JAVA_HOME',
   'installer.step2.javaHome.tooltip.content' : 'Path to 64-bit JAVA_HOME. 
/usr/jdk/jdk1.6.0_31 is the default used by Ambari. You can override this to a 
specific path that contains the JDK. <br/> Note: the path must be valid on 
<b>ALL</b> hosts in your cluster.',
   'installer.step2.javaHome.tooltip.placeholder' : '/usr/jdk/jdk1.6.0_31',
+  'installer.step2.automaticInstall' : 'Register Agents automatically',
   'installer.step2.automaticInstall.tooltip.title':'automatic registration',
   'installer.step2.automaticInstall.tooltip.content':'Ambari will 
automatically install and register the Ambari Agent on each host prior to the 
cluster installation.',
   'installer.step2.useSsh.provide' : 'Provide your',
   'installer.step2.useSsh.provide_id_rsa' : ' to automatically register hosts',
   'installer.step2.useSsh.tooltip.title':'SSH Private Key',
   'installer.step2.useSsh.tooltip.content':'The <b>SSH Private Key File</b> is 
used to connect to the target hosts in your cluster to install the Ambari 
Agent.',
+  'installer.step2.useSsh' : 'Register Agents Using SSH',
   'installer.step2.install.perform':'Perform',
   'installer.step2.install.perform_on_hosts':'on hosts',
   'installer.step2.install.without_ssh':' and do not use SSH',
+  'installer.step2.manualInstall' : 'Register Agents Manually',
   'installer.step2.manualInstall.tooltip.title':'manual registration',
   'installer.step2.manualInstall.tooltip.content':'Manually registering the 
Ambari Agent on each host eliminates the need for SSH and should be performed 
prior to continuing cluster installation.',
   'installer.step2.manualInstall.tooltip.content_no_ssh':'Manually registering 
the Ambari Agent on each host should be performed prior to continuing cluster 
installation.',
@@ -803,6 +809,15 @@ Em.I18n.translations = {
   'installer.step2.skipHostChecks.label': 'Skip host checks',
   'installer.step2.skipHostChecks.popup.header': 'Warning',
   'installer.step2.skipHostChecks.popup.body': 'By skipping host checks, 
Ambari will not check and warn if any issues with the host are identified and 
the host will be added to the cluster as is.',
+  'installer.step2.parsedHostsPlaceholder' : '{0} HOSTS ADDED',
+  'installer.step2.preRegistered.hostCount': 'We found <strong>{0}</strong> 
registered hosts.',
+  'installer.step2.noHostsFound.header': 'Please follow the following steps to 
register hosts manually. Refresh the table to see the updated list.',
+  'installer.step2.noHostsFound.step1': '1. Lorem ipsum dolor sit amet, 
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et.',
+  'installer.step2.noHostsFound.step2': '2. Lorem ipsum dolor sit amet, 
consectetur adipiscing elit, sed do eiusmod tempor.',
+  'installer.step2.noHostsFound.step3': '3. Lorem ipsum dolor sit amet, 
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et 
dolore.',
+  'installer.step2.noHostsFound.step4': '4. Lorem ipsum dolor sit amet, 
consectetur adipiscing elit.',
+  'installer.step2.noHostsFound.learn': '<a 
href="https://docs.hortonworks.com/HDPDocuments/Ambari-2.6.0.0/bk_ambari-administration/content/ch_amb_ref_installing_ambari_agents_manually.html";
 target="_blank"><u>Learn More</u></a>',
+  'installer.step2.refresh.table': 'REFRESH TABLE',
 
   'installer.step3.header':'Confirm Hosts',
   'installer.step3.body':'Registering your hosts.<br>' +
diff --git a/ambari-web/app/styles/wizard.less 
b/ambari-web/app/styles/wizard.less
index 8051f6e..129c812 100644
--- a/ambari-web/app/styles/wizard.less
+++ b/ambari-web/app/styles/wizard.less
@@ -64,22 +64,121 @@
   }
 
   #installOptions {
-    #targetHosts {
-      .step-title {
-        margin-bottom: 10px;
-      }
+    .step-description {
+      color: #999;
+      font-size: 11px;
     }
     .radio-button-options {
-      margin-top: 10px;
-      margin-bottom: 10px;
+      padding-bottom: 10px;
+      color: #666;
+      .radio.big-radio {
+        height: 100px;
+        background-color: #dddddd;
+        width: 115px;
+        margin: 15px;
+        padding-left: 0;
+        padding-right: 0;
+        border-radius: 4px;
+        float: left;
+        input[type="radio"] + label, p, .repo-group, {
+          cursor: default;
+        }
+        input[type="radio"] + label:before {
+          border-color: #999;
+          background-color: #fff;
+        }
+        input[type="radio"]:checked + label:before {
+          background: #fff;
+          border-color: #3FAE2A;
+        }
+        input[type="radio"]:checked + label:after {
+          background-color: #3FAE2A;
+        }
+        .repo-checkbox {
+          padding: 0 5px;
+          margin-top: 5px;
+        }
+        .icon {
+          font-size: 37px;
+          text-align: center;
+          position: absolute;
+          top: 15px;
+          padding: 0 20px;
+          width: 100%;
+          color: #fff;
+        }
+        .repo-group {
+          bottom: 0px;
+          position: absolute;
+          background-color: #3FAE2A;
+          color: white;
+          width: 100%;
+          font-size: 12px;
+          text-align: center;
+          border-radius: 2px;
+        }
+      }
     }
     .wizard-plain-text {
-      color: #666;
+      font-weight: normal;
     }
     .ssh-user, .ssh-port {
       padding-top: 8px;
     }
 
+    #host-names, #parsed-host-names {
+      font-size: 12px;
+    }
+
+    #parsed-host-names {
+      background-color: #eee;
+    }
+
+    .hosts-filter-box {
+      padding-right: 5px;
+      .form-control:after {
+        content: '\f080';
+      }
+    }
+
+    .hosts-table-options {
+      overflow: auto;
+      margin-bottom: 20px;
+      .icon-undo {
+        color: #666;
+      }
+      .host-count {
+        color: #666;
+        font-size: 12px;
+        padding-top: 10px;
+      }
+    }
+
+    .no-pre-registered{
+      color: #999;
+      font-size: 10px;
+      p {
+        margin-left: 30px;
+      }
+      .no-host-header {
+        font-size: 30px;
+        margin: 20px 0px 0px 30px;
+      }
+      .no-host-title {
+        font-size: 12px;
+      }
+    }
+
+    .pre-registered{
+      a {
+        color: #666;
+        text-decoration: none;
+        i {
+          color: #999;
+        }
+      }
+    }
+
     #sshKey {
       color: #555;
       font-family: "Courier New","courier";
@@ -104,6 +203,12 @@
         color: #666;
       }
     }
+    .icon-ellipsis-vertical {
+      margin-top: auto;
+      margin-bottom: auto;
+      color: #999;
+      font-size: 18px;
+    }
 
   }
   #confirm-hosts {
diff --git a/ambari-web/app/templates/wizard/step2.hbs 
b/ambari-web/app/templates/wizard/step2.hbs
index c141ed0..7d523b9 100644
--- a/ambari-web/app/templates/wizard/step2.hbs
+++ b/ambari-web/app/templates/wizard/step2.hbs
@@ -19,15 +19,40 @@
 <div id="installOptions" class="wizard-content col-md-9">
   <h4 class="step-title">{{t installer.step2.header}}</h4>
   {{#if isSaved}}
-  <div class="alert alert-warning" role="alert"><strong>{{t 
installer.warning.changes.header}}</strong> {{t 
installer.warning.changes}}</div>
+    <div class="alert alert-warning" role="alert"><strong>{{t 
installer.warning.changes.header}}</strong> {{t 
installer.warning.changes}}</div>
   {{/if}}
 
   <div class="panel panel-default">
     <div class="panel-body">
-      <div id="targetHosts" {{QAAttr "target-hosts"}}>
-        <div class="step-title" {{QAAttr "target-hosts-title"}}>{{t 
installer.step2.targetHosts}}</div>
+      <div class="step-description">
+        <div>{{t installer.step2.registration.body1}}</div>
+        {{t installer.step2.registration.body2}}
+      </div>
+      <div class="row radio-button-options">
+        <div {{bindAttr class=":col-sm-4 :radio :big-radio :manual-radio 
:public-radio :wizard-plain-text 
controller.content.installOptions.manualInstall:repo-selected:repo-not-selected"}}
 {{action useManualInstall target="controller"}}>
+          {{#view view.manualRegistrationRadioButton 
classNames="repo-checkbox" 
labelIdentifier="manual-registration-radio-button"}}{{/view}}
+          <i class="icon icon-edit"></i>
+          <div class="repo-group">
+            {{t installer.step2.manualInstall}}
+          </div>
+        </div>
+        <div {{bindAttr class=":col-sm-4 :radio :big-radio :ssh-radio 
:public-radio :wizard-plain-text 
controller.content.installOptions.useSsh:repo-selected:repo-not-selected"}} 
{{action useSshRegistration target="controller"}}>
+          {{#view view.providingSSHKeyRadioButton classNames="repo-checkbox" 
labelIdentifier="ssh-key-radio-button"}}{{/view}}
+          <i class="icon icon-lock"></i>
+          <div class="repo-group">
+            {{#if useSSH}}
+              {{t installer.step2.useSsh}}
+            {{else}}
+              {{t installer.step2.automaticInstall}}
+            {{/if}}
+          </div>
+        </div>
+      </div>
+
+      <div id="targetHosts" {{QAAttr "target-hosts"}} {{bindAttr 
class="controller.content.installOptions.useSsh:display:noDisplay"}}>
+        <div {{QAAttr "target-hosts-title"}}>{{t 
installer.step2.enterHosts}}</div>
         <div {{bindAttr class="hostsError:has-error :form-group 
:target-hosts-input"}}>
-          <p class="wizard-plain-text" {{QAAttr 
"target-hosts-description"}}>{{t installer.step2.targetHosts.info}}. {{t 
installer.step2.orUse}}
+          <p class="step-description" {{QAAttr 
"target-hosts-description"}}>{{t installer.step2.enterHosts.info}}. {{t 
installer.step2.orUse}}
             <a href="javascript:void(null)"
                rel="popover"
               {{translateAttr 
title="installer.step2.hostPattern.tooltip.title" 
data-content="installer.step2.hostPattern.tooltip.content"}}
@@ -36,10 +61,14 @@
             </a>
           </p>
 
-          <div class="row">
-            <div class="col-md-8">
+          <div class="row display-flex">
+            <div class="col-md-7">
               {{view Ember.TextArea id="host-names" class="form-control" 
valueBinding="content.installOptions.hostNames"
-              rows="5" placeholder="host names" 
data-qa="target-hosts-textarea"}}
+              rows="5" placeholder="Type or paste hosts here..." 
data-qa="target-hosts-textarea"}}
+            </div>
+            <i class="icon-ellipsis-vertical"></i>
+            <div class="col-md-7">
+              {{view Ember.TextArea id="parsed-host-names" disabled=true 
class="form-control" valueBinding="parsedHostsText" rows="5"}}
             </div>
             {{#if hostsError}}
               <div class="col-md-4">
@@ -50,62 +79,11 @@
         </div>
       </div>
 
-      <div {{QAAttr "host-registration-info"}}>
-        <div class="step-title" {{QAAttr "host-registration-info-title"}}>{{t 
installer.step2.sshKey}}</div>
-        <div class="row radio-button-options">
-          <div class="col-sm-5 row">
-            <div class="col-sm-1">
-              {{#view view.providingSSHKeyRadioButton 
labelIdentifier="ssh-key-radio-button"}}{{/view}}
-            </div>
-            <div class="col-sm-10 wizard-plain-text">
-              {{#if useSSH}}
-                {{t installer.step2.useSsh.provide}}
-                <a href="javascript:void(null)"
-                   rel="popover"
-                  {{translateAttr title="installer.step2.useSsh.tooltip.title" 
data-content="installer.step2.useSsh.tooltip.content"}}
-                  {{QAAttr "ssh-tooltip-link"}}>
-                  {{t installer.step2.useSsh.tooltip.title}}</a>
-                {{t installer.step2.useSsh.provide_id_rsa}}
-              {{else}}
-                {{t installer.step2.install.perform}}
-                <a href="javascript:void(null)"
-                   rel="popover"
-                  {{translateAttr 
title="installer.step2.automaticInstall.tooltip.title" 
data-content="installer.step2.automaticInstall.tooltip.content"}}
-                  {{QAAttr "ssh-tooltip-link"}}>
-                  {{t installer.step2.automaticInstall.tooltip.title}}</a>
-                {{t installer.step2.install.perform_on_hosts}}
-              {{/if}}
-            </div>
-          </div>
-          <div class="col-sm-5 row">
-            <div class="col-sm-1">
-              {{#view view.manualRegistrationRadioButton 
labelIdentifier="manual-registration-radio-button"}}{{/view}}
-            </div>
-            <div class="col-sm-10 wizard-plain-text">
-              {{t installer.step2.install.perform}}
-              {{#if useSSH}}
-                <a href="javascript:void(null)"
-                   rel="popover"
-                  {{translateAttr 
title="installer.step2.manualInstall.tooltip.title" 
data-content="installer.step2.manualInstall.tooltip.content"}}
-                  {{QAAttr "ssh-tooltip-link"}}>
-                  {{t installer.step2.manualInstall.tooltip.title}}</a>
-              {{else}}
-                <a href="javascript:void(null)"
-                   rel="popover"
-                  {{translateAttr 
title="installer.step2.manualInstall.tooltip.title" 
data-content="installer.step2.manualInstall.tooltip.content_no_ssh"}}
-                  {{QAAttr "ssh-tooltip-link"}}>
-                  {{t installer.step2.manualInstall.tooltip.title}}</a>
-              {{/if}}
-              {{t installer.step2.install.perform_on_hosts}}
-              {{#if useSSH}}
-                {{t installer.step2.install.without_ssh}}
-              {{/if}}
-            </div>
-          </div>
-        </div>
+      <div {{QAAttr "host-registration-info"}} {{bindAttr 
class="controller.content.installOptions.useSsh:display:noDisplay"}}>
 
         {{#if useSSH}}
           <div class="ssh-key-input">
+          <p>{{t installer.step2.useSsh.tooltip.title}}</p>
             {{#if view.isFileApi}}
               <div>
                 {{view App.SshKeyFileUploader 
disabledBinding="view.sshKeyState"}}
@@ -114,9 +92,9 @@
 
             {{! ssh key }}
             <div {{bindAttr class="sshKeyError:has-error :form-group :row"}}>
-              <div class="col-md-8">
+              <div class="col-md-12 display">
                 {{view Ember.TextArea class="form-control" rows="3" id="sshKey"
-                placeholder="ssh private key" 
disabledBinding="view.sshKeyState"
+                placeholder="Upload or paste key here" 
disabledBinding="view.sshKeyState"
                 valueBinding="content.installOptions.sshKey" 
data-qa="ssh-key-textarea"}}
               </div>
               {{#if sshKeyError}}
@@ -185,6 +163,51 @@
           </div>
         {{/if}}
       </div>
+      <div {{bindAttr 
class="controller.content.installOptions.manualInstall:display:noDisplay"}}>
+        <div class="hosts-table-options">
+          <div {{bindAttr class=":left :host-count 
controller.noPreRegisteredHosts:noDisplay:display"}}>{{{controller.preRegisteredHostFound}}}</div>
+          <button {{action getManuallyInstalledHosts target="controller"}} 
class="btn btn-default pull-right"><i class="icon-undo"></i> {{t 
installer.step2.refresh.table}}</button>
+          <div {{bindAttr class=":hosts-filter-box :pull-right 
controller.noPreRegisteredHosts:noDisplay:display"}}>
+            {{view Em.TextField valueBinding="controller.filterText" 
class="form-control" placeholder="Filter"}}
+          </div>
+        </div>
+        <table class="table table-hover">
+          <thead>
+          <tr>
+            <th class="col-md-6">{{t common.host}}</th>
+            <th class="col-md-2">{{t common.cores}}</th>
+            <th class="col-md-2">{{t common.freeStorage}}</th>
+            <th class="col-md-2">{{t common.memory}}</th>
+            <th class="col-md-2">{{t common.actions}}</th>
+          </tr>
+          </thead>
+          <tbody>
+          {{#if noPreRegisteredHosts}}
+            <tr class="no-pre-registered">
+              <td colspan="5">
+                <p class="no-host-header">{{t common.noHostsFound}}</p>
+                <p class="no-host-title">{{t 
installer.step2.noHostsFound.header}}</p>
+                <p>{{t installer.step2.noHostsFound.step1}}</p>
+                <p>{{t installer.step2.noHostsFound.step2}}</p>
+                <p>{{t installer.step2.noHostsFound.step3}}</p>
+                <p>{{t installer.step2.noHostsFound.step4}}</p>
+                <p>{{{t installer.step2.noHostsFound.learn}}}</p>
+              </td>
+            </tr>
+          {{else}}
+            {{#each host in manuallyInstalledHosts}}
+              <tr {{bindAttr class=":pre-registered host.isVisible::hidden"}}>
+                <td>{{host.hostName}}</td>
+                <td>{{host.cpuCount}}</td>
+                <td>{{host.freeSpace}}</td>
+                <td>{{host.memory}}</td>
+                <td><a><i class="icon-remove-sign" {{action 
deleteRegisteredHost host.hostName target="controller"}}></i></a></td>
+              </tr>
+            {{/each}}
+          {{/if}}
+          </tbody>
+        </table>
+      </div>
       {{#if isAddHostWizard}}
         <br>
         {{view view.skipHostsCheckBox 
checkedBinding="content.installOptions.skipHostChecks"}}
diff --git a/ambari-web/app/utils/ajax/ajax.js 
b/ambari-web/app/utils/ajax/ajax.js
index b944880..5869f49 100644
--- a/ambari-web/app/utils/ajax/ajax.js
+++ b/ambari-web/app/utils/ajax/ajax.js
@@ -378,6 +378,10 @@ var urls = {
     }
   },
 
+  'common.delete.registered.host': {
+    'real': '/hosts/{hostName}',
+    'type': 'DELETE'
+  },
   'common.delete.host': {
     'real': '/clusters/{clusterName}/hosts/{hostName}',
     'type': 'DELETE'
diff --git a/ambari-web/app/views/wizard/step2_view.js 
b/ambari-web/app/views/wizard/step2_view.js
index e498a2d..06f1c21 100644
--- a/ambari-web/app/views/wizard/step2_view.js
+++ b/ambari-web/app/views/wizard/step2_view.js
@@ -60,7 +60,9 @@ App.WizardStep2View = Em.View.extend({
     //todo: move them to conroller
     this.set('controller.hostsError', null);
     this.set('controller.sshKeyError', null);
+    this.set('controller.filterText', null);
     this.get('controller').loadStep();
+    this.get('controller').getManuallyInstalledHosts();
   },
 
   /**
@@ -87,11 +89,6 @@ App.WizardStep2View = Em.View.extend({
   providingSSHKeyRadioButton: App.RadioButtonView.extend({
     classNames: ['radio'],
     checked: Em.computed.alias('controller.content.installOptions.useSsh'),
-
-    click: function () {
-      this.set('controller.content.installOptions.useSsh', true);
-      this.set('controller.content.installOptions.manualInstall', false);
-    }
   }),
 
   /**
@@ -101,11 +98,6 @@ App.WizardStep2View = Em.View.extend({
   manualRegistrationRadioButton: App.RadioButtonView.extend({
     classNames: ['radio'],
     checked: 
Em.computed.alias('controller.content.installOptions.manualInstall'),
-
-    click: function () {
-      this.set('controller.content.installOptions.manualInstall', true);
-      this.set('controller.content.installOptions.useSsh', false);
-    }
   }),
 
   /**
diff --git a/ambari-web/test/controllers/wizard/step2_test.js 
b/ambari-web/test/controllers/wizard/step2_test.js
index c1614b9..15bb625 100644
--- a/ambari-web/test/controllers/wizard/step2_test.js
+++ b/ambari-web/test/controllers/wizard/step2_test.js
@@ -74,7 +74,7 @@ describe('App.WizardStep2Controller', function () {
 
   App.TestAliases.testAsComputedAlias(getController(), 'agentUser', 
'content.installOptions.agentUser', 'string');
 
-  App.TestAliases.testAsComputedOr(getController(), 'isSubmitDisabled', 
['hostsError', 'sshKeyError', 'sshUserError', 'sshPortError', 'agentUserError', 
'App.router.btnClickInProgress']);
+  App.TestAliases.testAsComputedOr(getController(), 'isSubmitDisabled', 
['hostsError', 'sshKeyError', 'sshUserError', 'sshPortError', 'agentUserError', 
'App.router.btnClickInProgress', 'preRegisteredHostsError']);
 
   describe('#hostNames', function() {
     it('should be equal to content.installOptions.hostNames', function() {
@@ -391,15 +391,6 @@ describe('App.WizardStep2Controller', function () {
       });
       expect(controller.evaluateStep()).to.equal(false);
     });
-
-    it('should return false if isPattern is true', function () {
-      var controller = App.WizardStep2Controller.create({
-        hostNames: 'apache.ambari',
-        isPattern: true,
-        parseHostNamesAsPatternExpression: Em.K
-      });
-      expect(controller.evaluateStep()).to.equal(false);
-    })
   });
 
   describe('#parseHostNamesAsPatternExpression()', function () {
@@ -454,13 +445,11 @@ describe('App.WizardStep2Controller', function () {
 
     beforeEach(function () {
       sinon.stub(c, 'warningPopup', Em.K);
-      sinon.stub(c, 'manualInstallPopup', Em.K);
       sinon.stub(App.router, 'send', Em.K);
     });
 
     afterEach(function () {
       c.warningPopup.restore();
-      c.manualInstallPopup.restore();
       App.router.send.restore();
     });
 
@@ -475,16 +464,6 @@ describe('App.WizardStep2Controller', function () {
       expect(c.warningPopup.calledOnce).to.equal(true);
     });
 
-    it('should call manualInstallPopup if manualInstall is true', function () {
-      c.reopen({
-        hostNames: '',
-        manualInstall: true
-      });
-      var r = c.proceedNext(true);
-      expect(r).to.equal(false);
-      expect(c.manualInstallPopup.calledOnce).to.equal(true);
-    });
-
     it ('should save hosts and proceed next if manualInstall is false', 
function() {
       c.reopen({
         hostNameArr: ['h1'],
@@ -542,66 +521,6 @@ describe('App.WizardStep2Controller', function () {
     });
   });
 
-  describe('#hostNamePatternPopup', function() {
-    beforeEach(function() {
-      sinon.spy(App.ModalPopup, 'show');
-      sinon.stub(c, 'proceedNext', Em.K);
-    });
-    afterEach(function() {
-      App.ModalPopup.show.restore();
-      c.proceedNext.restore();
-    });
-    it('should call App.ModalPopup.show', function() {
-      c.hostNamePatternPopup();
-      expect(App.ModalPopup.show.calledOnce).to.equal(true);
-    });
-    it('should proceed next on primary', function() {
-      c.hostNamePatternPopup().onPrimary();
-      expect(c.proceedNext.calledOnce).to.equal(true);
-    });
-  });
-
-  describe('#manualInstallPopup', function() {
-    beforeEach(function() {
-      sinon.spy(App.ModalPopup, 'show');
-      sinon.stub(App.router, 'send', Em.K);
-      sinon.stub(c, 'saveHosts', Em.K);
-    });
-    afterEach(function() {
-      App.ModalPopup.show.restore();
-      App.router.send.restore();
-      c.saveHosts.restore();
-    });
-    it('should call App.ModalPopup.show', function() {
-      c.manualInstallPopup();
-      expect(App.ModalPopup.show.calledOnce).to.equal(true);
-    });
-    it('should save hosts and go next on primary', function() {
-      c.manualInstallPopup().onPrimary();
-      expect(c.saveHosts.calledOnce).to.equal(true);
-      expect(App.router.send.calledWith('next')).to.equal(true);
-    });
-  });
-
-  describe('#manualInstallWarningPopup', function() {
-    beforeEach(function() {
-      sinon.spy(App.ModalPopup, 'show');
-    });
-    afterEach(function() {
-      App.ModalPopup.show.restore();
-    });
-    it('should call App.ModalPopup.show if content.installOptions.useSsh is 
false', function() {
-      var controller = App.WizardStep2Controller.create({content: 
{installOptions: {useSsh: false}}});
-      controller.manualInstallWarningPopup();
-      expect(App.ModalPopup.show.calledOnce).to.equal(true);
-    });
-    it('shouldn\'t call App.ModalPopup.show if content.installOptions.useSsh 
is true', function() {
-      var controller = App.WizardStep2Controller.create({content: 
{installOptions: {useSsh: true}}});
-      controller.manualInstallWarningPopup();
-      expect(App.ModalPopup.show.called).to.equal(false);
-    });
-  });
-
   describe('#setAmbariJavaHome', function() {
 
     it('should do ajax-request', function() {
@@ -652,4 +571,38 @@ describe('App.WizardStep2Controller', function () {
     });
   });
 
+  describe('#useSshRegistration()', function() {
+
+    var controller = App.WizardStep2Controller.create();
+
+    it('should set manualInstall to false', function() {
+      controller.set('content', {'installOptions': {'hostNames': 'h1', 
'manualInstall': true, 'useSsh': false }});
+      controller.useSshRegistration();
+      expect(controller.content.installOptions.manualInstall).to.equal(false);
+    });
+
+    it('should set useSsh to true', function() {
+      controller.set('content', {'installOptions': {'hostNames': 'h1', 
'manualInstall': true, 'useSsh': false }});
+      controller.useSshRegistration();
+      expect(controller.content.installOptions.useSsh).to.equal(true);
+    });
+  });
+
+  describe('#useManualInstall()', function() {
+
+      var controller = App.WizardStep2Controller.create();
+
+      it('should set manualInstall to true', function() {
+        controller.set('content', {'installOptions': {'hostNames': 'h1', 
'manualInstall': false, 'useSsh': true }});
+        controller.useManualInstall();
+        expect(controller.content.installOptions.manualInstall).to.equal(true);
+      });
+
+      it('should set useSsh to false', function() {
+        controller.set('content', {'installOptions': {'hostNames': 'h1', 
'manualInstall': false, 'useSsh': true }});
+        controller.useManualInstall();
+        expect(controller.content.installOptions.useSsh).to.equal(false);
+      });
+    });
+
 });
diff --git a/ambari-web/test/views/wizard/step2_view_test.js 
b/ambari-web/test/views/wizard/step2_view_test.js
index caadb48..ba96a89 100644
--- a/ambari-web/test/views/wizard/step2_view_test.js
+++ b/ambari-web/test/views/wizard/step2_view_test.js
@@ -21,7 +21,8 @@ require('views/wizard/step2_view');
 
 var view, controller = Em.Object.create({
   clusterNameError: '',
-  loadStep: Em.K
+  loadStep: Em.K,
+  getManuallyInstalledHosts: Em.K
 });
 
 function getView() {
@@ -42,6 +43,7 @@ describe('App.WizardStep2View', function () {
       sinon.stub(App, 'tooltip', Em.K);
       view.set('controller.hostsError', 'some text');
       view.set('controller.sshKeyError', 'some text');
+      view.set('controller.manuallyInstalledHosts', []);
     });
     afterEach(function () {
       App.popover.restore();
@@ -90,19 +92,6 @@ describe('App.WizardStep2View', function () {
       });
     });
 
-    describe('#click', function() {
-      it('should update controller.content.installOptions.useSsh', function () 
{
-        v.set('controller.content.installOptions.useSsh', false);
-        v.click();
-        
expect(v.get('controller.content.installOptions.useSsh')).to.equal(true);
-      });
-      it('should update controller.content.installOptions.manualInstall', 
function () {
-        v.set('controller.content.installOptions.manualInstall', true);
-        v.click();
-        
expect(v.get('controller.content.installOptions.manualInstall')).to.equal(false);
-      });
-    });
-
   });
 
   describe('#manualRegistrationRadioButton', function() {
@@ -130,19 +119,6 @@ describe('App.WizardStep2View', function () {
       });
     });
 
-    describe('#click', function() {
-      it('should update controller.content.installOptions.useSsh', function () 
{
-        v.set('controller.content.installOptions.useSsh', true);
-        v.click();
-        
expect(v.get('controller.content.installOptions.useSsh')).to.equal(false);
-      });
-      it('should update controller.content.installOptions.manualInstall', 
function () {
-        v.set('controller.content.installOptions.manualInstall', false);
-        v.click();
-        
expect(v.get('controller.content.installOptions.manualInstall')).to.equal(true);
-      });
-    });
-
   });
 
   describe('#textFieldView', function() {

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to