batch_scheduled_requests.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with this
  4. * work for additional information regarding copyright ownership. The ASF
  5. * licenses this file to you under the Apache License, Version 2.0 (the
  6. * "License"); you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14. * License for the specific language governing permissions and limitations under
  15. * the License.
  16. */
  17. var App = require('app');
  18. /**
  19. * Default success callback for ajax-requests in this module
  20. * @type {Function}
  21. */
  22. var defaultSuccessCallback = function() {
  23. App.router.get('applicationController').dataLoading().done(function(initValue) {
  24. if (initValue) {
  25. App.router.get('backgroundOperationsController').showPopup();
  26. }
  27. });
  28. };
  29. /**
  30. * Default error callback for ajax-requests in this module
  31. * @param {Object} xhr
  32. * @param {String} textStatus
  33. * @param {String} error
  34. * @param {Object} opt
  35. * @type {Function}
  36. */
  37. var defaultErrorCallback = function(xhr, textStatus, error, opt) {
  38. App.ajax.defaultErrorHandler(xhr, opt.url, 'POST', xhr.status);
  39. };
  40. /**
  41. * Contains helpful utilities for handling batch and scheduled requests.
  42. */
  43. module.exports = {
  44. /**
  45. * Some services have components which have a need for rolling restarts. This
  46. * method returns the name of the host-component which supports rolling
  47. * restarts for a service.
  48. * @param {String} serviceName
  49. */
  50. getRollingRestartComponentName: function(serviceName) {
  51. var rollingRestartComponents = {
  52. HDFS: 'DATANODE',
  53. YARN: 'NODEMANAGER',
  54. MAPREDUCE: 'TASKTRACKER',
  55. HBASE: 'HBASE_REGIONSERVER',
  56. STORM: 'SUPERVISOR'
  57. };
  58. return rollingRestartComponents[serviceName] ? rollingRestartComponents[serviceName] : null;
  59. },
  60. /**
  61. * Facade-function for restarting host components of specific service
  62. * @param {String} serviceName for which service hostComponents should be restarted
  63. * @param {Boolean} staleConfigsOnly restart only hostComponents with <code>staleConfig</code> true
  64. */
  65. restartAllServiceHostComponents: function(serviceName, staleConfigsOnly) {
  66. var service = App.Service.find(serviceName);
  67. if (service) {
  68. var hostComponents = service.get('hostComponents');
  69. if (staleConfigsOnly) {
  70. hostComponents = hostComponents.filterProperty('staleConfigs', true);
  71. }
  72. this.restartHostComponents(hostComponents);
  73. }
  74. },
  75. /**
  76. * Restart list of host components
  77. * @param {Array} hostComponentsList list of host components should be restarted
  78. */
  79. restartHostComponents: function(hostComponentsList) {
  80. /**
  81. * Format: {
  82. * 'DATANODE': ['host1', 'host2'],
  83. * 'NAMENODE': ['host1', 'host3']
  84. * ...
  85. * }
  86. * @type {Object}
  87. */
  88. var componentToHostsMap = {};
  89. var componentServiceMap = App.QuickDataMapper.componentServiceMap();
  90. hostComponentsList.forEach(function(hc) {
  91. var componentName = hc.get('componentName');
  92. if (!componentToHostsMap[componentName]) {
  93. componentToHostsMap[componentName] = [];
  94. }
  95. componentToHostsMap[componentName].push(hc.get('host.hostName'));
  96. });
  97. for (var componentName in componentToHostsMap) {
  98. App.ajax.send({
  99. name: 'restart.service.hostComponents',
  100. sender: {
  101. successCallback: defaultSuccessCallback,
  102. errorCallback: defaultErrorCallback
  103. },
  104. data: {
  105. serviceName: componentServiceMap[componentName],
  106. componentName: componentName,
  107. hosts: componentToHostsMap[componentName].join(",")
  108. },
  109. success: 'successCallback',
  110. error: 'errorCallback'
  111. });
  112. }
  113. },
  114. /**
  115. * Makes a REST call to the server requesting the rolling restart of the
  116. * provided host components.
  117. * @param {Array} restartHostComponents list of host components should be restarted
  118. * @param {Number} batchSize size of each batch
  119. * @param {Number} intervalTimeSeconds delay between two batches
  120. * @param {Number} tolerateSize task failure tolerance
  121. * @param {Function} successCallback
  122. * @param {Function} errorCallback
  123. */
  124. _doPostBatchRollingRestartRequest: function(restartHostComponents, batchSize, intervalTimeSeconds, tolerateSize, successCallback, errorCallback) {
  125. successCallback = successCallback ? successCallback : defaultSuccessCallback;
  126. errorCallback = errorCallback ? errorCallback : defaultErrorCallback;
  127. if (!restartHostComponents.length) {
  128. console.log('No batch rolling restart if no restartHostComponents provided!');
  129. return;
  130. }
  131. App.ajax.send({
  132. name: 'rolling_restart.post',
  133. sender: {
  134. successCallback: successCallback,
  135. errorCallback: errorCallback
  136. },
  137. data: {
  138. intervalTimeSeconds: intervalTimeSeconds,
  139. tolerateSize: tolerateSize,
  140. batches: this.getBatchesForRollingRestartRequest(restartHostComponents, batchSize)
  141. },
  142. success: 'successCallback',
  143. error: 'errorCallback'
  144. });
  145. },
  146. /**
  147. * Create list of batches for rolling restart request
  148. * @param {Array} restartHostComponents list host components should be restarted
  149. * @param {Number} batchSize size of each batch
  150. * @returns {Array} list of batches
  151. */
  152. getBatchesForRollingRestartRequest: function(restartHostComponents, batchSize) {
  153. var hostIndex = 0,
  154. batches = [],
  155. batchCount = Math.ceil(restartHostComponents.length / batchSize),
  156. sampleHostComponent = restartHostComponents.objectAt(0),
  157. componentName = sampleHostComponent.get('componentName'),
  158. componentDisplayName = App.format.role(componentName),
  159. serviceName = sampleHostComponent.get('service.serviceName');
  160. for ( var count = 0; count < batchCount; count++) {
  161. var hostNames = [];
  162. for ( var hc = 0; hc < batchSize && hostIndex < restartHostComponents.length; hc++) {
  163. hostNames.push(restartHostComponents.objectAt(hostIndex++).get('host.hostName'));
  164. }
  165. if (hostNames.length > 0) {
  166. batches.push({
  167. "order_id" : count + 1,
  168. "type" : "POST",
  169. "uri" : App.apiPrefix + "/clusters/" + App.get('clusterName') + "/requests",
  170. "RequestBodyInfo" : {
  171. "RequestInfo" : {
  172. "context" : Em.I18n.t('rollingrestart.rest.context').format(componentDisplayName, (count + 1), batchCount),
  173. "command" : "RESTART",
  174. "service_name" : serviceName,
  175. "component_name" : componentName,
  176. "hosts" : hostNames.join(",")
  177. }
  178. }
  179. });
  180. }
  181. }
  182. return batches;
  183. },
  184. /**
  185. * Launches dialog to handle rolling restarts of host components.
  186. *
  187. * Rolling restart is supported only for components listed in <code>getRollingRestartComponentName</code>
  188. * @see getRollingRestartComponentName
  189. * @param {String} hostComponentName
  190. * Type of host-component to restart across cluster
  191. * (ex: DATANODE)
  192. * @param {Boolean} staleConfigsOnly
  193. * Pre-select host-components which have stale
  194. * configurations
  195. */
  196. launchHostComponentRollingRestart: function(hostComponentName, staleConfigsOnly) {
  197. var componentDisplayName = App.format.role(hostComponentName);
  198. if (!componentDisplayName) {
  199. componentDisplayName = hostComponentName;
  200. }
  201. var self = this;
  202. var title = Em.I18n.t('rollingrestart.dialog.title').format(componentDisplayName);
  203. var allowedHostComponents = ["DATANODE", "TASKTRACKER", "NODEMANAGER", "HBASE_REGIONSERVER", "SUPERVISOR"];
  204. if (allowedHostComponents.contains(hostComponentName)) {
  205. App.ModalPopup.show({
  206. header : title,
  207. hostComponentName : hostComponentName,
  208. staleConfigsOnly : staleConfigsOnly,
  209. innerView : null,
  210. bodyClass : App.RollingRestartView.extend({
  211. hostComponentName : hostComponentName,
  212. staleConfigsOnly : staleConfigsOnly,
  213. didInsertElement : function() {
  214. this.set('parentView.innerView', this);
  215. this.initialize();
  216. }
  217. }),
  218. classNames : [ 'rolling-restart-popup' ],
  219. primary : Em.I18n.t('rollingrestart.dialog.primary'),
  220. onPrimary : function() {
  221. var dialog = this;
  222. if (!dialog.get('enablePrimary')) {
  223. return;
  224. }
  225. var restartComponents = this.get('innerView.restartHostComponents');
  226. var batchSize = this.get('innerView.batchSize');
  227. var waitTime = this.get('innerView.interBatchWaitTimeSeconds');
  228. var tolerateSize = this.get('innerView.tolerateSize');
  229. self._doPostBatchRollingRestartRequest(restartComponents, batchSize, waitTime, tolerateSize, function() {
  230. dialog.hide();
  231. defaultSuccessCallback();
  232. });
  233. },
  234. updateButtons : function() {
  235. var errors = this.get('innerView.errors');
  236. this.set('enablePrimary', !(errors != null && errors.length > 0))
  237. }.observes('innerView.errors')
  238. });
  239. } else {
  240. var msg = Em.I18n.t('rollingrestart.notsupported.hostComponent').format(componentDisplayName);
  241. console.log(msg);
  242. App.ModalPopup.show({
  243. header : title,
  244. secondary : false,
  245. msg : msg,
  246. bodyClass : Ember.View.extend({
  247. template : Ember.Handlebars.compile('<div class="alert alert-warning">{{msg}}</div>')
  248. })
  249. });
  250. }
  251. }
  252. };