/**
* 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');
var lazyloading = require('utils/lazy_loading');
var numberUtils = require('utils/number_utils');
App.WizardStep3Controller = Em.Controller.extend({
name: 'wizardStep3Controller',
hosts: [],
content: [],
bootHosts: [],
registeredHosts: [],
hostCheckWarnings: [],
repoCategoryWarnings: [],
diskCategoryWarnings: [],
jdkCategoryWarnings: null,
registrationStartedAt: null,
requestId: 0,
/**
* Timeout for registration
* Based on installOptions.manualInstall
* @type {number}
*/
registrationTimeoutSecs: function () {
return this.get('content.installOptions.manualInstall') ? 15 : 120;
}.property('content.installOptions.manualInstall'),
/**
* Bootstrap calls are stopped
* @type {bool}
*/
stopBootstrap: false,
/**
* is Submit button disabled
* @type {bool}
*/
isSubmitDisabled: true,
/**
* is Retry button disabled
* @type {bool}
*/
isRetryDisabled: true,
/**
* @type {bool}
*/
isLoaded: false,
/**
* Polls count
* @type {number}
*/
numPolls: 0,
/**
* Is hosts registration in progress
* @type {bool}
*/
isRegistrationInProgress: true,
/**
* Are some registered hosts which are not added by user
* @type {bool}
*/
hasMoreRegisteredHosts: false,
/**
* List of installed hostnames
* @type {string[]}
*/
hostsInCluster: function () {
return this.get('content.installedHosts').getEach('hostName');
}.property('content.installedHosts'),
/**
* All hosts warnings
* @type {object[]}
*/
warnings: [],
/**
* Warnings grouped by host
* @type {Ember.Enumerable}
*/
warningsByHost: [],
/**
* Timeout for "warning"-requests
* @type {number}
*/
warningsTimeInterval: 60000,
/**
* Are hosts warnings loaded
* @type {bool}
*/
isWarningsLoaded: function () {
return this.get('isJDKWarningsLoaded') && this.get('isHostsWarningsLoaded');
}.property('isJDKWarningsLoaded', 'isHostsWarningsLoaded'),
/**
* Check are hosts have any warnings
* @type {bool}
*/
isHostHaveWarnings: function () {
return this.get('warnings.length') > 0;
}.property('warnings'),
/**
* Should warnings-box be visible
* @type {bool}
*/
isWarningsBoxVisible: function () {
return (App.testMode) ? true : !this.get('isRegistrationInProgress');
}.property('isRegistrationInProgress'),
/**
* Progress value for "update hosts status" process
* @type {number}
*/
checksUpdateProgress: 0,
/**
*
* @type {object}
*/
checksUpdateStatus: null,
/**
*
* @method navigateStep
*/
navigateStep: function () {
if (this.get('isLoaded')) {
if (!this.get('content.installOptions.manualInstall')) {
if (!this.get('wizardController').getDBProperty('bootStatus')) {
this.startBootstrap();
}
} else {
this.set('bootHosts', this.get('hosts'));
if (App.get('testMode')) {
this.startHostcheck();
this.get('bootHosts').setEach('cpu', '2');
this.get('bootHosts').setEach('memory', '2000000');
this.set('isSubmitDisabled', false);
} else {
this.set('registrationStartedAt', null);
this.startRegistration();
}
}
}
}.observes('isLoaded'),
/**
* Clear controller data
* @method clearStep
*/
clearStep: function () {
this.set('stopBootstrap', false);
this.set('hosts', []);
this.get('bootHosts').clear();
this.get('wizardController').setDBProperty('bootStatus', false);
this.set('isSubmitDisabled', true);
this.set('isRetryDisabled', true);
},
/**
* Make basic init steps
* @method loadStep
*/
loadStep: function () {
console.log("TRACE: Loading step3: Confirm Hosts");
this.set('registrationStartedAt', null);
this.set('isLoaded', false);
this.disablePreviousSteps();
this.clearStep();
App.router.get('clusterController').loadAmbariProperties();
this.loadHosts();
},
/**
* Loads the hostinfo from localStorage on the insertion of view. It's being called from view
* @method loadHosts
*/
loadHosts: function () {
var hostsInfo = this.get('content.hosts');
var hosts = [];
var bootStatus = (this.get('content.installOptions.manualInstall')) ? 'DONE' : 'PENDING';
if (App.testMode) {
bootStatus = 'REGISTERED';
}
for (var index in hostsInfo) {
if (hostsInfo.hasOwnProperty(index)) {
hosts.pushObject(App.HostInfo.create({
name: hostsInfo[index].name,
bootStatus: bootStatus,
isChecked: false
}));
}
}
this.set('hosts', hosts);
this.set('isLoaded', true);
},
/**
* Parses and updates the content based on bootstrap API response.
* @return {bool} true if polling should continue (some hosts are in "RUNNING" state); false otherwise
* @method parseHostInfo
*/
parseHostInfo: function (hostsStatusFromServer) {
hostsStatusFromServer.forEach(function (_hostStatus) {
var host = this.get('bootHosts').findProperty('name', _hostStatus.hostName);
// check if hostname extracted from REST API data matches any hostname in content
// also, make sure that bootStatus modified by isHostsRegistered call does not get overwritten
// since these calls are being made in parallel
if (host && !['REGISTERED', 'REGISTERING'].contains(host.get('bootStatus'))) {
host.set('bootStatus', _hostStatus.status);
host.set('bootLog', _hostStatus.log);
}
}, this);
// if the data rendered by REST API has hosts in "RUNNING" state, polling will continue
return this.get('bootHosts').length != 0 && this.get('bootHosts').someProperty('bootStatus', 'RUNNING');
},
/**
* Remove list of hosts
* @param {Ember.Enumerable} hosts
* @return {App.ModalPopup}
* @method removeHosts
*/
removeHosts: function (hosts) {
var self = this;
return App.showConfirmationPopup(function () {
App.router.send('removeHosts', hosts);
self.hosts.removeObjects(hosts);
if (!self.hosts.length) {
self.set('isSubmitDisabled', true);
}
}, Em.I18n.t('installer.step3.hosts.remove.popup.body'));
},
/**
* Removes a single element on the trash icon click. Called from View
* @param {object} hostInfo
* @method removeHost
*/
removeHost: function (hostInfo) {
this.removeHosts([hostInfo]);
},
/**
* Remove selected hosts (click-handler)
* @return App.ModalPopup
* @method removeSelectedHosts
*/
removeSelectedHosts: function () {
var selectedHosts = this.get('hosts').filterProperty('isChecked', true);
selectedHosts.forEach(function (_hostInfo) {
console.log('Removing: ' + _hostInfo.name);
});
return this.removeHosts(selectedHosts);
},
/**
* Show popup with the list of hosts which are selected
* @return App.ModalPopup
* @method selectedHostsPopup
*/
selectedHostsPopup: function () {
var selectedHosts = this.get('hosts').filterProperty('isChecked').mapProperty('name');
return App.ModalPopup.show({
header: Em.I18n.t('installer.step3.selectedHosts.popup.header'),
secondary: null,
bodyClass: Em.View.extend({
templateName: require('templates/common/items_list_popup'),
items: selectedHosts,
insertedItems: [],
didInsertElement: function () {
lazyloading.run({
destination: this.get('insertedItems'),
source: this.get('items'),
context: this,
initSize: 100,
chunkSize: 500,
delay: 100
});
}
})
});
},
/**
* Retry one host {click-handler}
* @param {object} hostInfo
* @method retryHost
*/
retryHost: function (hostInfo) {
this.retryHosts([hostInfo]);
},
/**
* Retry list of hosts
* @param {object[]} hosts
* @method retryHosts
*/
retryHosts: function (hosts) {
var self = this;
var bootStrapData = JSON.stringify({
'verbose': true,
'sshKey': this.get('content.installOptions.sshKey'),
'hosts': hosts.mapProperty('name'),
'user': this.get('content.installOptions.sshUser')}
);
this.set('numPolls', 0);
this.set('registrationStartedAt', null);
if (this.get('content.installOptions.manualInstall')) {
this.get('bootHosts').setEach('bootStatus', 'DONE');
this.startRegistration();
}
else {
App.router.get(this.get('content.controllerName')).launchBootstrap(bootStrapData, function (requestId) {
self.set('content.installOptions.bootRequestId', requestId);
self.doBootstrap();
});
}
},
/**
* Retry selected hosts (click-handler)
* @method retrySelectedHosts
*/
retrySelectedHosts: function () {
if (!this.get('isRetryDisabled')) {
this.set('isRetryDisabled', true);
var selectedHosts = this.get('bootHosts').filterProperty('bootStatus', 'FAILED');
selectedHosts.forEach(function (_host) {
_host.set('bootStatus', 'RUNNING');
_host.set('bootLog', 'Retrying ...');
}, this);
this.retryHosts(selectedHosts);
}
},
/**
* Init bootstrap settings and start it
* @method startBootstrap
*/
startBootstrap: function () {
//this.set('isSubmitDisabled', true); //TODO: uncomment after actual hookup
this.set('numPolls', 0);
this.set('registrationStartedAt', null);
this.set('bootHosts', this.get('hosts'));
this.doBootstrap();
},
/**
* Update isRegistrationInProgress
once
* @method setRegistrationInProgressOnce
*/
setRegistrationInProgressOnce: function () {
Em.run.once(this, 'setRegistrationInProgress');
}.observes('bootHosts.@each.bootStatus'),
/**
* Set isRegistrationInProgress
value based on each host boot status
* @method setRegistrationInProgress
*/
setRegistrationInProgress: function () {
var bootHosts = this.get('bootHosts');
//if hosts aren't loaded yet then registration should be in progress
var result = (bootHosts.length === 0 && !this.get('isLoaded'));
for (var i = 0, l = bootHosts.length; i < l; i++) {
if (bootHosts[i].get('bootStatus') !== 'REGISTERED' && bootHosts[i].get('bootStatus') !== 'FAILED') {
result = true;
break;
}
}
this.set('isRegistrationInProgress', result);
},
/**
* Disable wizard's previous steps (while registering)
* @method disablePreviousSteps
*/
disablePreviousSteps: function () {
App.router.get('installerController.isStepDisabled').filter(function (step) {
return step.step >= 0 && step.step <= 2;
}).setEach('value', this.get('isRegistrationInProgress'));
if (this.get('isRegistrationInProgress')) {
this.set('isSubmitDisabled', true);
}
}.observes('isRegistrationInProgress'),
/**
* Do bootstrap calls
* @method doBootstrap
* @return {$.ajax|null}
*/
doBootstrap: function () {
if (this.get('stopBootstrap')) {
return null;
}
this.incrementProperty('numPolls');
return App.ajax.send({
name: 'wizard.step3.bootstrap',
sender: this,
data: {
bootRequestId: this.get('content.installOptions.bootRequestId'),
numPolls: this.get('numPolls')
},
success: 'doBootstrapSuccessCallback'
}).
retry({
times: App.maxRetries,
timeout: App.timeout
}).
then(
null,
function () {
App.showReloadPopup();
console.log('Bootstrap failed');
}
);
},
/**
* Success-callback for each boostrap request
* @param {object} data
* @method doBootstrapSuccessCallback
*/
doBootstrapSuccessCallback: function (data) {
var self = this;
var pollingInterval = 3000;
if (Em.isNone(data.hostsStatus)) {
console.log('Invalid response, setting timeout');
window.setTimeout(function () {
self.doBootstrap()
}, pollingInterval);
} else {
// in case of bootstrapping just one host, the server returns an object rather than an array, so
// force into an array
if (!(data.hostsStatus instanceof Array)) {
data.hostsStatus = [ data.hostsStatus ];
}
console.log("TRACE: In success function for the GET bootstrap call");
var keepPolling = this.parseHostInfo(data.hostsStatus);
// Single host : if the only hostname is invalid (data.status == 'ERROR')
// Multiple hosts : if one or more hostnames are invalid
// following check will mark the bootStatus as 'FAILED' for the invalid hostname
if (data.status == 'ERROR' || data.hostsStatus.length != this.get('bootHosts').length) {
var hosts = this.get('bootHosts');
for (var i = 0; i < hosts.length; i++) {
var isValidHost = data.hostsStatus.someProperty('hostName', hosts[i].get('name'));
if (hosts[i].get('bootStatus') !== 'REGISTERED') {
if (!isValidHost) {
hosts[i].set('bootStatus', 'FAILED');
hosts[i].set('bootLog', Em.I18n.t('installer.step3.hosts.bootLog.failed'));
}
}
}
}
if (data.status == 'ERROR' || data.hostsStatus.someProperty('status', 'DONE') || data.hostsStatus.someProperty('status', 'FAILED')) {
// kicking off registration polls after at least one host has succeeded
this.startRegistration();
}
if (keepPolling) {
window.setTimeout(function () {
self.doBootstrap()
}, pollingInterval);
}
}
},
/**
* Start hosts registration
* @method startRegistration
*/
startRegistration: function () {
if (Em.isNone(this.get('registrationStartedAt'))) {
this.set('registrationStartedAt', App.dateTime());
console.log('registration started at ' + this.get('registrationStartedAt'));
this.isHostsRegistered();
}
},
/**
* Do requests to check if hosts are already registered
* @return {$.ajax|null}
* @method isHostsRegistered
*/
isHostsRegistered: function () {
if (this.get('stopBootstrap')) {
return null;
}
return App.ajax.send({
name: 'wizard.step3.is_hosts_registered',
sender: this,
success: 'isHostsRegisteredSuccessCallback'
}).
retry({
times: App.maxRetries,
timeout: App.timeout
}).
then(
null,
function () {
App.showReloadPopup();
console.log('Error: Getting registered host information from the server');
}
);
},
/**
* Success-callback for registered hosts request
* @param {object} data
* @method isHostsRegisteredSuccessCallback
*/
isHostsRegisteredSuccessCallback: function (data) {
console.log('registration attempt...');
var hosts = this.get('bootHosts');
var jsonData = data;
if (!jsonData) {
console.warn("Error: jsonData is null");
return;
}
// keep polling until all hosts have registered/failed, or registrationTimeout seconds after the last host finished bootstrapping
var stopPolling = true;
hosts.forEach(function (_host, index) {
// Change name of first host for test mode.
if (App.testMode) {
if (index == 0) {
_host.set('name', 'localhost.localdomain');
}
}
// actions to take depending on the host's current bootStatus
// RUNNING - bootstrap is running; leave it alone
// DONE - bootstrap is done; transition to REGISTERING
// REGISTERING - bootstrap is done but has not registered; transition to REGISTERED if host found in polling API result
// REGISTERED - bootstrap and registration is done; leave it alone
// FAILED - either bootstrap or registration failed; leave it alone
switch (_host.get('bootStatus')) {
case 'DONE':
_host.set('bootStatus', 'REGISTERING');
_host.set('bootLog', (_host.get('bootLog') != null ? _host.get('bootLog') : '') + Em.I18n.t('installer.step3.hosts.bootLog.registering'));
// update registration timestamp so that the timeout is computed from the last host that finished bootstrapping
this.set('registrationStartedAt', App.dateTime());
stopPolling = false;
break;
case 'REGISTERING':
if (jsonData.items.someProperty('Hosts.host_name', _host.name)) {
_host.set('bootStatus', 'REGISTERED');
_host.set('bootLog', (_host.get('bootLog') != null ? _host.get('bootLog') : '') + Em.I18n.t('installer.step3.hosts.bootLog.registering'));
} else {
stopPolling = false;
}
break;
case 'RUNNING':
stopPolling = false;
break;
case 'REGISTERED':
case 'FAILED':
default:
break;
}
}, this);
if (stopPolling) {
this.startHostcheck();
}
else {
if (hosts.someProperty('bootStatus', 'RUNNING') || App.dateTime() - this.get('registrationStartedAt') < this.get('registrationTimeoutSecs') * 1000) {
// we want to keep polling for registration status if any of the hosts are still bootstrapping (so we check for RUNNING).
var self = this;
window.setTimeout(function () {
self.isHostsRegistered();
}, 3000);
}
else {
// registration timed out. mark all REGISTERING hosts to FAILED
console.log('registration timed out');
hosts.filterProperty('bootStatus', 'REGISTERING').forEach(function (_host) {
_host.set('bootStatus', 'FAILED');
_host.set('bootLog', (_host.get('bootLog') != null ? _host.get('bootLog') : '') + Em.I18n.t('installer.step3.hosts.bootLog.failed'));
});
this.startHostcheck();
}
}
},
/**
* Do request for all registered hosts
* @return {$.ajax}
* @method getAllRegisteredHosts
*/
getAllRegisteredHosts: function () {
return App.ajax.send({
name: 'wizard.step3.is_hosts_registered',
sender: this,
success: 'getAllRegisteredHostsCallback'
});
}.observes('bootHosts'),
/**
* Success-callback for all registered hosts request
* @param {object} hosts
* @method getAllRegisteredHostsCallback
*/
getAllRegisteredHostsCallback: function (hosts) {
var registeredHosts = [];
var hostsInCluster = this.get('hostsInCluster');
var addedHosts = this.get('bootHosts').getEach('name');
hosts.items.forEach(function (host) {
if (!hostsInCluster.contains(host.Hosts.host_name) && !addedHosts.contains(host.Hosts.host_name)) {
registeredHosts.push(host.Hosts.host_name);
}
});
if (registeredHosts.length) {
this.set('hasMoreRegisteredHosts', true);
this.set('registeredHosts', registeredHosts);
} else {
this.set('hasMoreRegisteredHosts', false);
this.set('registeredHosts', '');
}
},
/**
* Show popup with regitration error-message
* @param {string} header
* @param {string} message
* @return {App.ModalPopup}
* @method registerErrPopup
*/
registerErrPopup: function (header, message) {
return App.ModalPopup.show({
header: header,
secondary: false,
bodyClass: Em.View.extend({
template: Em.Handlebars.compile('
{{view.message}}
'), message: message }) }); }, /** * Get JDK name from server to determine if user had setup a customized JDK path when doing 'ambari-server setup'. * The Ambari properties are different from default ambari-server setup, property 'jdk.name' will be missing if a customized jdk path is applied. * @return {$.ajax} * @method getJDKName */ getJDKName: function () { return App.ajax.send({ name: 'ambari.service.load_jdk_name', sender: this, success: 'getJDKNameSuccessCallback' }); }, /** * Success callback for JDK name, property 'jdk.name' will be missing if a customized jdk path is applied * @param {object} data * @method getJDKNameSuccessCallback */ getJDKNameSuccessCallback: function (data) { this.set('needJDKCheckOnHosts', !data.RootServiceComponents.properties["jdk.name"]); this.set('jdkLocation', Em.get(data, "RootServiceComponents.properties.jdk_location")); this.set('javaHome', data.RootServiceComponents.properties["java.home"]); }, doCheckJDK: function () { var hostsNames = this.get('bootHosts').getEach('name').join(","); var javaHome = this.get('javaHome'); var jdkLocation = this.get('jdkLocation'); App.ajax.send({ name: 'wizard.step3.jdk_check', sender: this, data: { host_names: hostsNames, java_home: javaHome, jdk_location: jdkLocation }, success: 'doCheckJDKsuccessCallback', error: 'doCheckJDKerrorCallback' }); }, doCheckJDKsuccessCallback: function (data) { var requestIndex = data.href.split('/')[data.href.split('/').length - 1]; var self = this; // keep getting JDK check results data until all hosts jdk check completed var myVar = setInterval( function(){ if (self.get('jdkCategoryWarnings') == null) { // get jdk check results for all hosts App.ajax.send({ name: 'wizard.step3.jdk_check.get_results', sender: self, data: { requestIndex: requestIndex }, success: 'parseJDKCheckResults' }) } else { clearInterval(myVar); self.set('isJDKWarningsLoaded', true); } }, 1000); }, doCheckJDKerrorCallback: function () { console.log('INFO: Doing JDK check for host failed'); this.set('isJDKWarningsLoaded', true); }, parseJDKCheckResults: function (data) { var jdkWarnings = [], hostsJDKContext = [], hostsJDKNames = []; // check if the request ended if (data.Requests.end_time > 0 && data.tasks) { data.tasks.forEach( function(task) { // generate warning context if (Em.get(task, "Tasks.structured_out.java_home_check.exit_code") == 1){ var jdkContext = Em.I18n.t('installer.step3.hostWarningsPopup.jdk.context').format(task.Tasks.host_name); hostsJDKContext.push(jdkContext); hostsJDKNames.push(task.Tasks.host_name); } }); if (hostsJDKContext.length > 0) { // java jdk warning exist var invalidJavaHome = this.get('javaHome'); jdkWarnings.push({ name: Em.I18n.t('installer.step3.hostWarningsPopup.jdk.name').format(invalidJavaHome), hosts: hostsJDKContext, hostsNames: hostsJDKNames, category: 'jdk', onSingleHost: false }); } this.set('jdkCategoryWarnings', jdkWarnings); } else { // still doing JDK check, data not ready to be parsed this.set('jdkCategoryWarnings', null); } }, /** * Check JDK issues on registered hosts. */ checkHostJDK: function () { this.set('isJDKWarningsLoaded', false); this.set('jdkCategoryWarnings', null); var self = this; this.getJDKName().done( function() { if (self.get('needJDKCheckOnHosts')) { // need to do JDK check on each host self.doCheckJDK(); } else { // no customized JDK path, so no need to check jdk self.set('jdkCategoryWarnings', []); self.set('isJDKWarningsLoaded', true); } }); }, /** * Get disk info and cpu count of booted hosts from server * @return {$.ajax} * @method getHostInfo */ getHostInfo: function () { this.set('isHostsWarningsLoaded', false); // begin JDK check for each host return App.ajax.send({ name: 'wizard.step3.host_info', sender: this, success: 'getHostInfoSuccessCallback', error: 'getHostInfoErrorCallback' }); }, startHostcheck: function() { this.set('isWarningsLoaded', false); this.getHostNameResolution(); this.checkHostJDK(); }, getHostNameResolution: function () { var hosts = this.get('bootHosts').getEach('name').join(","); var jdk_location = App.router.get('clusterController.ambariProperties.jdk_location'); var RequestInfo = { "action": "check_host", "context": "Check host", "parameters": { "check_execute_list": "host_resolution_check", "jdk_location" : jdk_location, "hosts": hosts, "threshold": "20" } }; var resource_filters = { "hosts": hosts }; if (App.testMode) { this.getHostNameResolutionSuccess(); } else { return App.ajax.send({ name: 'preinstalled.checks', sender: this, data: { RequestInfo: RequestInfo, resource_filters: resource_filters }, success: 'getHostNameResolutionSuccess', error: 'getHostNameResolutionError' }); } }, getHostNameResolutionSuccess: function(response) { if (!App.testMode) { this.set("requestId", response.Requests.id); } this.getHostCheckTasks(); }, getHostNameResolutionError: function() { this.getHostInfo(); }, /** * send ajax request to get all tasks * @method getHostCheckTasks */ getHostCheckTasks: function () { var requestId = this.get("requestId"); var self = this; var checker = setInterval(function () { if (self.get('stopChecking') == true) { clearInterval(checker); self.getHostInfo(); } else { App.ajax.send({ name: 'preinstalled.checks.tasks', sender: self, data: { requestId: requestId }, success: 'getHostCheckTasksSuccess', error: 'getHostCheckTasksError' }); } }, 1000); }, /** * add warnings to host warning popup if needed * @param data {Object} - json * @method getHostCheckTasksSuccess */ getHostCheckTasksSuccess: function (data) { console.log('checking attempt...'); if (!data) { console.warn("Error: jsonData is null"); return; } this.set('stopChecking', true); data.tasks.forEach(function (task) { var name = Em.I18n.t('installer.step3.hostWarningsPopup.resolution.validation.error'); var hostInfo = this.get("hostCheckWarnings").findProperty('name', name); if (task.Tasks.status == "FAILED" || task.Tasks.status == "COMPLETED" || task.Tasks.status == "TIMEDOUT") { if (task.Tasks.status == "COMPLETED") { if (Em.get(task, "Tasks.structured_out.host_resolution_check.failed_count") == 0) { return; } } if (!hostInfo) { hostInfo = { name: name, hosts: [task.Tasks.host_name], onSingleHost: true }; this.get("hostCheckWarnings").push(hostInfo); } else { if (!hostInfo.hosts.contains(task.Tasks.host_name)) { hostInfo.hosts.push(task.Tasks.host_name); } } } else { this.set('stopChecking', false); } }, this); }, stopChecking: false, /** * @method getHostCheckTasksError */ getHostCheckTasksError: function() { console.warn("failed to cheek hostName resolution"); this.set('stopChecking', true); }, /** * Success-callback for hosts info request * @param {object} jsonData * @method getHostInfoSuccessCallback */ getHostInfoSuccessCallback: function (jsonData) { var hosts = this.get('bootHosts'), self = this, repoWarnings = [], hostsRepoNames = [], hostsContext = [], diskWarnings = [], hostsDiskContext = [], hostsDiskNames = []; // parse host checks warning this.parseWarnings(jsonData); hosts.forEach(function (_host) { var host = (App.get('testMode')) ? jsonData.items[0] : jsonData.items.findProperty('Hosts.host_name', _host.name); if (App.get('skipBootstrap')) { self._setHostDataWithSkipBootstrap(_host); } else { if (host) { self._setHostDataFromLoadedHostInfo(_host, host); var host_name = Em.get(host, 'Hosts.host_name'); var context = self.checkHostOSType(host.Hosts.os_type, host_name); if (context) { hostsContext.push(context); hostsRepoNames.push(host_name); } var diskContext = self.checkHostDiskSpace(host_name, host.Hosts.disk_info); if (diskContext) { hostsDiskContext.push(diskContext); hostsDiskNames.push(host_name); } } } }); if (hostsContext.length > 0) { // repository warning exist repoWarnings.push({ name: Em.I18n.t('installer.step3.hostWarningsPopup.repositories.name'), hosts: hostsContext, hostsNames: hostsRepoNames, category: 'repositories', onSingleHost: false }); } if (hostsDiskContext.length > 0) { // disk space warning exist diskWarnings.push({ name: Em.I18n.t('installer.step3.hostWarningsPopup.disk.name'), hosts: hostsDiskContext, hostsNames: hostsDiskNames, category: 'disk', onSingleHost: false }); } this.set('repoCategoryWarnings', repoWarnings); this.set('diskCategoryWarnings', diskWarnings); this.stopRegistration(); }, /** * Set metrics to host object * Used whenApp.skipBootstrap
is true
* @param {Ember.Object} host
* @returns {object}
* @private
* @methos _setHostDataWithSkipBootstrap
*/
_setHostDataWithSkipBootstrap: function(host) {
host.set('cpu', 2);
host.set('memory', ((parseInt(2000000))).toFixed(2));
host.set('disk_info', [
{"mountpoint": "/", "type": "ext4"},
{"mountpoint": "/grid/0", "type": "ext4"},
{"mountpoint": "/grid/1", "type": "ext4"},
{"mountpoint": "/grid/2", "type": "ext4"}
]);
return host;
},
/**
* Set loaded metrics to host object
* @param {object} host
* @param {object} hostInfo
* @returns {object}
* @method _setHostDataFromLoadedHostInfo
* @private
*/
_setHostDataFromLoadedHostInfo: function(host, hostInfo) {
host.set('cpu', Em.get(hostInfo, 'Hosts.cpu_count'));
host.set('memory', ((parseInt(Em.get(hostInfo, 'Hosts.total_mem')))).toFixed(2));
host.set('disk_info', Em.get(hostInfo, 'Hosts.disk_info').filter(function (h) {
return h.mountpoint != "/boot"
}));
host.set('os_type', Em.get(hostInfo, 'Hosts.os_type'));
host.set('os_arch', Em.get(hostInfo, 'Hosts.os_arch'));
host.set('ip', Em.get(hostInfo, 'Hosts.ip'));
return host;
},
/**
* Error-callback for hosts info request
* @method getHostInfoErrorCallback
*/
getHostInfoErrorCallback: function () {
console.log('INFO: Getting host information(cpu_count and total_mem) from the server failed');
this.set('isHostsWarningsLoaded', true);
this.registerErrPopup(Em.I18n.t('installer.step3.hostInformation.popup.header'), Em.I18n.t('installer.step3.hostInformation.popup.body'));
},
/**
* Enable or disable submit/retry buttons according to hosts boot statuses
* @method stopRegistration
*/
stopRegistration: function () {
this.set('isSubmitDisabled', !this.get('bootHosts').someProperty('bootStatus', 'REGISTERED'));
this.set('isRetryDisabled', !this.get('bootHosts').someProperty('bootStatus', 'FAILED'));
},
/**
* Check if the customized os group contains the registered host os type. If not the repo on that host is invalid.
* @param {string} osType
* @param {string} hostName
* @return {string} error-message or empty string
* @method checkHostOSType
*/
checkHostOSType: function (osType, hostName) {
if (this.get('content.stacks')) {
var selectedStack = this.get('content.stacks').findProperty('isSelected', true);
var selectedOS = [];
var self = this;
var isValid = false;
if (selectedStack && selectedStack.operatingSystems) {
selectedStack.get('operatingSystems').filterProperty('selected', true).forEach(function (os) {
selectedOS.pushObject(os.osType);
if (self.repoToAgentOsType(os.osType).indexOf(osType) >= 0) {
isValid = true;
}
});
}
if (isValid) {
return '';
} else {
console.log('WARNING: Getting host os type does NOT match the user selected os group in step1. ' +
'Host Name: ' + hostName + '. Host os type:' + osType + '. Selected group:' + selectedOS.uniq());
return Em.I18n.t('installer.step3.hostWarningsPopup.repositories.context').format(hostName, osType, selectedOS.uniq());
}
} else {
return '';
}
},
/**
* return the supported agent os types for a repo os type
* @param {String} repoType
* @return {Array} supported agent os type array
* @method repoToAgentOsType
*/
repoToAgentOsType : function (repoType) {
switch (repoType) {
case "redhat6":
return ["redhat6", "centos6", "oraclelinux6", "rhel6"];
case "redhat5":
return ["redhat5", "centos5", "oraclelinux5", "rhel5"];
case "suse11":
return ["suse11", "sles11", "opensuse11"];
case "debian12":
return ["debian12", "ubuntu12"];
default:
return [];
}
},
/**
* Check if current host has enough free disk usage.
* @param {string} hostName
* @param {object} diskInfo
* @return {string} error-message or empty string
* @method checkHostDiskSpace
*/
checkHostDiskSpace: function (hostName, diskInfo) {
var minFreeRootSpace = App.minDiskSpace * 1024 * 1024; //in kilobyte
var minFreeUsrLibSpace = App.minDiskSpaceUsrLib * 1024 * 1024; //in kilobyte
var warningString = '';
diskInfo.forEach(function (info) {
switch (info.mountpoint) {
case '/':
warningString = info.available < minFreeRootSpace ?
Em.I18n.t('installer.step3.hostWarningsPopup.disk.context2').format(App.minDiskSpace + 'GB', info.mountpoint) + ' ' + warningString :
warningString;
break;
case '/usr':
case '/usr/lib':
warningString = info.available < minFreeUsrLibSpace ?
Em.I18n.t('installer.step3.hostWarningsPopup.disk.context2').format(App.minDiskSpaceUsrLib + 'GB', info.mountpoint) + ' ' + warningString :
warningString;
break;
default:
break;
}
});
if (warningString) {
console.log('WARNING: Getting host free disk space. ' + 'Host Name: ' + hostName);
return Em.I18n.t('installer.step3.hostWarningsPopup.disk.context1').format(hostName) + ' ' + warningString;
} else {
return '';
}
},
/**
* Submit-click handler
* @return {App.ModalPopup|null}
* @method submit
*/
submit: function () {
if (this.get('isHostHaveWarnings')) {
var self = this;
return App.showConfirmationPopup(
function () {
self.set('content.hosts', self.get('bootHosts'));
App.router.send('next');
},
Em.I18n.t('installer.step3.hostWarningsPopup.hostHasWarnings'));
}
else {
this.set('content.hosts', this.get('bootHosts'));
App.router.send('next');
}
return null;
},
/**
* Show popup with host log
* @param {object} event
* @return {App.ModalPopup}
*/
hostLogPopup: function (event) {
var host = event.context;
return App.ModalPopup.show({
header: Em.I18n.t('installer.step3.hostLog.popup.header').format(host.get('name')),
secondary: null,
host: host,
bodyClass: App.WizardStep3HostLogPopupBody
});
},
/**
* Check warnings from server and put it in parsing
* @method rerunChecks
*/
rerunChecks: function () {
var self = this;
var currentProgress = 0;
this.getHostNameResolution();
this.checkHostJDK();
var interval = setInterval(function () {
currentProgress += 100000 / self.get('warningsTimeInterval');
if (currentProgress < 100) {
self.set('checksUpdateProgress', currentProgress);
} else {
clearInterval(interval);
App.ajax.send({
name: 'wizard.step3.rerun_checks',
sender: self,
success: 'rerunChecksSuccessCallback',
error: 'rerunChecksErrorCallback'
});
}
}, 1000);
},
/**
* Success-callback for rerun request
* @param {object} data
* @method rerunChecksSuccessCallback
*/
rerunChecksSuccessCallback: function (data) {
this.set('checksUpdateProgress', 100);
this.set('checksUpdateStatus', 'SUCCESS');
this.parseWarnings(data);
},
/**
* Error-callback for rerun request
* @method rerunChecksErrorCallback
*/
rerunChecksErrorCallback: function () {
this.set('checksUpdateProgress', 100);
this.set('checksUpdateStatus', 'FAILED');
console.log('INFO: Getting host information(last_agent_env) from the server failed');
},
/**
* Filter data for warnings parse
* is data from host in bootStrap
* @param {object} data
* @return {Object}
* @method filterBootHosts
*/
filterBootHosts: function (data) {
var bootHostNames = {};
this.get('bootHosts').forEach(function (bootHost) {
bootHostNames[bootHost.get('name')] = true;
});
var filteredData = {
href: data.href,
items: []
};
data.items.forEach(function (host) {
if (bootHostNames[host.Hosts.host_name]) {
filteredData.items.push(host);
}
});
return filteredData;
},
/**
* Parse warnings data for each host and total
* @param {object} data
* @method parseWarnings
*/
parseWarnings: function (data) {
data = App.testMode ? data : this.filterBootHosts(data);
var warnings = [];
var warning;
var hosts = [];
var warningCategories = {
fileFoldersWarnings: {},
packagesWarnings: {},
processesWarnings: {},
servicesWarnings: {},
usersWarnings: {},
alternativeWarnings: {}
};
data.items.sortPropertyLight('Hosts.host_name').forEach(function (_host) {
var host = {
name: _host.Hosts.host_name,
warnings: []
};
if (!_host.Hosts.last_agent_env) {
// in some unusual circumstances when last_agent_env is not available from the _host,
// skip the _host and proceed to process the rest of the hosts.
console.log("last_agent_env is missing for " + _host.Hosts.host_name + ". Skipping _host check.");
return;
}
//parse all directories and files warnings for host
//todo: to be removed after check in new API
var stackFoldersAndFiles = _host.Hosts.last_agent_env.stackFoldersAndFiles || [];
stackFoldersAndFiles.forEach(function (path) {
warning = warningCategories.fileFoldersWarnings[path.name];
if (warning) {
warning.hosts.push(_host.Hosts.host_name);
warning.onSingleHost = false;
} else {
warningCategories.fileFoldersWarnings[path.name] = warning = {
name: path.name,
hosts: [_host.Hosts.host_name],
category: 'fileFolders',
onSingleHost: true
};
}
host.warnings.push(warning);
}, this);
//parse all package warnings for host
if (_host.Hosts.last_agent_env.installedPackages) {
_host.Hosts.last_agent_env.installedPackages.forEach(function (_package) {
warning = warningCategories.packagesWarnings[_package.name];
if (warning) {
warning.hosts.push(_host.Hosts.host_name);
warning.version = _package.version;
warning.onSingleHost = false;
} else {
warningCategories.packagesWarnings[_package.name] = warning = {
name: _package.name,
version: _package.version,
hosts: [_host.Hosts.host_name],
category: 'packages',
onSingleHost: true
};
}
host.warnings.push(warning);
}, this);
}
//parse all process warnings for host
//todo: to be removed after check in new API
var javaProcs = _host.Hosts.last_agent_env.hostHealth ? _host.Hosts.last_agent_env.hostHealth.activeJavaProcs : _host.Hosts.last_agent_env.javaProcs;
if (javaProcs) {
javaProcs.forEach(function (process) {
warning = warningCategories.processesWarnings[process.pid];
if (warning) {
warning.hosts.push(_host.Hosts.host_name);
warning.onSingleHost = false;
} else {
warningCategories.processesWarnings[process.pid] = warning = {
name: (process.command.substr(0, 35) + '...'),
hosts: [_host.Hosts.host_name],
category: 'processes',
user: process.user,
pid: process.pid,
command: '' +
((process.command.length < 500) ? process.command : process.command.substr(0, 230) + '...' +
' ................ ' + '...' + process.command.substr(-230)) + ' |