diff --git a/ambari-web/app/controllers/wizard.js b/ambari-web/app/controllers/wizard.js
index 7ef227c120f..f0948510f9e 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 c6da054eb12..7caa3c61e99 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 sshKey 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
@@ -197,22 +221,88 @@ App.WizardStep2Controller = App.WizardStepController.extend({
return installedHostsName;
}.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;
@@ -490,43 +586,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 55e2f17b737..70705ce748c 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': 'Attention: Please check at least one repository.',
'installer.step1.retryRepoUrls': 'Click here 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.
Note: the path must be valid on ALL 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 SSH Private Key File 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 {0} 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': 'Learn More',
+ 'installer.step2.refresh.table': 'REFRESH TABLE',
'installer.step3.header':'Confirm Hosts',
'installer.step3.body':'Registering your hosts.
' +
diff --git a/ambari-web/app/styles/wizard.less b/ambari-web/app/styles/wizard.less
index 8051f6eb745..129c8122cb7 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 c141ed07ae2..7d523b9a135 100644
--- a/ambari-web/app/templates/wizard/step2.hbs
+++ b/ambari-web/app/templates/wizard/step2.hbs
@@ -19,15 +19,40 @@
{{t installer.step2.targetHosts.info}}. {{t installer.step2.orUse}} +
{{t installer.step2.enterHosts.info}}. {{t installer.step2.orUse}}
-{{t installer.step2.useSsh.tooltip.title}}
{{#if view.isFileApi}}