blob: 4950b6b2243c3e3764574553dee99ad78f73ee48 [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');
require('utils/configs/defaults_providers/defaultsProvider');
App.YARNDefaultsProvider = App.DefaultsProvider.create({
/**
* List of the configs that should be calculated
*/
configsTemplate: {
'yarn.nodemanager.resource.memory-mb': null,
'yarn.scheduler.minimum-allocation-mb': null,
'yarn.scheduler.maximum-allocation-mb': null,
'mapreduce.map.memory.mb': null,
'mapreduce.reduce.memory.mb': null,
'mapreduce.map.java.opts': null,
'mapreduce.reduce.java.opts': null,
'mapreduce.task.io.sort.mb': null,
'yarn.app.mapreduce.am.resource.mb': null,
'yarn.app.mapreduce.am.command-opts': null
},
/**
* Information about ram, disk count, cpu count and hbase availability
* Example:
* {
* disk: 12,
* ram: 48 * 1024, // MB
* cpu: 12,
* hBaseInstalled: false
* }
*/
clusterData: null,
/**
* Reserved for system memory
*
* Value in MB!
*/
reservedRam: null,
/**
* Reserved for HBase memory
*
* Value in MB!
*/
hBaseRam: null,
GB: 1024,
/**
* Minimum container size (in RAM).
* This value is dependent on the amount of RAM available, as in smaller memory nodes the minimum container size should also be smaller
*
* Value in MB!
*/
recommendedMinimumContainerSize: function () {
if (!this.clusterDataIsValid()) return null;
var ram = this.get('clusterData.ram');
switch (true) {
case (ram <=4 ):
return 256;
case (ram <= 8):
return 512;
case (ram <= 24):
return 1024;
default:
return 2048;
}
}.property('clusterData.ram'),
/**
* Maximum number of containers allowed per node
* max(3, min (2*cores,min (1.8*DISKS,(Total available RAM) / MIN_CONTAINER_SIZE))))
*/
containers: function () {
if (!this.clusterDataIsValid()) return null;
var cpu = this.get('clusterData.cpu');
var disk = this.get('clusterData.disk');
var ram = this.get('clusterData.ram');
var containerSize = this.get('recommendedMinimumContainerSize');
cpu *= 2;
disk = Math.ceil(disk * 1.8);
ram = (ram - this.get('reservedRam'));
if (this.get('clusterData.hBaseInstalled')) {
ram -= this.get('hBaseRam')
}
// On low memory systems, memory left over after
// removing reserved-RAM and HBase might be
// less than 2GB (even negative). If so, we force
// a 2GB value relying on virtual memory.
if (ram < 2) {
ram = 2;
}
ram *= this.get('GB');
ram /= containerSize;
return Math.round(Math.max(3, Math.min(cpu, Math.min(disk, ram))));
}.property('clusterData.cpu', 'clusterData.ram', 'clusterData.hBaseInstalled', 'clusterData.disk', 'reservedRam', 'hBaseRam', 'recommendedMinimumContainerSize'),
/**
* Amount of RAM per container.
* Calculated to be max(2GB, RAM - reservedRam - hBaseRam) / containers
*
* @return Memory per container in MB. If greater than 1GB,
* value will be in multiples of 512.
*/
ramPerContainer: function () {
var containers = this.get('containers');
var ram = this.get('clusterData.ram');
ram = (ram - this.get('reservedRam'));
if (this.get('clusterData.hBaseInstalled')) {
ram -= this.get('hBaseRam')
}
// On low memory systems, memory left over after
// removing reserved-RAM and HBase might be
// less than 2GB (even negative). If so, we force
// a 2GB value relying on virtual memory.
if (ram < 2) {
ram = 2;
}
ram *= this.get('GB');
var container_ram = Math.abs(ram / containers);
// If container memory is greater than 1GB,
// we use multiples of 512 as value
return container_ram > this.get('GB') ? (Math.floor(container_ram / 512) * 512) : container_ram;
}.property('recommendedMinimumContainerSize', 'containers', 'clusterData.ram', 'clusterData.hBaseInstalled', 'hBaseRam', 'reservedRam'),
mapMemory: function () {
return Math.floor(this.get('ramPerContainer') / 2);
}.property('ramPerContainer'),
reduceMemory: function () {
return this.get('ramPerContainer');
}.property('ramPerContainer'),
amMemory: function () {
return Math.max(this.get('mapMemory'), this.get('reduceMemory'));
}.property('mapMemory', 'reduceMemory'),
/**
* Reserved for HBase and system memory is based on total available memory
*/
reservedStackRecommendations: function () {
var memory = this.get('clusterData.ram');
var reservedStack = { 4: 1, 8: 2, 16: 2, 24: 4, 48: 6, 64: 8, 72: 8, 96: 12,
128: 24, 256: 32, 512: 64};
if (memory in reservedStack) {
this.set('reservedRam', reservedStack[memory]);
}
if (memory <= 4)
this.set('reservedRam', 1);
else if (memory >= 512)
this.set('reservedRam', 64);
else
this.set('reservedRam', 1);
}.observes('clusterData.ram'),
hbaseMemRecommendations: function () {
var memory = this.get('clusterData.ram');
var reservedHBase = {4:1, 8:1, 16:2, 24:4, 48:8, 64:8, 72:8, 96:16,
128:24, 256:32, 512:64};
if (memory in reservedHBase) {
this.set('reservedRam', reservedHBase[memory]);
}
if (memory <= 4)
this.set('hBaseRam', 1);
else if (memory >= 512)
this.set('hBaseRam', 64);
else
this.set('hBaseRam', 2);
}.observes('clusterData.ram'),
/**
* Provide an object where keys are property-names and values are the recommended defaults
* @param {object} localDB Object with information about hosts and master/slave components
* Example:
* <code>
* {
* "hosts": {
* "host1": {
* "name": "host1",
* "cpu": 1,
* "memory": "6123683.00",
* "disk_info": [{
* ....
* },...]
* },...
* },
* "masterComponentHosts": [{
* "component": "NAMENODE",
* "hostName": "host1",
* "serviceId": "HDFS"
* },...],
* "slaveComponentHosts": [{
* "componentName": "DATANODE",
* "hosts": [{
* "hostName": "host2"
* }]
* },...]
* }
* </code>
* @return {object}
*/
getDefaults: function (localDB) {
this._super();
this.getClusterData(localDB);
var configs = {};
jQuery.extend(configs, this.get('configsTemplate'));
configs['yarn.nodemanager.resource.memory-mb'] = Math.round(this.get('containers') * this.get('ramPerContainer'));
configs['yarn.scheduler.minimum-allocation-mb'] = Math.round(this.get('ramPerContainer'));
configs['yarn.scheduler.maximum-allocation-mb'] = Math.round(this.get('containers') * this.get('ramPerContainer'));
configs['yarn.app.mapreduce.am.resource.mb'] = Math.round(this.get('amMemory'));
configs['yarn.app.mapreduce.am.command-opts'] = "-Xmx" + Math.round(0.8 * this.get('amMemory')) + "m";
configs['mapreduce.map.memory.mb'] = Math.round(this.get('mapMemory'));
configs['mapreduce.reduce.memory.mb'] = Math.round(this.get('reduceMemory'));
configs['mapreduce.map.java.opts'] = "-Xmx" + Math.round(0.8 * this.get('mapMemory')) + "m";
configs['mapreduce.reduce.java.opts'] = "-Xmx" + Math.round(0.8 * this.get('reduceMemory')) + "m";
configs['mapreduce.task.io.sort.mb'] = Math.round(0.4 * this.get('mapMemory'));
return configs;
},
/**
* Calculate needed cluster data (like disk count, cpu count, ram (in MB!) and hbase availability)
* @param {object} localDB Object with information about hosts and master/slave components
*/
getClusterData: function (localDB) {
this._super();
var components = ['NODEMANAGER'];
var hosts = [];
if (!localDB.hosts || !(localDB.masterComponentHosts || localDB.slaveComponentHosts)) return;
var hBaseInstalled = !!localDB.masterComponentHosts.filterProperty('component', 'HBASE_MASTER').length;
components.forEach(function (component) {
var mc = localDB.masterComponentHosts.findProperty('component', component);
if (mc) {
if (!hosts.contains(mc.hostName)) {
hosts.push(mc.hostName);
}
}
else {
var sc = localDB.slaveComponentHosts.findProperty('componentName', component);
if (sc) {
sc.hosts.map(function (host) {
if (!hosts.contains(host.hostName)) {
hosts.push(host.hostName);
}
});
}
}
});
var clusterData = {
cpu: 0,
disk: 0,
ram: 0,
hBaseInstalled: hBaseInstalled
};
var host = hosts[0] && localDB.hosts[hosts[0]];
if (host) {
clusterData.cpu = parseInt(host.cpu);
var length = 0;
host.disk_info.forEach(function(disk) {
//invalid mountpoints
if (!(disk.mountpoint.startsWith('/home/') || disk.mountpoint.startsWith('/homes/') ||
disk.mountpoint.startsWith('/dev/') || disk.mountpoint.startsWith('/tmp/'))) {
length++;
}
},this);
clusterData.disk = length;
clusterData.ram = Math.round(parseFloat(host.memory) / (1024 * 1024));
}
this.set('clusterData', clusterData);
},
/**
* Verify <code>clusterData</code> - check if all properties are defined
*/
clusterDataIsValid: function () {
if (!this.get('clusterData')) return false;
if (this.get('clusterData.ram') == null || this.get('clusterData.cpu') == null || this.get('clusterData.disk') == null || this.get('clusterData.hBaseInstalled') == null) return false;
return true;
}
});