You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sr...@apache.org on 2013/10/31 23:48:19 UTC

[2/3] git commit: AMBARI-3644. App.ServiceConfig needs 'defaultsProvider' mechanism. (onechiporenko via srimanth)

AMBARI-3644. App.ServiceConfig needs 'defaultsProvider' mechanism. (onechiporenko via srimanth)


Project: http://git-wip-us.apache.org/repos/asf/incubator-ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ambari/commit/ea86d690
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ambari/tree/ea86d690
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ambari/diff/ea86d690

Branch: refs/heads/trunk
Commit: ea86d6904b2f761aa761dd7aee9efa7ca96c5b31
Parents: 2a0bf71
Author: Srimanth Gunturi <sg...@hortonworks.com>
Authored: Thu Oct 31 15:02:47 2013 -0700
Committer: Srimanth Gunturi <sg...@hortonworks.com>
Committed: Thu Oct 31 15:02:47 2013 -0700

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |   1 +
 ambari-web/app/data/service_configs.js          |   4 +-
 ambari-web/app/utils/config.js                  |  17 ++
 .../defaults_providers/defaultsProvider.js      |  37 +++
 .../yarn_defaults_provider.js                   | 272 +++++++++++++++++
 .../yarn_defaults_provider_test.js              | 295 +++++++++++++++++++
 6 files changed, 625 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ea86d690/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index 521a0cc..37edd6a 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -61,6 +61,7 @@ require('test/mappers/runs_mapper_test');
 require('test/mappers/service_mapper_test');
 require('test/mappers/status_mapper_test');
 require('test/mappers/users_mapper_test');
+require('test/utils/defaults_providers/yarn_defaults_provider_test');
 require('test/utils/config_test');
 require('test/utils/date_test');
 require('test/utils/config_test');

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ea86d690/ambari-web/app/data/service_configs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/data/service_configs.js b/ambari-web/app/data/service_configs.js
index f87e6d0..b7857b1 100644
--- a/ambari-web/app/data/service_configs.js
+++ b/ambari-web/app/data/service_configs.js
@@ -18,7 +18,7 @@
 
 var App = require('app');
 require('models/service_config');
-
+require('utils/defaults_providers/yarn_defaults_provider');
 
 module.exports = [
   {
@@ -66,6 +66,7 @@ module.exports = [
   {
     serviceName: 'YARN',
     displayName: 'YARN',
+    defaultsProviders: [App.YARNDefaultsProvider],
     filename: 'yarn-site',
     configCategories: [
       App.ServiceConfigCategory.create({ name: 'ResourceManager', displayName : 'Resource Manager', hostComponentNames : ['RESOURCEMANAGER']}),
@@ -83,6 +84,7 @@ module.exports = [
     serviceName: 'MAPREDUCE2',
     displayName: 'MapReduce 2',
     filename: 'mapred-site',
+    defaultsProviders: [App.YARNDefaultsProvider],
     configCategories: [
       App.ServiceConfigCategory.create({ name: 'HistoryServer', displayName : 'History Server', hostComponentNames : ['HISTORYSERVER']}),
       App.ServiceConfigCategory.create({ name: 'General', displayName : 'General'}),

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ea86d690/ambari-web/app/utils/config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/config.js b/ambari-web/app/utils/config.js
index eae8b6f..f03554f 100644
--- a/ambari-web/app/utils/config.js
+++ b/ambari-web/app/utils/config.js
@@ -461,8 +461,10 @@ App.config = Em.Object.create({
    * render configs, distribute them by service
    * and wrap each in ServiceConfigProperty object
    * @param configs
+   * @param storedConfigs
    * @param allInstalledServiceNames
    * @param selectedServiceNames
+   * @param localDB
    * @return {Array}
    */
   renderConfigs: function (configs, storedConfigs, allInstalledServiceNames, selectedServiceNames, localDB) {
@@ -496,6 +498,21 @@ App.config = Em.Object.create({
       }, this);
       serviceConfig = this.createServiceConfig(service.serviceName);
       serviceConfig.set('showConfig', service.showConfig);
+
+      // Use calculated default values for some configs
+      if (service.defaultsProviders) {
+        service.defaultsProviders.forEach(function(defaultsProvider) {
+          var defaults = defaultsProvider.getDefaults(localDB);
+          for(var name in defaults) {
+            var config = configsByService.findProperty('name', name);
+            if (config) {
+              config.set('value', defaults[name]);
+              config.set('defaultValue', defaults[name]);
+            }
+          }
+        });
+      }
+
       serviceConfig.set('configs', configsByService);
       renderedServiceConfigs.push(serviceConfig);
     }, this);

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ea86d690/ambari-web/app/utils/defaults_providers/defaultsProvider.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/defaults_providers/defaultsProvider.js b/ambari-web/app/utils/defaults_providers/defaultsProvider.js
new file mode 100644
index 0000000..1eaad12
--- /dev/null
+++ b/ambari-web/app/utils/defaults_providers/defaultsProvider.js
@@ -0,0 +1,37 @@
+/**
+ * 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');
+
+App.DefaultsProvider = Em.Object.extend({
+
+  /**
+   * Look at cluster setup, the provided properties, and provide an object where keys are property-names, and values are the recommended defaults
+   * @param {App.ServiceConfigProperty} serviceConfigProperty
+   */
+  getDefaults: function(serviceConfigProperty) {
+
+  },
+
+  /**
+   * Cluster info used to calculate properties values
+   * Should be redeclared in the child providers
+   */
+  getClusterData: function() {
+
+  }
+});

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ea86d690/ambari-web/app/utils/defaults_providers/yarn_defaults_provider.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/defaults_providers/yarn_defaults_provider.js b/ambari-web/app/utils/defaults_providers/yarn_defaults_provider.js
new file mode 100644
index 0000000..0ae3e70
--- /dev/null
+++ b/ambari-web/app/utils/defaults_providers/yarn_defaults_provider.js
@@ -0,0 +1,272 @@
+/**
+ * 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/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,
+    '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,
+
+  /**
+   *  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*1024): return 256;
+      case (ram >= 4*1024 && ram < 8*1024): return 512;
+      case (ram >= 8*1024 && ram < 24*1024): return 1024;
+      case (ram >= 24*1024):
+      default: return 2048;
+    }
+  }.property('clusterData.ram'),
+
+  /**
+   * Maximum number of containers allowed per node
+   * min (2*CORES, 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 *= 1.8;
+    ram = (ram - this.get('reservedRam'));
+    if (this.get('clusterData.hBaseInstalled')) {
+      ram -= this.get('hBaseRam')
+    }
+    ram /= containerSize;
+    if (cpu < disk) {
+      if (cpu < ram) {
+        return cpu;
+      }
+      return ram;
+    }
+    else {
+      if (disk < ram) {
+        return parseInt(disk);
+      }
+      return ram;
+    }
+  }.property('clusterData.cpu', 'clusterData.ram', 'clusterData.disk', 'recommendedMinimumContainerSize'),
+
+  /**
+   * amount of RAM per container
+   * RAM-per-container = max(MIN_CONTAINER_SIZE, (Total Available RAM) / containers))
+   *
+   * Value in MB!
+   */
+  ramPerContainer: function() {
+    var containerSize = this.get('recommendedMinimumContainerSize');
+    var containers = this.get('containers');
+    if (!containerSize || !containers) {
+      return null;
+    }
+    var s = this.get('clusterData.ram') - this.get('reservedRam');
+    if (this.get('clusterData.hBaseInstalled')) {
+      s -= this.get('hBaseRam');
+    }
+    s /= containers;
+    return (containerSize > s) ? containerSize : s;
+  }.property('recommendedMinimumContainerSize', 'containers'),
+
+  /**
+   * Reserved for HBase and system memory is based on total available memory
+   */
+  reservedMemoryRecommendations: function() {
+    var table = [
+      {os:1,hbase:1},
+      {os:2,hbase:1},
+      {os:2,hbase:2},
+      {os:4,hbase:4},
+      {os:6,hbase:8},
+      {os:8,hbase:8},
+      {os:8,hbase:8},
+      {os:12,hbase:16},
+      {os:24,hbase:24},
+      {os:32,hbase:32},
+      {os:64,hbase:64}
+    ];
+    var ram = this.get('clusterData.ram') / 1024;
+    var index = 0;
+    switch (true) {
+      case (ram <= 4): index = 0; break;
+      case (ram > 4 && ram <= 8): index = 1; break;
+      case (ram > 8 && ram <= 16): index = 2; break;
+      case (ram > 16 && ram <= 24): index = 3; break;
+      case (ram > 24 && ram <= 48): index = 4; break;
+      case (ram > 48 && ram <= 64): index = 5; break;
+      case (ram > 64 && ram <= 72): index = 6; break;
+      case (ram > 72 && ram <= 96): index = 7; break;
+      case (ram > 96 && ram <= 128): index = 8; break;
+      case (ram > 128 && ram <= 256): index = 9; break;
+      case (ram > 256 && ram <= 512): index = 10; break;
+      default: index = 10; break;
+    }
+    this.set('reservedRam', table[index].os * 1024);
+    this.set('hBaseRam', table[index].hbase * 1024);
+  }.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'] = this.get('containers') * this.get('ramPerContainer');
+    configs['yarn.scheduler.minimum-allocation-mb'] = this.get('ramPerContainer');
+    configs['yarn.scheduler.maximum-allocation-mb'] = this.get('containers') * this.get('ramPerContainer');
+    configs['mapreduce.map.memory.mb'] = this.get('ramPerContainer');
+    configs['mapreduce.reduce.memory.mb'] = 2 * this.get('ramPerContainer');
+    configs['mapreduce.map.java.opts'] = Math.round(0.8 * this.get('ramPerContainer'));
+    configs['mapreduce.reduce.java.opts'] = Math.round(0.8 *2 * this.get('ramPerContainer'));
+    configs['yarn.app.mapreduce.am.resource.mb'] = 2 * this.get('ramPerContainer');
+    configs['yarn.app.mapreduce.am.command-opts'] = Math.round(0.8 * 2 * this.get('ramPerContainer'));
+    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 = ['RESOURCEMANAGER', '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
+    };
+    hosts.forEach(function(hostName) {
+      var host = localDB.hosts[hostName];
+      if (host) {
+        clusterData.cpu += parseInt(host.cpu);
+        clusterData.disk += host.disk_info.length;
+        clusterData.ram += Math.round(parseFloat(host.memory) / 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;
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ea86d690/ambari-web/test/utils/defaults_providers/yarn_defaults_provider_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/defaults_providers/yarn_defaults_provider_test.js b/ambari-web/test/utils/defaults_providers/yarn_defaults_provider_test.js
new file mode 100644
index 0000000..4f1efef
--- /dev/null
+++ b/ambari-web/test/utils/defaults_providers/yarn_defaults_provider_test.js
@@ -0,0 +1,295 @@
+/**
+ * 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/defaults_providers/defaultsProvider');
+require('utils/defaults_providers/yarn_defaults_provider');
+
+describe('YARNDefaultsProvider', function() {
+
+  describe('#clusterDataIsValid', function() {
+    var tests = [
+      {clusterData: {disk: 12,ram: 48 * 1024,cpu: 12,hBaseInstalled: false},e: true},
+      {clusterData: {disk: null,ram: 48 * 1024,cpu: 12,hBaseInstalled: false},e: false},
+      {clusterData: {disk: 12,ram: null,cpu: 12,hBaseInstalled: false},e: false},
+      {clusterData: {disk: 12,ram: 48 * 1024,cpu: null,hBaseInstalled: false},e: false},
+      {clusterData: {disk: 12,ram: 48 * 1024,cpu: 12,hBaseInstalled: null},e: false},
+      {clusterData: {disk: 12,ram: 48 * 1024,cpu: 12},e: false},
+      {clusterData: {disk: 12,ram: 48 * 1024,hBaseInstalled: true},e: false},
+      {clusterData: {disk: 12,cpu: 12,hBaseInstalled: true},e: false},
+      {clusterData: {ram: 48 * 1024,cpu: 12,hBaseInstalled: false},e: false}
+    ];
+    tests.forEach(function(test) {
+      it((test.e?'valid':'invalid') + ' clusterData', function() {
+        App.YARNDefaultsProvider.set('clusterData', test.clusterData);
+        expect(App.YARNDefaultsProvider.clusterDataIsValid()).to.equal(test.e);
+      });
+    });
+  });
+
+  describe('#reservedMemoryRecommendations', function() {
+    var tests = [
+      {ram: null, e: {os: 1, hbase: 1}},
+      {ram: 2, e: {os: 1, hbase: 1}},
+      {ram: 4, e: {os: 1, hbase: 1}},
+      {ram: 6, e: {os: 2, hbase: 1}},
+      {ram: 8, e: {os: 2, hbase: 1}},
+      {ram: 12, e: {os: 2, hbase: 2}},
+      {ram: 16, e: {os: 2, hbase: 2}},
+      {ram: 20, e: {os: 4, hbase: 4}},
+      {ram: 24, e: {os: 4, hbase: 4}},
+      {ram: 36, e: {os: 6, hbase: 8}},
+      {ram: 48, e: {os: 6, hbase: 8}},
+      {ram: 56, e: {os: 8, hbase: 8}},
+      {ram: 64, e: {os: 8, hbase: 8}},
+      {ram: 68, e: {os: 8, hbase: 8}},
+      {ram: 72, e: {os: 8, hbase: 8}},
+      {ram: 84, e: {os: 12, hbase: 16}},
+      {ram: 96, e: {os: 12, hbase: 16}},
+      {ram: 112, e: {os: 24, hbase: 24}},
+      {ram: 128, e: {os: 24, hbase: 24}},
+      {ram: 196, e: {os: 32, hbase: 32}},
+      {ram: 256, e: {os: 32, hbase: 32}},
+      {ram: 384, e: {os: 64, hbase: 64}},
+      {ram: 512, e: {os: 64, hbase: 64}},
+      {ram: 756, e: {os: 64, hbase: 64}}
+    ];
+    App.YARNDefaultsProvider.set('clusterData');
+    tests.forEach(function(test) {
+      it('ram: ' + test.ram + ' GB', function() {
+        App.YARNDefaultsProvider.set('clusterData', {
+          disk: 12,
+          ram: test.ram * 1024,
+          cpu: 12,
+          hBaseInstalled: false
+        });
+        expect(App.YARNDefaultsProvider.get('reservedRam')).to.equal(test.e.os * 1024);
+        expect(App.YARNDefaultsProvider.get('hBaseRam')).to.equal(test.e.hbase * 1024);
+      });
+    });
+  });
+
+  describe('#recommendedMinimumContainerSize', function() {
+    it('No clusterData', function() {
+      App.YARNDefaultsProvider.set('clusterData', null);
+      expect(App.YARNDefaultsProvider.get('recommendedMinimumContainerSize')).to.equal(null);
+    });
+    it('No clusterData.ram', function() {
+      App.YARNDefaultsProvider.set('clusterData', {});
+      expect(App.YARNDefaultsProvider.get('recommendedMinimumContainerSize')).to.equal(null);
+    });
+
+    var tests = [
+      {ram: 3, e: 256},
+      {ram: 4, e: 512},
+      {ram: 6, e: 512},
+      {ram: 8, e: 1024},
+      {ram: 12, e: 1024},
+      {ram: 24, e: 2048}
+    ];
+
+    tests.forEach(function(test) {
+      it('ram: ' + test.ram + ' GB', function() {
+        App.YARNDefaultsProvider.set('clusterData', {
+          disk: 12,
+          ram: test.ram * 1024,
+          cpu: 12,
+          hBaseInstalled: false
+        });
+        expect(App.YARNDefaultsProvider.get('recommendedMinimumContainerSize')).to.equal(test.e);
+      });
+    });
+
+  });
+
+  describe('#containers', function() {
+    it('No clusterData', function() {
+      App.YARNDefaultsProvider.set('clusterData', null);
+      expect(App.YARNDefaultsProvider.get('containers')).to.equal(null);
+    });
+    it('Some clusterData metric is null', function() {
+      App.YARNDefaultsProvider.set('clusterData', {disk: null, cpu: 1, ram: 1});
+      expect(App.YARNDefaultsProvider.get('containers')).to.equal(null);
+      App.YARNDefaultsProvider.set('clusterData', {disk: 1, cpu: null, ram: 1});
+      expect(App.YARNDefaultsProvider.get('containers')).to.equal(null);
+      App.YARNDefaultsProvider.set('clusterData', {disk:1, cpu: 1, ram: null});
+      expect(App.YARNDefaultsProvider.get('containers')).to.equal(null);
+    });
+
+    var tests = [
+      {
+        clusterData: {
+          disk: 12,
+          ram: 48 * 1024,
+          cpu: 12,
+          hBaseInstalled: false
+        },
+        e: 21
+      },
+      {
+        clusterData: {
+          disk: 12,
+          ram: 48 * 1024,
+          cpu: 12,
+          hBaseInstalled: true
+        },
+        e: 17
+      }
+    ];
+
+    tests.forEach(function(test) {
+      it((test.hBaseInstalled?'With':'Without') + ' hBase', function() {
+        App.YARNDefaultsProvider.set('clusterData', test.clusterData);
+        expect(App.YARNDefaultsProvider.get('containers')).to.equal(test.e);
+      });
+    });
+
+  });
+
+  describe('#ramPerContainer', function() {
+    it('No clusterData', function() {
+      App.YARNDefaultsProvider.set('clusterData', null);
+      expect(App.YARNDefaultsProvider.get('ramPerContainer')).to.equal(null);
+    });
+    var tests = [
+      {
+        clusterData: {
+          disk: 12,
+          ram: 48 * 1024,
+          cpu: 12,
+          hBaseInstalled: false
+        },
+        e: 2048
+      },
+      {
+        clusterData: {
+          disk: 12,
+          ram: 16 * 1024,
+          cpu: 12,
+          hBaseInstalled: true
+        },
+        e: 1024
+      }
+    ];
+
+    tests.forEach(function(test) {
+      it((test.hBaseInstalled?'With':'Without') + ' hBase', function() {
+        App.YARNDefaultsProvider.set('clusterData', test.clusterData);
+        expect(App.YARNDefaultsProvider.get('ramPerContainer')).to.equal(test.e);
+      });
+    });
+  });
+
+  describe('#getDefaults', function() {
+    var tests = [
+      {
+        localDB: {},
+        m: 'Empty localDB',
+        e: null
+      },
+      {
+        localDB: {
+          "masterComponentHosts": []
+        },
+        m: 'localDB without hosts',
+        e: null
+      },
+      {
+        localDB: {
+          "hosts": {}
+        },
+        m: 'localDB without masterComponentHosts amd slaveComponentHosts',
+        e: null
+      },
+      {
+        localDB: {
+          "hosts": {
+            "host1": {"name": "host1","cpu": 8,"memory": "25165824.00","disk_info": [{},{},{},{},{},{},{},{}]},
+            "host2": {"name": "host2","cpu": 4,"memory": "25165824.00","disk_info": [{},{},{},{}]}
+          },
+          "masterComponentHosts": [
+            {"component": "RESOURCEMANAGER","hostName": "host1","serviceId": "HDFS"}
+          ],
+          "slaveComponentHosts": [
+            {
+              "componentName": "NODEMANAGER",
+              "hosts": [{"hostName": "host2"}]
+            }
+          ]
+        },
+        m: 'Without HBase',
+        e: {
+          'mapreduce.map.java.opts': 1638,
+          'mapreduce.map.memory.mb': 2048,
+          'mapreduce.reduce.java.opts': 3277,
+          'mapreduce.reduce.memory.mb': 4096,
+          'yarn.app.mapreduce.am.command-opts': 3277,
+          'yarn.app.mapreduce.am.resource.mb': 4096,
+          'yarn.nodemanager.resource.memory-mb': 43008,
+          'yarn.scheduler.maximum-allocation-mb': 43008,
+          'yarn.scheduler.minimum-allocation-mb': 2048
+        }
+      },
+      {
+        localDB: {
+          "hosts": {
+            "host1": {"name": "host1","cpu": 8,"memory": "25165824.00","disk_info": [{},{},{},{},{},{},{},{}]},
+            "host2": {"name": "host2","cpu": 4,"memory": "12582912.00","disk_info": [{},{},{},{}]}
+          },
+          "masterComponentHosts": [
+            {"component": "RESOURCEMANAGER","hostName": "host1","serviceId": "HDFS"},
+            {"component": "HBASE_MASTER","hostName": "host1","serviceId": "HDFS"}
+          ],
+          "slaveComponentHosts": [
+            {
+              "componentName": "NODEMANAGER",
+              "hosts": [{"hostName": "host2"}]
+            }
+          ]
+        },
+        m: 'With HBase',
+        e: {
+          'mapreduce.map.java.opts': 1638,
+          'mapreduce.map.memory.mb': 2048,
+          'mapreduce.reduce.java.opts': 3277,
+          'mapreduce.reduce.memory.mb': 4096,
+          'yarn.app.mapreduce.am.command-opts': 3277,
+          'yarn.app.mapreduce.am.resource.mb': 4096,
+          'yarn.nodemanager.resource.memory-mb': 22528,
+          'yarn.scheduler.maximum-allocation-mb': 22528,
+          'yarn.scheduler.minimum-allocation-mb': 2048
+        }
+      }
+    ];
+    tests.forEach(function(test) {
+      it(test.m, function() {
+        App.YARNDefaultsProvider.set('clusterData', null);
+        var configs = App.YARNDefaultsProvider.getDefaults(test.localDB);
+
+        for(var config in configs) {
+          if (test.e) {
+            expect(configs[config]).to.equal(test.e[config]);
+          }
+          else {
+            expect(configs[config] == 0 || configs[config] == null).to.equal(true);
+          }
+        }
+      });
+    });
+  });
+
+});