blob: 29c656a4e28748bcc14b32e257a1c7e53055ef0f [file] [log] [blame]
/**
* 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 uiEffects = require('utils/ui_effects');
App.MainHostSummaryView = Em.View.extend({
templateName: require('templates/main/host/summary'),
isStopCommand:true,
content: function () {
return App.router.get('mainHostDetailsController.content');
}.property('App.router.mainHostDetailsController.content'),
showGangliaCharts: function () {
var name = this.get('content.hostName');
var gangliaMobileUrl = App.router.get('clusterController.gangliaUrl') + "/mobile_helper.php?show_host_metrics=1&h=" + name + "&c=HDPNameNode&r=hour&cs=&ce=";
window.open(gangliaMobileUrl);
},
needToRestartComponentsCount: function() {
return this.get('sortedComponents').filterProperty('staleConfigs', true).length;
}.property('sortedComponents.@each.staleConfigs'),
stopComponentsIsDisabled: function () {
var staleComponents = this.get('sortedComponents').filterProperty('staleConfigs', true);
if(!staleComponents.findProperty('workStatus','STARTED')){
return true;
} else {
return false;
}
}.property('sortedComponents.@each.workStatus'),
startComponentsIsDisabled:function () {
var staleComponents = this.get('sortedComponents').filterProperty('staleConfigs', true);
if(!staleComponents.findProperty('workStatus','INSTALLED')){
return true;
} else {
return false;
}
}.property('sortedComponents.@each.workStatus'),
needToRestartMessage: function() {
return Em.I18n.t('hosts.host.details.needToRestart').format(this.get('needToRestartComponentsCount'));
}.property('needToRestartComponentsCount'),
/**
* @type: [{String}]
*/
decommissionDataNodeHostNames: null,
loadDecommissionNodesList: function () {
var self = this;
var clusterName = App.router.get('clusterController.clusterName');
var persistUrl = App.apiPrefix + '/persist';
var clusterUrl = App.apiPrefix + '/clusters/' + clusterName;
var getConfigAjax = {
type: 'GET',
url: persistUrl,
dataType: 'json',
timeout: App.timeout,
success: function (data) {
if (data && data.decommissionDataNodesTag) {
// We know the tag which contains the decommisioned nodes.
var configsUrl = clusterUrl + '/configurations?type=hdfs-exclude-file&tag=' + data.decommissionDataNodesTag;
var decomNodesAjax = {
type: 'GET',
url: configsUrl,
dataType: 'json',
timeout: App.timeout,
success: function (data) {
if (data && data.items) {
var csv = data.items[0].properties.datanodes;
if (csv!==null && csv.length>0) {
self.set('decommissionDataNodeHostNames', csv.split(','));
} else {
self.set('decommissionDataNodeHostNames', null);
}
}
},
error: function (xhr, textStatus, errorThrown) {
console.log(textStatus);
console.log(errorThrown);
}
};
jQuery.ajax(decomNodesAjax);
}
},
error: function (xhr, textStatus, errorThrown) {
// No tag pointer in persist. Rely on service's decomNodes.
var hdfsSvcs = App.HDFSService.find();
if (hdfsSvcs && hdfsSvcs.get('length') > 0) {
var hdfsSvc = hdfsSvcs.objectAt(0);
if (hdfsSvc) {
var hostNames = [];
var decomNodes = hdfsSvc.get('decommissionDataNodes');
decomNodes.forEach(function (decomNode) {
hostNames.push(decomNode.get('hostName'));
});
self.set('decommissionDataNodeHostNames', hostNames);
}
}
}
}
jQuery.ajax(getConfigAjax);
},
didInsertElement: function () {
this.loadDecommissionNodesList();
this.addToolTip();
},
addToolTip: function() {
if (this.get('addComponentDisabled')) {
$('#add_component').tooltip({title: Em.I18n.t('services.nothingToAdd')});
}
}.observes('addComponentDisabled'),
sortedComponents: function () {
var slaveComponents = [];
var masterComponents = [];
this.get('content.hostComponents').forEach(function (component) {
if (component.get('isMaster')) {
masterComponents.push(component);
} else if (component.get('isSlave')) {
slaveComponents.push(component);
}
}, this);
return masterComponents.concat(slaveComponents);
}.property('content', 'content.hostComponents.length'),
clients: function () {
var clients = [];
this.get('content.hostComponents').forEach(function (component) {
if (!component.get('componentName')) {
//temporary fix because of different data in hostComponents and serviceComponents
return;
}
if (!component.get('isSlave') && !component.get('isMaster')) {
if (clients.length) {
clients[clients.length - 1].set('isLast', false);
}
component.set('isLast', true);
clients.push(component);
}
}, this);
return clients;
}.property('content'),
addableComponentObject: Em.Object.extend({
componentName: '',
subComponentNames: null,
displayName: function () {
if (this.get('componentName') === 'CLIENTS') {
return this.t('common.clients');
}
return App.format.role(this.get('componentName'));
}.property('componentName')
}),
isAddComponent: function () {
return this.get('content.healthClass') !== 'health-status-DEAD-YELLOW';
}.property('content.healthClass'),
addComponentDisabled: function() {
return (!this.get('isAddComponent')) || (this.get('addableComponents.length') == 0);
}.property('isAddComponent', 'addableComponents.length'),
installableClientComponents: function() {
var installableClients = [];
if (!App.supports.deleteHost) {
return installableClients;
}
App.Service.find().forEach(function(svc){
switch(svc.get('serviceName')){
case 'PIG':
installableClients.push('PIG');
break;
case 'SQOOP':
installableClients.push('SQOOP');
break;
case 'HCATALOG':
installableClients.push('HCAT');
break;
case 'HDFS':
installableClients.push('HDFS_CLIENT');
break;
case 'OOZIE':
installableClients.push('OOZIE_CLIENT');
break;
case 'ZOOKEEPER':
installableClients.push('ZOOKEEPER_CLIENT');
break;
case 'HIVE':
installableClients.push('HIVE_CLIENT');
break;
case 'HBASE':
installableClients.push('HBASE_CLIENT');
break;
case 'YARN':
installableClients.push('YARN_CLIENT');
break;
case 'MAPREDUCE':
installableClients.push('MAPREDUCE_CLIENT');
break;
case 'MAPREDUCE2':
installableClients.push('MAPREDUCE2_CLIENT');
break;
}
});
this.get('content.hostComponents').forEach(function (component) {
var index = installableClients.indexOf(component.get('componentName'));
if (index > -1) {
installableClients.splice(index, 1);
}
}, this);
return installableClients;
}.property('content', 'content.hostComponents.length', 'App.Service', 'App.supports.deleteHost'),
addableComponents: function () {
var components = [];
var services = App.Service.find();
var dataNodeExists = false;
var taskTrackerExists = false;
var regionServerExists = false;
var zookeeperServerExists = false;
var nodeManagerExists = false;
var hbaseMasterExists = false;
var installableClients = this.get('installableClientComponents');
this.get('content.hostComponents').forEach(function (component) {
switch (component.get('componentName')) {
case 'DATANODE':
dataNodeExists = true;
break;
case 'TASKTRACKER':
taskTrackerExists = true;
break;
case 'HBASE_REGIONSERVER':
regionServerExists = true;
break;
case 'ZOOKEEPER_SERVER':
zookeeperServerExists = true;
break;
case 'NODEMANAGER':
nodeManagerExists = true;
break;
case 'HBASE_MASTER':
hbaseMasterExists = true;
break;
}
}, this);
if (!dataNodeExists) {
components.pushObject(this.addableComponentObject.create({ 'componentName': 'DATANODE' }));
}
if (!taskTrackerExists && services.findProperty('serviceName', 'MAPREDUCE')) {
components.pushObject(this.addableComponentObject.create({ 'componentName': 'TASKTRACKER' }));
}
if (!regionServerExists && services.findProperty('serviceName', 'HBASE')) {
components.pushObject(this.addableComponentObject.create({ 'componentName': 'HBASE_REGIONSERVER' }));
}
if (!hbaseMasterExists && services.findProperty('serviceName', 'HBASE')) {
components.pushObject(this.addableComponentObject.create({ 'componentName': 'HBASE_MASTER' }));
}
if (!zookeeperServerExists && services.findProperty('serviceName', 'ZOOKEEPER')) {
components.pushObject(this.addableComponentObject.create({ 'componentName': 'ZOOKEEPER_SERVER' }));
}
if (!nodeManagerExists && services.findProperty('serviceName', 'YARN')) {
components.pushObject(this.addableComponentObject.create({ 'componentName': 'NODEMANAGER' }));
}
if (installableClients.length > 0) {
components.pushObject(this.addableComponentObject.create({ 'componentName': 'CLIENTS', subComponentNames: installableClients }));
}
return components;
}.property('content', 'content.hostComponents.length', 'installableClientComponents'),
ComponentView: Em.View.extend({
content: null,
didInsertElement: function () {
if (this.get('isInProgress')) {
this.doBlinking();
}
},
hostComponent: function () {
var hostComponent = null;
var serviceComponent = this.get('content');
var host = App.router.get('mainHostDetailsController.content');
if (host) {
hostComponent = host.get('hostComponents').findProperty('componentName', serviceComponent.get('componentName'));
}
return hostComponent;
}.property('content', 'App.router.mainHostDetailsController.content'),
workStatus: function () {
var workStatus = this.get('content.workStatus');
var hostComponent = this.get('hostComponent');
if (hostComponent) {
workStatus = hostComponent.get('workStatus');
}
return workStatus;
}.property('content.workStatus', 'hostComponent.workStatus'),
/**
* Return host component text status
*/
componentTextStatus: function () {
var workStatus = this.get("workStatus");
var componentTextStatus = this.get('content.componentTextStatus');
var hostComponent = this.get('hostComponent');
if (hostComponent) {
componentTextStatus = hostComponent.get('componentTextStatus');
if(this.get("isDataNode"))
if(this.get('isDataNodeRecommissionAvailable')){
if(hostComponent.get('isDecommissioning')){
componentTextStatus = "Decommissioning...";
} else {
componentTextStatus = "Decommissioned";
}
}
}
return componentTextStatus;
}.property('workStatus','isDataNodeRecommissionAvailable'),
statusClass: function () {
//If the component is DataNode
if (this.get('isDataNode')) {
if (this.get('isDataNodeRecommissionAvailable') && (this.get('isStart') || this.get('workStatus') == 'INSTALLED')) {
return 'health-status-DEAD-ORANGE';
}
}
//Class when install failed
if (this.get('workStatus') === App.HostComponentStatus.install_failed) {
return 'health-status-color-red icon-cog';
}
//Class when installing
if (this.get('workStatus') === App.HostComponentStatus.installing) {
return 'health-status-color-blue icon-cog';
}
//For all other cases
return 'health-status-' + App.HostComponentStatus.getKeyName(this.get('workStatus'));
}.property('workStatus', 'isDataNodeRecommissionAvailable', 'this.content.isDecommissioning'),
disabled: function() {
return this.get('parentView.content.isNotHeartBeating')?'disabled':'';
}.property('parentView.content.isNotHeartBeating'),
/**
* For Upgrade failed state
*/
isUpgradeFailed: function () {
return App.HostComponentStatus.getKeyName(this.get('workStatus')) === "upgrade_failed";
}.property("workStatus"),
/**
* For Install failed state
*/
isInstallFailed: function () {
return App.HostComponentStatus.getKeyName(this.get('workStatus')) === "install_failed";
}.property("workStatus"),
/**
* Do blinking for 1 minute
*/
doBlinking: function () {
var workStatus = this.get('workStatus');
var self = this;
var pulsate = [ App.HostComponentStatus.starting, App.HostComponentStatus.stopping, App.HostComponentStatus.installing].contains(workStatus);
if (!pulsate && this.get('isDataNode')) {
var dataNodeComponent = this.get('content');
if (dataNodeComponent && workStatus != "INSTALLED") {
pulsate = this.get('isDecommissioning');
}
}
if (pulsate && !self.get('isBlinking')) {
self.set('isBlinking', true);
uiEffects.pulsate(self.$('.components-health'), 1000, function () {
self.set('isBlinking', false);
self.doBlinking();
});
}
},
/**
* Start blinking when host component is starting/stopping
*/
startBlinking: function () {
this.$('.components-health').stop(true, true);
this.$('.components-health').css({opacity: 1.0});
this.doBlinking();
}.observes('workStatus','isDataNodeRecommissionAvailable'),
isStart: function () {
return (this.get('workStatus') == App.HostComponentStatus.started || this.get('workStatus') == App.HostComponentStatus.starting);
}.property('workStatus'),
isInstalling: function () {
return (this.get('workStatus') == App.HostComponentStatus.installing);
}.property('workStatus'),
/**
* No action available while component is starting/stopping/unknown
*/
noActionAvailable: function () {
var workStatus = this.get('workStatus');
if ([App.HostComponentStatus.starting, App.HostComponentStatus.stopping, App.HostComponentStatus.unknown].contains(workStatus)) {
return "hidden";
}else{
return "";
}
}.property('workStatus'),
isInProgress: function () {
return (this.get('workStatus') === App.HostComponentStatus.stopping ||
this.get('workStatus') === App.HostComponentStatus.starting) ||
this.get('isDecommissioning');
}.property('workStatus', 'isDataNodeRecommissionAvailable'),
/**
* Shows whether we need to show Decommision/Recomission buttons
*/
isDataNode: function () {
return this.get('content.componentName') === 'DATANODE';
}.property('content'),
isDecommissioning: function () {
var hostComponentDecommissioning = this.get('hostComponent.isDecommissioning');
return this.get('isDataNode') && this.get("isDataNodeRecommissionAvailable") && hostComponentDecommissioning;
}.property("workStatus", "isDataNodeRecommissionAvailable", "hostComponent.isDecommissioning"),
/**
* Set in template via binding from parent view
*/
decommissionDataNodeHostNames: null,
/**
* Decommission is available whenever the service is started.
*/
isDataNodeDecommissionAvailable: function () {
return this.get('isStart') && !this.get('isDataNodeRecommissionAvailable');
}.property('isStart', 'isDataNodeRecommissionAvailable'),
/**
* Recommission is available only when this hostname shows up in the
* 'decommissionDataNodeHostNames'
*/
isDataNodeRecommissionAvailable: function () {
var decommissionHostNames = this.get('decommissionDataNodeHostNames');
var hostName = App.router.get('mainHostDetailsController.content.hostName');
return decommissionHostNames != null && decommissionHostNames.contains(hostName);
}.property('App.router.mainHostDetailsController.content', 'decommissionDataNodeHostNames'),
/**
* Shows whether we need to show Delete button
*/
isHBaseMaster: function () {
return this.get('content.componentName') === 'HBASE_MASTER';
}.property('content'),
isDeleteHBaseMasterDisabled: function () {
return !(this.get('workStatus') == App.HostComponentStatus.stopped || this.get('workStatus') == App.HostComponentStatus.unknown ||
this.get('workStatus') == App.HostComponentStatus.install_failed || this.get('workStatus') == App.HostComponentStatus.upgrade_failed);
}.property('workStatus'),
isReassignable: function () {
return App.supports.reassignMaster && App.reassignableComponents.contains(this.get('content.componentName')) && App.Host.find().content.length > 1;
}.property('content.componentName')
}),
timeSinceHeartBeat: function () {
var d = this.get('content.lastHeartBeatTime');
if (d) {
return $.timeago(d);
}
return "";
}.property('content.lastHeartBeatTime')
});