You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by on...@apache.org on 2014/01/20 18:10:50 UTC
git commit: AMBARI-4349. Slaves API-calls. (onechiporenko)
Updated Branches:
refs/heads/trunk aae72dfaf -> 6974a6be3
AMBARI-4349. Slaves API-calls. (onechiporenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/6974a6be
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/6974a6be
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/6974a6be
Branch: refs/heads/trunk
Commit: 6974a6be3b18e8788c82db088b20f3090a8312d2
Parents: aae72df
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Mon Jan 20 19:10:30 2014 +0200
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Mon Jan 20 19:10:30 2014 +0200
----------------------------------------------------------------------
ambari-web/app/assets/test/tests.js | 1 +
ambari-web/app/controllers/main/host.js | 150 ++++++++++++++++++-
ambari-web/app/messages.js | 4 +
ambari-web/app/utils/ajax.js | 47 +++++-
.../app/utils/batch_scheduled_requests.js | 6 +-
ambari-web/app/views/main/host.js | 2 +-
.../views/main/host/hosts_table_menu_view.js | 79 ++++------
.../test/utils/batch_scheduled_requests_test.js | 89 +++++++++++
8 files changed, 320 insertions(+), 58 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/6974a6be/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 8190608..20ff4b3 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -63,6 +63,7 @@ require('test/mappers/users_mapper_test');
require('test/utils/configs/defaults_providers/yarn_defaults_provider_test');
require('test/utils/configs/validators/service_configs_validator_test');
require('test/utils/ajax_test');
+require('test/utils/batch_scheduled_requests_test');
require('test/utils/config_test');
require('test/utils/date_test');
require('test/utils/config_test');
http://git-wip-us.apache.org/repos/asf/ambari/blob/6974a6be/ambari-web/app/controllers/main/host.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host.js b/ambari-web/app/controllers/main/host.js
index bca67a4..5536742 100644
--- a/ambari-web/app/controllers/main/host.js
+++ b/ambari-web/app/controllers/main/host.js
@@ -19,6 +19,7 @@
var App = require('app');
var validator = require('utils/validator');
var componentHelper = require('utils/component');
+var batchUtils = require('utils/batch_scheduled_requests');
App.MainHostController = Em.ArrayController.extend({
name:'mainHostController',
@@ -137,12 +138,155 @@ App.MainHostController = Em.ArrayController.extend({
},
/**
- * Do bulk operation for selected hosts or hostComponents
+ * Bulk operation wrapper
* @param {Object} operationData - data about bulk operation (action, hosts or hostComponents etc)
- * @param {Array} hostNames - list of affected hostNames
+ * @param {Array} hosts - list of affected hosts
*/
- bulkOperation: function(operationData, hostNames) {
+ bulkOperation: function(operationData, hosts) {
+ if (operationData.componentNameFormatted) {
+ if (operationData.action === 'RESTART') {
+ this.bulkOperationForHostComponentsRestart(operationData, hosts);
+ }
+ else {
+ if (operationData.action.indexOf('DECOMMISSION') != -1) {
+ this.bulkOperationForHostComponentsDecommission(operationData, hosts);
+ }
+ else {
+ this.bulkOperationForHostComponents(operationData, hosts);
+ }
+ }
+ }
+ },
+
+ /**
+ * Do bulk operation for selected hostComponents
+ * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
+ * @param {Array} hosts - list of affected hosts
+ */
+ bulkOperationForHostComponents: function(operationData, hosts) {
+ var hostsWithSelectedComponent = [];
+ hosts.forEach(function(host) {
+ var components = host.get('hostComponents');
+ if (components.findProperty('componentName', operationData.componentName)) {
+ hostsWithSelectedComponent.push(host);
+ }
+ });
+ var service = App.Service.find(operationData.serviceName);
+ var components = service.get('hostComponents').filter(function(hc) {
+ if (hc.get('componentName') != operationData.componentName) {
+ return false;
+ }
+ if(hc.get('workStatus') == operationData.action) {
+ return false;
+ }
+ return hosts.contains(hc.get('host'));
+ });
+ if (components.length) {
+ var hostsWithComponentInProperState = components.mapProperty('host.hostName');
+ App.ajax.send({
+ name: 'bulk_request.host_components',
+ sender: this,
+ data: {
+ hostNames: hostsWithComponentInProperState.join(','),
+ state: operationData.action,
+ requestInfo: operationData.message + ' ' + operationData.componentNameFormatted,
+ componentName: operationData.componentName
+ },
+ success: 'bulkOperationForHostComponentsSuccessCallback'
+ });
+ }
+ else {
+ App.ModalPopup.show({
+ header: Em.I18n.t('rolling.nothingToDo.header'),
+ body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
+ secondary: false
+ });
+ }
+ },
+
+ /**
+ * Bulk decommission for selected hostComponents
+ * @param {Object} operationData
+ * @param {Array} hosts
+ */
+ bulkOperationForHostComponentsDecommission: function(operationData, hosts) {
+ var service = App.Service.find(operationData.serviceName);
+ var components = service.get('hostComponents').filter(function(hc) {
+ if (hc.get('componentName') != operationData.realComponentName) {
+ return false;
+ }
+ return hosts.contains(hc.get('host'));
+ });
+
+ if (components.length) {
+ var hostsWithComponentInProperState = components.mapProperty('host.hostName');
+ var turn_off = operationData.action.indexOf('OFF') !== -1;
+ var parameters = {
+ "slave_type": operationData.realComponentName
+ };
+ if (turn_off) {
+ parameters['included_hosts'] = hostsWithComponentInProperState.join(',')
+ }
+ else {
+ parameters['excluded_hosts'] = hostsWithComponentInProperState.join(',');
+ }
+ App.ajax.send({
+ name: 'bulk_request.decommission',
+ sender: this,
+ data: {
+ context: turn_off ? Em.I18n.t('hosts.host.datanode.recommission') : Em.I18n.t('hosts.host.datanode.decommission'),
+ serviceName: service.get('serviceName'),
+ componentName: operationData.componentName,
+ parameters: parameters
+ },
+ success: 'bulkOperationForHostComponentsSuccessCallback'
+ });
+ }
+ else {
+ App.ModalPopup.show({
+ header: Em.I18n.t('rolling.nothingToDo.header'),
+ body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
+ secondary: false
+ });
+ }
+ },
+
+ /**
+ * Bulk restart for selected hostComponents
+ * @param {Object} operationData
+ * @param {Array} hosts
+ */
+ bulkOperationForHostComponentsRestart: function(operationData, hosts) {
+ var service = App.Service.find(operationData.serviceName);
+ var components = service.get('hostComponents').filter(function(hc) {
+ if (hc.get('componentName') != operationData.componentName) {
+ return false;
+ }
+ return hosts.contains(hc.get('host'));
+ });
+
+ if (components.length) {
+ batchUtils._doPostBatchRollingRestartRequest(components, components.length, 1, 1);
+ }
+ else {
+ App.ModalPopup.show({
+ header: Em.I18n.t('rolling.nothingToDo.header'),
+ body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
+ secondary: false
+ });
+ }
+ },
+
+ /**
+ * Show BO popup after bulk request
+ */
+ bulkOperationForHostComponentsSuccessCallback: function() {
+ App.router.get('applicationController').dataLoading().done(function (initValue) {
+ if (initValue) {
+ App.router.get('backgroundOperationsController').showPopup();
+ }
+ });
}
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/6974a6be/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 2f69fb0..1b11a06 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1794,6 +1794,10 @@ Em.I18n.translations = {
'rollingrestart.dialog.msg.staleConfigsOnly': 'Only restart {0}s with stale configs',
'rollingrestart.rest.context': 'Rolling Restart of {0}s - batch {1} of {2}',
+ 'rolling.command.context': 'Rolling set {0} to state "{1}" - batch {2} of {3}',
+ 'rolling.nothingToDo.header': 'Nothing to do',
+ 'rolling.nothingToDo.body': '{0} on selected hosts are already in selected state.',
+
'restart.service.all': 'Restart All',
'restart.service.rest.context': 'Restart {1}s ({0})',
http://git-wip-us.apache.org/repos/asf/ambari/blob/6974a6be/ambari-web/app/utils/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax.js b/ambari-web/app/utils/ajax.js
index 4421d31..867b78a 100644
--- a/ambari-web/app/utils/ajax.js
+++ b/ambari-web/app/utils/ajax.js
@@ -658,12 +658,7 @@ var urls = {
},
'settings.get.user_pref': {
'real': '/persist/{key}',
- 'mock': '/data/user_settings/user_pref.json',
- 'type': 'GET',
- 'format': function (data, opt) {
- return {
- };
- }
+ 'mock': '/data/user_settings/user_pref.json'
},
'settings.post.user_pref': {
'real': '/persist',
@@ -1340,6 +1335,46 @@ var urls = {
'mock': '/data/mirroring/{dataset}_instances.json'
},
+ 'bulk_request.host_components': {
+ 'real': '/clusters/{clusterName}/host_components',
+ 'mock': '',
+ 'format': function(data) {
+ return {
+ type: 'PUT',
+ data: JSON.stringify({
+ RequestInfo: {
+ context: data.requestInfo,
+ query: 'HostRoles/component_name=' + data.componentName + '&HostRoles/host_name.in(' + data.hostNames + ')'
+ },
+ Body: {
+ HostRoles: {
+ state: data.state
+ }
+ }
+ })
+ }
+ }
+ },
+
+ 'bulk_request.decommission': {
+ 'real' : '/clusters/{clusterName}/requests',
+ 'mock' : '',
+ 'format': function(data) {
+ return {
+ type: 'POST',
+ data: JSON.stringify({
+ 'RequestInfo': {
+ 'context': data.context,
+ 'command': 'DECOMMISSION',
+ 'service_name': data.serviceName,
+ 'component_name': data.componentName,
+ 'parameters': data.parameters
+ }
+ })
+ }
+ }
+ },
+
'mirroring.create_new_dataset': {
'real': '/falcon/entities/submitAndSchedule/feed',
'mock': '/data/mirroring/succeeded.json',
http://git-wip-us.apache.org/repos/asf/ambari/blob/6974a6be/ambari-web/app/utils/batch_scheduled_requests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/batch_scheduled_requests.js b/ambari-web/app/utils/batch_scheduled_requests.js
index ce3bf24..bf9164f 100644
--- a/ambari-web/app/utils/batch_scheduled_requests.js
+++ b/ambari-web/app/utils/batch_scheduled_requests.js
@@ -70,7 +70,7 @@ module.exports = {
restartAllServiceHostComponents: function(serviceName, staleConfigsOnly) {
var service = App.Service.find(serviceName);
if (service) {
- var hostComponents = service.get('hostComponents').filterProperty('isClient', false);
+ var hostComponents = service.get('hostComponents');
if (staleConfigsOnly) {
hostComponents = hostComponents.filterProperty('staleConfigs', true);
}
@@ -129,9 +129,10 @@ module.exports = {
* @param {Function} errorCallback
*/
_doPostBatchRollingRestartRequest: function(restartHostComponents, batchSize, intervalTimeSeconds, tolerateSize, successCallback, errorCallback) {
+ successCallback = successCallback ? successCallback : defaultSuccessCallback;
errorCallback = errorCallback ? errorCallback : defaultErrorCallback;
if (!restartHostComponents.length) {
- console.log('No batch rolling restart if restartHostComponents is empty!');
+ console.log('No batch rolling restart if no restartHostComponents provided!');
return;
}
App.ajax.send({
@@ -149,6 +150,7 @@ module.exports = {
error: 'errorCallback'
});
},
+
/**
* Create list of batches for rolling restart request
* @param {Array} restartHostComponents list host components should be restarted
http://git-wip-us.apache.org/repos/asf/ambari/blob/6974a6be/ambari-web/app/views/main/host.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host.js b/ambari-web/app/views/main/host.js
index 93ce21c..340e71a 100644
--- a/ambari-web/app/views/main/host.js
+++ b/ambari-web/app/views/main/host.js
@@ -122,7 +122,7 @@ App.MainHostView = App.TableView.extend({
hosts = this.get('filteredContent');
break;
case 'a':
- hosts = this.get('content');
+ hosts = this.get('content').toArray();
break;
}
// no hosts - no actions
http://git-wip-us.apache.org/repos/asf/ambari/blob/6974a6be/ambari-web/app/views/main/host/hosts_table_menu_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/hosts_table_menu_view.js b/ambari-web/app/views/main/host/hosts_table_menu_view.js
index a3cac2a..b6bd742 100644
--- a/ambari-web/app/views/main/host/hosts_table_menu_view.js
+++ b/ambari-web/app/views/main/host/hosts_table_menu_view.js
@@ -16,80 +16,64 @@
* limitations under the License.
*/
+var App = require('app');
+
App.HostTableMenuView = Em.View.extend({
templateName: require('templates/main/host/bulk_operation_menu'),
/**
- * Get third-level menu items for slave components (but not for DataNode!)
+ * Get third-level menu items for slave components
* @returns {Array}
*/
- getSlaveItemsTemplate: function() {
+ getSlaveItemsTemplate: function(componentNameForDecommission, componentNameForOtherActions) {
return Em.A([
Em.Object.create({
label: Em.I18n.t('common.start'),
operationData: Em.Object.create({
- action: 'start',
- message: Em.I18n.t('common.start')
+ action: App.HostComponentStatus.started,
+ message: Em.I18n.t('common.start'),
+ componentName: componentNameForOtherActions
})
}),
Em.Object.create({
label: Em.I18n.t('common.stop'),
operationData: Em.Object.create({
- action: 'stop',
- message: Em.I18n.t('common.stop')
+ action: App.HostComponentStatus.stopped,
+ message: Em.I18n.t('common.stop'),
+ componentName: componentNameForOtherActions
})
}),
Em.Object.create({
label: Em.I18n.t('common.restart'),
operationData: Em.Object.create({
- action: 'restart',
- message: Em.I18n.t('common.restart')
+ action: 'RESTART',
+ message: Em.I18n.t('common.restart'),
+ componentName: componentNameForOtherActions
})
}),
Em.Object.create({
- label: Em.I18n.t('maintenance.turnOn'),
+ label: Em.I18n.t('common.decommission'),
operationData: Em.Object.create({
- action: 'turn_on_maintenance',
- message: Em.I18n.t('maintenance.turnOnFor')
+ action: 'DECOMMISSION',
+ message: Em.I18n.t('common.decommission'),
+ componentName: componentNameForDecommission,
+ realComponentName: componentNameForOtherActions
})
}),
Em.Object.create({
- label: Em.I18n.t('maintenance.turnOff'),
+ label: Em.I18n.t('common.recommission'),
operationData: Em.Object.create({
- action: 'turn_off_maintenance',
- message: Em.I18n.t('maintenance.turnOffFor')
+ action: 'DECOMMISSION_OFF',
+ message: Em.I18n.t('common.recommission'),
+ componentName: componentNameForDecommission,
+ realComponentName: componentNameForOtherActions
})
})
]);
},
/**
- * Get third-level menu items for DataNode
- * @returns {Array}
- */
- getDataNodeItemsTemplate: function() {
- var dataNodesItems = this.getSlaveItemsTemplate();
- dataNodesItems.push(Em.Object.create({
- label: Em.I18n.t('common.decommission'),
- operationData: Em.Object.create({
- action: 'decommission',
- message: Em.I18n.t('common.decommission')
- })
- }));
- dataNodesItems.push(Em.Object.create({
- label: Em.I18n.t('common.recommission'),
- operationData: Em.Object.create({
- action: 'recommission',
- message: Em.I18n.t('common.recommission')
- })
- }));
- dataNodesItems.setEach('operationData.componentNameFormatted', Em.I18n.t('dashboard.services.hdfs.datanodes'));
- dataNodesItems.setEach('operationData.componentName', 'DATANODE');
- return dataNodesItems;
- },
-
- /**
* Get third-level menu items for Hosts
* @returns {Array}
*/
@@ -142,26 +126,29 @@ App.HostTableMenuView = Em.View.extend({
var submenu = [{label: Em.I18n.t('common.hosts'), submenu: this.getHostItemsTemplate()}];
if (!!App.HDFSService.find().content.length) {
- submenu.push({label: Em.I18n.t('dashboard.services.hdfs.datanodes'), submenu: this.getDataNodeItemsTemplate()});
+ var slaveItemsForHdfs = this.getSlaveItemsTemplate('NAMENODE', 'DATANODE');
+ slaveItemsForHdfs.setEach('operationData.serviceName', 'HDFS');
+ slaveItemsForHdfs.setEach('operationData.componentNameFormatted', Em.I18n.t('dashboard.services.hdfs.datanodes'));
+ submenu.push({label: Em.I18n.t('dashboard.services.hdfs.datanodes'), submenu: slaveItemsForHdfs});
}
if (!!App.YARNService.find().content.length) {
- var slaveItemsForYarn = this.getSlaveItemsTemplate();
- slaveItemsForYarn.setEach('operationData.componentName', 'NODEMANAGER');
+ var slaveItemsForYarn = this.getSlaveItemsTemplate('RESOURCEMANAGER', 'NODEMANAGER');
+ slaveItemsForYarn.setEach('operationData.serviceName', 'YARN');
slaveItemsForYarn.setEach('operationData.componentNameFormatted', Em.I18n.t('dashboard.services.yarn.nodeManagers'));
submenu.push({label: Em.I18n.t('dashboard.services.yarn.nodeManagers'), submenu: slaveItemsForYarn});
}
if (!!App.HBaseService.find().content.length) {
- var slaveItemsForHBase = this.getSlaveItemsTemplate();
- slaveItemsForHBase.setEach('operationData.componentName', 'HBASE_REGIONSERVER');
+ var slaveItemsForHBase = this.getSlaveItemsTemplate('HBASE_REGIONSERVER', 'HBASE_REGIONSERVER'); // @todo provide proper component for decommission
+ slaveItemsForHBase.setEach('operationData.serviceName', 'HBASE');
slaveItemsForHBase.setEach('operationData.componentNameFormatted', Em.I18n.t('dashboard.services.hbase.regionServers'));
submenu.push({label: Em.I18n.t('dashboard.services.hbase.regionServers'), submenu: slaveItemsForHBase});
}
if (!!App.MapReduceService.find().content.length) {
- var slaveItemsForMapReduce = this.getSlaveItemsTemplate();
- slaveItemsForMapReduce.setEach('operationData.componentName', 'TASKTRACKER');
+ var slaveItemsForMapReduce = this.getSlaveItemsTemplate('JOBTRACKER', 'TASKTRACKER');
+ slaveItemsForMapReduce.setEach('operationData.serviceName', 'MAPREDUCE');
slaveItemsForMapReduce.setEach('operationData.componentNameFormatted', Em.I18n.t('dashboard.services.mapreduce.taskTrackers'));
submenu.push({label: Em.I18n.t('dashboard.services.mapreduce.taskTrackers'), submenu: slaveItemsForMapReduce});
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/6974a6be/ambari-web/test/utils/batch_scheduled_requests_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/batch_scheduled_requests_test.js b/ambari-web/test/utils/batch_scheduled_requests_test.js
new file mode 100644
index 0000000..3c4508e
--- /dev/null
+++ b/ambari-web/test/utils/batch_scheduled_requests_test.js
@@ -0,0 +1,89 @@
+/**
+ * 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/helper');
+var batchUtils = require('utils/batch_scheduled_requests');
+
+describe('batch_scheduled_requests', function() {
+
+ describe('#getRollingRestartComponentName', function() {
+ var tests = [
+ {serviceName: 'HDFS', componentName: 'DATANODE'},
+ {serviceName: 'YARN', componentName: 'NODEMANAGER'},
+ {serviceName: 'MAPREDUCE', componentName: 'TASKTRACKER'},
+ {serviceName: 'HBASE', componentName: 'HBASE_REGIONSERVER'},
+ {serviceName: 'STORM', componentName: 'SUPERVISOR'},
+ {serviceName: 'SOME_INVALID_SERVICE', componentName: null}
+ ];
+
+ tests.forEach(function(test) {
+ it(test.serviceName + ' - ' + test.componentName, function() {
+ expect(batchUtils.getRollingRestartComponentName(test.serviceName)).to.equal(test.componentName);
+ });
+ });
+
+ });
+
+ describe('#getBatchesForRollingRestartRequest', function() {
+ var tests = [
+ {
+ hostComponents: Em.A([
+ Em.Object.create({componentName:'DATANODE', service:{serviceName:'HDFS'}, host:{hostName:'host1'}}),
+ Em.Object.create({componentName:'DATANODE', service:{serviceName:'HDFS'}, host:{hostName:'host2'}}),
+ Em.Object.create({componentName:'DATANODE', service:{serviceName:'HDFS'}, host:{hostName:'host3'}})
+ ]),
+ batchSize: 2,
+ m: 'DATANODES on three hosts, batchSize = 2',
+ e: {
+ batchCount: 2
+ }
+ },
+ {
+ hostComponents: Em.A([
+ Em.Object.create({componentName:'DATANODE', service:{serviceName:'HDFS'}, host:{hostName:'host1'}}),
+ Em.Object.create({componentName:'DATANODE', service:{serviceName:'HDFS'}, host:{hostName:'host2'}}),
+ Em.Object.create({componentName:'DATANODE', service:{serviceName:'HDFS'}, host:{hostName:'host3'}})
+ ]),
+ batchSize: 3,
+ m: 'DATANODES on 3 hosts, batchSize = 3',
+ e: {
+ batchCount: 1
+ }
+ },
+ {
+ hostComponents: Em.A([
+ Em.Object.create({componentName:'DATANODE', service:{serviceName:'HDFS'}, host:{hostName:'host1'}}),
+ Em.Object.create({componentName:'DATANODE', service:{serviceName:'HDFS'}, host:{hostName:'host2'}}),
+ Em.Object.create({componentName:'DATANODE', service:{serviceName:'HDFS'}, host:{hostName:'host3'}})
+ ]),
+ batchSize: 1,
+ m: 'DATANODES on 3 hosts, batchSize = 1',
+ e: {
+ batchCount: 3
+ }
+ }
+ ];
+
+ tests.forEach(function(test) {
+ it(test.m, function() {
+ expect(batchUtils.getBatchesForRollingRestartRequest(test.hostComponents, test.batchSize).length).to.equal(test.e.batchCount);
+ });
+ });
+ });
+
+});