bulk_operations_controller.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  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. var batchUtils = require('utils/batch_scheduled_requests');
  19. var hostsManagement = require('utils/hosts');
  20. var O = Em.Object;
  21. /**
  22. * @class BulkOperationsController
  23. */
  24. App.BulkOperationsController = Em.Controller.extend({
  25. name: 'bulkOperationsController',
  26. /**
  27. * Bulk operation wrapper
  28. * @param {Object} operationData - data about bulk operation (action, hosts or hostComponents etc)
  29. * @param {Array} hosts - list of affected hosts
  30. * @method bulkOperation
  31. */
  32. bulkOperation: function (operationData, hosts) {
  33. if (operationData.componentNameFormatted) {
  34. if (operationData.action === 'RESTART') {
  35. this.bulkOperationForHostComponentsRestart(operationData, hosts);
  36. }
  37. else {
  38. if (operationData.action.indexOf('DECOMMISSION') == -1) {
  39. this.bulkOperationForHostComponents(operationData, hosts);
  40. }
  41. else {
  42. this.bulkOperationForHostComponentsDecommission(operationData, hosts);
  43. }
  44. }
  45. }
  46. else {
  47. if (operationData.action === 'SET_RACK_INFO') {
  48. this.bulkOperationForHostsSetRackInfo(operationData, hosts);
  49. }
  50. else {
  51. if (operationData.action === 'RESTART') {
  52. this.bulkOperationForHostsRestart(operationData, hosts);
  53. }
  54. else if (operationData.action === 'REINSTALL'){
  55. this.bulkOperationForHostsReinstall(operationData, hosts);
  56. }
  57. else {
  58. if (operationData.action === 'PASSIVE_STATE') {
  59. this.bulkOperationForHostsPassiveState(operationData, hosts);
  60. }
  61. else {
  62. this.bulkOperationForHosts(operationData, hosts);
  63. }
  64. }
  65. }
  66. }
  67. },
  68. /**
  69. * Bulk operation (start/stop all) for selected hosts
  70. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  71. * @param {Array} hosts - list of affected hosts
  72. * @return {$.ajax}
  73. */
  74. bulkOperationForHosts: function (operationData, hosts) {
  75. var self = this;
  76. return batchUtils.getComponentsFromServer({
  77. hosts: hosts.mapProperty('hostName'),
  78. passiveState: 'OFF',
  79. displayParams: ['host_components/HostRoles/component_name']
  80. }, function (data) {
  81. return self._getComponentsFromServerForHostsCallback(operationData, data);
  82. });
  83. },
  84. /**
  85. * run Bulk operation (start/stop all) for selected hosts
  86. * after host and components are loaded
  87. * @param operationData
  88. * @param data
  89. */
  90. _getComponentsFromServerForHostsCallback: function (operationData, data) {
  91. var query = [];
  92. var hostNames = [];
  93. var hostsMap = {};
  94. var clients = App.components.get('clients');
  95. data.items.forEach(function (host) {
  96. host.host_components.forEach(function (hostComponent) {
  97. if (!clients.contains((hostComponent.HostRoles.component_name))) {
  98. if (hostsMap[host.Hosts.host_name]) {
  99. hostsMap[host.Hosts.host_name].push(hostComponent.HostRoles.component_name);
  100. } else {
  101. hostsMap[host.Hosts.host_name] = [hostComponent.HostRoles.component_name];
  102. }
  103. }
  104. });
  105. });
  106. var nn_hosts = [];
  107. for (var hostName in hostsMap) {
  108. if (hostsMap.hasOwnProperty(hostName)) {
  109. var subQuery = '(HostRoles/component_name.in(%@)&HostRoles/host_name=' + hostName + ')';
  110. var components = hostsMap[hostName];
  111. if (components.length) {
  112. if (components.contains('NAMENODE')) {
  113. nn_hosts.push(hostName);
  114. }
  115. query.push(subQuery.fmt(components.join(',')));
  116. }
  117. hostNames.push(hostName);
  118. }
  119. }
  120. hostNames = hostNames.join(",");
  121. if (query.length) {
  122. query = query.join('|');
  123. var self = this;
  124. // if NameNode included, check HDFS NameNode checkpoint before stop NN
  125. var isHDFSStarted = 'STARTED' === App.Service.find('HDFS').get('workStatus');
  126. var request = function () {
  127. return App.ajax.send({
  128. name: 'common.host_components.update',
  129. sender: self,
  130. data: {
  131. query: query,
  132. HostRoles: {
  133. state: operationData.action
  134. },
  135. context: operationData.message,
  136. hostName: hostNames,
  137. noOpsMessage: Em.I18n.t('hosts.host.maintainance.allComponents.context')
  138. },
  139. success: 'bulkOperationForHostComponentsSuccessCallback'
  140. });
  141. };
  142. if (operationData.action === 'INSTALLED' && isHDFSStarted) {
  143. if (nn_hosts.length == 1) {
  144. return App.router.get('mainHostDetailsController').checkNnLastCheckpointTime(request, nn_hosts[0]);
  145. }
  146. if (nn_hosts.length == 2) {
  147. // HA enabled
  148. return App.router.get('mainServiceItemController').checkNnLastCheckpointTime(request);
  149. }
  150. }
  151. return request();
  152. }
  153. else {
  154. return App.ModalPopup.show({
  155. header: Em.I18n.t('rolling.nothingToDo.header'),
  156. body: Em.I18n.t('rolling.nothingToDo.body').format(Em.I18n.t('hosts.host.maintainance.allComponents.context')),
  157. secondary: false
  158. });
  159. }
  160. },
  161. bulkOperationForHostsSetRackInfo: function (operationData, hosts) {
  162. return hostsManagement.setRackInfo(operationData, hosts);
  163. },
  164. /**
  165. * Bulk restart for selected hosts
  166. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  167. * @param {Ember.Enumerable} hosts - list of affected hosts
  168. */
  169. bulkOperationForHostsRestart: function (operationData, hosts) {
  170. return batchUtils.getComponentsFromServer({
  171. passiveState: 'OFF',
  172. hosts: hosts.mapProperty('hostName'),
  173. displayParams: ['host_components/HostRoles/component_name']
  174. }, this._getComponentsFromServerForRestartCallback);
  175. },
  176. /**
  177. *
  178. * @param {object} data
  179. * @private
  180. * @method _getComponentsFromServerCallback
  181. */
  182. _getComponentsFromServerForRestartCallback: function (data) {
  183. var hostComponents = [];
  184. data.items.forEach(function (host) {
  185. host.host_components.forEach(function (hostComponent) {
  186. hostComponents.push(O.create({
  187. componentName: hostComponent.HostRoles.component_name,
  188. hostName: host.Hosts.host_name
  189. }));
  190. })
  191. });
  192. // if NameNode included, check HDFS NameNode checkpoint before restart NN
  193. var isHDFSStarted = 'STARTED' === App.Service.find('HDFS').get('workStatus');
  194. var namenodes = hostComponents.filterProperty('componentName', 'NAMENODE');
  195. var nn_count = namenodes.get('length');
  196. if (nn_count == 1 && isHDFSStarted) {
  197. var hostName = namenodes.get('firstObject.hostName');
  198. App.router.get('mainHostDetailsController').checkNnLastCheckpointTime(function () {
  199. batchUtils.restartHostComponents(hostComponents, Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST");
  200. }, hostName);
  201. }
  202. else {
  203. if (nn_count == 2 && isHDFSStarted) {
  204. // HA enabled
  205. App.router.get('mainServiceItemController').checkNnLastCheckpointTime(function () {
  206. batchUtils.restartHostComponents(hostComponents, Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST");
  207. });
  208. }
  209. else {
  210. batchUtils.restartHostComponents(hostComponents, Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST");
  211. }
  212. }
  213. },
  214. /**
  215. * Bulk reinstall failed components for selected hosts
  216. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  217. * @param {Ember.Enumerable} hosts - list of affected hosts
  218. */
  219. bulkOperationForHostsReinstall: function (operationData, hosts) {
  220. return App.ajax.send({
  221. name: 'common.host_components.update',
  222. sender: this,
  223. data: {
  224. HostRoles: {
  225. state: 'INSTALLED'
  226. },
  227. query: 'HostRoles/host_name.in(' + hosts.mapProperty('hostName').join(',') + ')&HostRoles/state=INSTALL_FAILED',
  228. context: operationData.message,
  229. noOpsMessage: Em.I18n.t('hosts.host.maintainance.reinstallFailedComponents.context')
  230. },
  231. success: 'bulkOperationForHostComponentsSuccessCallback'
  232. });
  233. },
  234. /**
  235. * Bulk turn on/off passive state for selected hosts
  236. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  237. * @param {Array} hosts - list of affected hosts
  238. */
  239. bulkOperationForHostsPassiveState: function (operationData, hosts) {
  240. var self = this;
  241. return batchUtils.getComponentsFromServer({
  242. hosts: hosts.mapProperty('hostName'),
  243. displayParams: ['Hosts/maintenance_state']
  244. }, function (data) {
  245. return self._getComponentsFromServerForPassiveStateCallback(operationData, data)
  246. });
  247. },
  248. /**
  249. *
  250. * @param {object} operationData
  251. * @param {object} data
  252. * @returns {$.ajax|App.ModalPopup}
  253. * @private
  254. * @method _getComponentsFromServerForPassiveStateCallback
  255. */
  256. _getComponentsFromServerForPassiveStateCallback: function (operationData, data) {
  257. var hostNames = [];
  258. data.items.forEach(function (host) {
  259. if (host.Hosts.maintenance_state !== operationData.state) {
  260. hostNames.push(host.Hosts.host_name);
  261. }
  262. });
  263. if (hostNames.length) {
  264. return App.ajax.send({
  265. name: 'bulk_request.hosts.passive_state',
  266. sender: this,
  267. data: {
  268. hostNames: hostNames.join(','),
  269. passive_state: operationData.state,
  270. requestInfo: operationData.message
  271. },
  272. success: 'updateHostPassiveState'
  273. });
  274. }
  275. return App.ModalPopup.show({
  276. header: Em.I18n.t('rolling.nothingToDo.header'),
  277. body: Em.I18n.t('hosts.bulkOperation.passiveState.nothingToDo.body'),
  278. secondary: false
  279. });
  280. },
  281. updateHostPassiveState: function (data, opt, params) {
  282. return batchUtils.infoPassiveState(params.passive_state);
  283. },
  284. /**
  285. * Bulk operation for selected hostComponents
  286. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  287. * @param {Array} hosts - list of affected hosts
  288. */
  289. bulkOperationForHostComponents: function (operationData, hosts) {
  290. var self = this;
  291. return batchUtils.getComponentsFromServer({
  292. components: [operationData.componentName],
  293. hosts: hosts.mapProperty('hostName'),
  294. passiveState: 'OFF'
  295. }, function (data) {
  296. return self._getComponentsFromServerForHostComponentsCallback(operationData, data)
  297. });
  298. },
  299. /**
  300. *
  301. * @param {object} operationData
  302. * @param {object} data
  303. * @returns {$.ajax|App.ModalPopup}
  304. * @private
  305. */
  306. _getComponentsFromServerForHostComponentsCallback: function (operationData, data) {
  307. if (data.items) {
  308. var hostsWithComponentInProperState = data.items.mapProperty('Hosts.host_name');
  309. return App.ajax.send({
  310. name: 'common.host_components.update',
  311. sender: this,
  312. data: {
  313. HostRoles: {
  314. state: operationData.action
  315. },
  316. query: 'HostRoles/component_name=' + operationData.componentName + '&HostRoles/host_name.in(' + hostsWithComponentInProperState.join(',') + ')&HostRoles/maintenance_state=OFF',
  317. context: operationData.message + ' ' + operationData.componentNameFormatted,
  318. level: 'SERVICE',
  319. noOpsMessage: operationData.componentNameFormatted
  320. },
  321. success: 'bulkOperationForHostComponentsSuccessCallback'
  322. });
  323. }
  324. return App.ModalPopup.show({
  325. header: Em.I18n.t('rolling.nothingToDo.header'),
  326. body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
  327. secondary: false
  328. });
  329. },
  330. /**
  331. * Bulk decommission/recommission for selected hostComponents
  332. * @param {Object} operationData
  333. * @param {Array} hosts
  334. */
  335. bulkOperationForHostComponentsDecommission: function (operationData, hosts) {
  336. var self = this;
  337. return batchUtils.getComponentsFromServer({
  338. components: [operationData.realComponentName],
  339. hosts: hosts.mapProperty('hostName'),
  340. passiveState: 'OFF',
  341. displayParams: ['host_components/HostRoles/state']
  342. }, function (data) {
  343. return self._getComponentsFromServerForHostComponentsDecommissionCallBack(operationData, data)
  344. });
  345. },
  346. /**
  347. * run Bulk decommission/recommission for selected hostComponents
  348. * after host and components are loaded
  349. * @param operationData
  350. * @param data
  351. * @method _getComponentsFromServerForHostComponentsDecommissionCallBack
  352. */
  353. _getComponentsFromServerForHostComponentsDecommissionCallBack: function (operationData, data) {
  354. var service = App.Service.find(operationData.serviceName);
  355. var components = [];
  356. data.items.forEach(function (host) {
  357. host.host_components.forEach(function (hostComponent) {
  358. components.push(O.create({
  359. componentName: hostComponent.HostRoles.component_name,
  360. hostName: host.Hosts.host_name,
  361. workStatus: hostComponent.HostRoles.state
  362. }))
  363. });
  364. });
  365. if (components.length) {
  366. var hostsWithComponentInProperState = components.mapProperty('hostName');
  367. var turn_off = operationData.action.indexOf('OFF') !== -1;
  368. var svcName = operationData.serviceName;
  369. var masterName = operationData.componentName;
  370. var slaveName = operationData.realComponentName;
  371. var hostNames = hostsWithComponentInProperState.join(',');
  372. if (turn_off) {
  373. // For recommession
  374. if (svcName === "YARN" || svcName === "HBASE" || svcName === "HDFS") {
  375. App.router.get('mainHostDetailsController').doRecommissionAndStart(hostNames, svcName, masterName, slaveName);
  376. }
  377. } else {
  378. hostsWithComponentInProperState = components.filterProperty('workStatus', 'STARTED').mapProperty('hostName');
  379. //For decommession
  380. if (svcName == "HBASE") {
  381. // HBASE service, decommission RegionServer in batch requests
  382. this.warnBeforeDecommission(hostNames);
  383. } else {
  384. var parameters = {
  385. "slave_type": slaveName
  386. };
  387. var contextString = turn_off ? 'hosts.host.' + slaveName.toLowerCase() + '.recommission' :
  388. 'hosts.host.' + slaveName.toLowerCase() + '.decommission';
  389. if (turn_off) {
  390. parameters['included_hosts'] = hostsWithComponentInProperState.join(',')
  391. }
  392. else {
  393. parameters['excluded_hosts'] = hostsWithComponentInProperState.join(',');
  394. }
  395. App.ajax.send({
  396. name: 'bulk_request.decommission',
  397. sender: this,
  398. data: {
  399. context: Em.I18n.t(contextString),
  400. serviceName: service.get('serviceName'),
  401. componentName: operationData.componentName,
  402. parameters: parameters,
  403. noOpsMessage: operationData.componentNameFormatted
  404. },
  405. success: 'bulkOperationForHostComponentsSuccessCallback'
  406. });
  407. }
  408. }
  409. }
  410. else {
  411. App.ModalPopup.show({
  412. header: Em.I18n.t('rolling.nothingToDo.header'),
  413. body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
  414. secondary: false
  415. });
  416. }
  417. },
  418. /**
  419. * get info about regionserver passive_state
  420. * @method warnBeforeDecommission
  421. * @param {String} hostNames
  422. * @return {$.ajax}
  423. */
  424. warnBeforeDecommission: function (hostNames) {
  425. return App.ajax.send({
  426. 'name': 'host_components.hbase_regionserver.active',
  427. 'sender': this,
  428. 'data': {
  429. hostNames: hostNames
  430. },
  431. success: 'warnBeforeDecommissionSuccess'
  432. });
  433. },
  434. /**
  435. * check is hbase regionserver in mm. If so - run decommission
  436. * otherwise shows warning
  437. * @method warnBeforeDecommission
  438. * @param {Object} data
  439. * @param {Object} opt
  440. * @param {Object} params
  441. */
  442. warnBeforeDecommissionSuccess: function(data, opt, params) {
  443. if (Em.get(data, 'items.length')) {
  444. return App.router.get('mainHostDetailsController').showHbaseActiveWarning();
  445. }
  446. return App.router.get('mainHostDetailsController').checkRegionServerState(params.hostNames);
  447. },
  448. /**
  449. * Bulk restart for selected hostComponents
  450. * @param {Object} operationData
  451. * @param {Array} hosts
  452. */
  453. bulkOperationForHostComponentsRestart: function (operationData, hosts) {
  454. var self = this;
  455. return batchUtils.getComponentsFromServer({
  456. components: [operationData.componentName],
  457. hosts: hosts.mapProperty('hostName'),
  458. passiveState: 'OFF',
  459. displayParams: ['Hosts/maintenance_state', 'host_components/HostRoles/stale_configs', 'host_components/HostRoles/maintenance_state']
  460. }, function (data) {
  461. return self._getComponentsFromServerForHostComponentsRestartCallback(operationData, data);
  462. });
  463. },
  464. _getComponentsFromServerForHostComponentsRestartCallback: function (operationData, data) {
  465. var wrappedHostComponents = [];
  466. var service = App.Service.find(operationData.serviceName);
  467. data.items.forEach(function (host) {
  468. host.host_components.forEach(function (hostComponent) {
  469. wrappedHostComponents.push(O.create({
  470. componentName: hostComponent.HostRoles.component_name,
  471. serviceName: operationData.serviceName,
  472. hostName: host.Hosts.host_name,
  473. hostPassiveState: host.Hosts.maintenance_state,
  474. staleConfigs: hostComponent.HostRoles.stale_configs,
  475. passiveState: hostComponent.HostRoles.maintenance_state
  476. }));
  477. });
  478. });
  479. if (wrappedHostComponents.length) {
  480. return batchUtils.showRollingRestartPopup(wrappedHostComponents.objectAt(0).get('componentName'), service.get('displayName'), service.get('passiveState') === "ON", false, wrappedHostComponents);
  481. }
  482. return App.ModalPopup.show({
  483. header: Em.I18n.t('rolling.nothingToDo.header'),
  484. body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
  485. secondary: false
  486. });
  487. },
  488. updateHostComponentsPassiveState: function (data, opt, params) {
  489. return batchUtils.infoPassiveState(params.passive_state);
  490. },
  491. /**
  492. * Show BO popup after bulk request
  493. * @method bulkOperationForHostComponentsSuccessCallback
  494. */
  495. bulkOperationForHostComponentsSuccessCallback: function (data, opt, params, req) {
  496. if (!data && req.status == 200) {
  497. return App.ModalPopup.show({
  498. header: Em.I18n.t('rolling.nothingToDo.header'),
  499. body: Em.I18n.t('rolling.nothingToDo.body').format(params.noOpsMessage || Em.I18n.t('hosts.host.maintainance.allComponents.context')),
  500. secondary: false
  501. });
  502. }
  503. return App.router.get('userSettingsController').dataLoading('show_bg').done(function (initValue) {
  504. if (initValue) {
  505. App.router.get('backgroundOperationsController').showPopup();
  506. }
  507. });
  508. },
  509. /**
  510. * Returns all hostNames if amount is less than {minShown} or
  511. * first elements of array (number of elements - {minShown}) converted to string
  512. * @param {Array} hostNames - array of all listed hostNames
  513. * @param {String} divider - string to separate hostNames
  514. * @param {Number} minShown - min amount of hostName to be shown
  515. * @returns {String} hostNames
  516. * @method _showHostNames
  517. * @private
  518. */
  519. _showHostNames: function(hostNames, divider, minShown) {
  520. if (hostNames.length > minShown) {
  521. return hostNames.slice(0, minShown).join(divider) + divider + Em.I18n.t("installer.step8.other").format(hostNames.length - minShown);
  522. }
  523. return hostNames.join(divider);
  524. },
  525. /**
  526. * Confirmation Popup for bulk Operations
  527. */
  528. bulkOperationConfirm: function(operationData, selection) {
  529. var hostsNames = [],
  530. queryParams = [];
  531. // @todo remove using external controller
  532. switch(selection) {
  533. case 's':
  534. hostsNames = App.router.get('mainHostController.content').filterProperty('selected').mapProperty('hostName');
  535. if(hostsNames.length > 0){
  536. queryParams.push({
  537. key: 'Hosts/host_name',
  538. value: hostsNames,
  539. type: 'MULTIPLE'
  540. });
  541. }
  542. break;
  543. case 'f':
  544. queryParams = App.router.get('mainHostController').getQueryParameters(true).filter(function (obj) {
  545. return !(obj.key == 'page_size' || obj.key == 'from');
  546. });
  547. break;
  548. }
  549. if (operationData.action === 'SET_RACK_INFO') {
  550. this.getHostsForBulkOperations(queryParams, operationData, null);
  551. return;
  552. }
  553. var loadingPopup = App.ModalPopup.show({
  554. header: Em.I18n.t('jobs.loadingTasks'),
  555. primary: false,
  556. secondary: false,
  557. bodyClass: Em.View.extend({
  558. template: Em.Handlebars.compile('{{view App.SpinnerView}}')
  559. })
  560. });
  561. this.getHostsForBulkOperations(queryParams, operationData, loadingPopup);
  562. },
  563. getHostsForBulkOperations: function (queryParams, operationData, loadingPopup) {
  564. return App.ajax.send({
  565. name: 'hosts.bulk.operations',
  566. sender: this,
  567. data: {
  568. parameters: App.router.get('updateController').computeParameters(queryParams),
  569. operationData: operationData,
  570. loadingPopup: loadingPopup
  571. },
  572. success: 'getHostsForBulkOperationSuccessCallback'
  573. });
  574. },
  575. _convertHostsObjects: function (hosts) {
  576. return hosts.map(function (host) {
  577. return {
  578. index: host.index,
  579. id: host.id,
  580. clusterId: host.cluster_id,
  581. passiveState: host.passive_state,
  582. hostName: host.host_name,
  583. hostComponents: host.host_components
  584. }
  585. });
  586. },
  587. getHostsForBulkOperationSuccessCallback: function(json, opt, param) {
  588. var self = this;
  589. var operationData = param.operationData;
  590. var hosts = this._convertHostsObjects(App.hostsMapper.map(json, true));
  591. // no hosts - no actions
  592. if (!hosts.length) {
  593. return;
  594. }
  595. Em.tryInvoke(param.loadingPopup, 'hide');
  596. if ('SET_RACK_INFO' === operationData.action) {
  597. return self.bulkOperation(operationData, hosts);
  598. }
  599. var hostNames = hosts.mapProperty('hostName');
  600. var hostNamesSkipped = [];
  601. if ('DECOMMISSION' === operationData.action) {
  602. hostNamesSkipped = this._getSkippedForDecommissionHosts(json, hosts, operationData);
  603. }
  604. if ('PASSIVE_STATE' === operationData.action) {
  605. hostNamesSkipped = this._getSkippedForPassiveStateHosts(hosts);
  606. }
  607. var message = operationData.componentNameFormatted ?
  608. Em.I18n.t('hosts.bulkOperation.confirmation.hostComponents').format(operationData.message, operationData.componentNameFormatted, hostNames.length) :
  609. Em.I18n.t('hosts.bulkOperation.confirmation.hosts').format(operationData.message, hostNames.length);
  610. return App.ModalPopup.show({
  611. header: Em.I18n.t('hosts.bulkOperation.confirmation.header'),
  612. hostNames: hostNames.join("\n"),
  613. visibleHosts: self._showHostNames(hostNames, "\n", 3),
  614. hostNamesSkippedVisible: self._showHostNames(hostNamesSkipped, "\n", 3),
  615. expanded: false,
  616. hostNamesSkipped: function() {
  617. return hostNamesSkipped.length ? hostNamesSkipped.join("\n") : false;
  618. }.property(),
  619. didInsertElement: function() {
  620. this.set('expanded', hostNames.length <= 3);
  621. },
  622. onPrimary: function() {
  623. self.bulkOperation(operationData, hosts);
  624. this._super();
  625. },
  626. bodyClass: Em.View.extend({
  627. templateName: require('templates/main/host/bulk_operation_confirm_popup'),
  628. message: message,
  629. textareaVisible: false,
  630. warningInfo: function() {
  631. switch (operationData.action) {
  632. case "DECOMMISSION":
  633. return Em.I18n.t('hosts.bulkOperation.warningInfo.body');
  634. case "PASSIVE_STATE":
  635. return operationData.state === 'OFF' ? Em.I18n.t('hosts.passiveMode.popup.version.mismatch.multiple')
  636. .format(App.StackVersion.find().findProperty('isCurrent').get('repositoryVersion.repositoryVersion')) : "";
  637. default:
  638. return ""
  639. }
  640. }.property(),
  641. textTrigger: function() {
  642. this.toggleProperty('textareaVisible');
  643. },
  644. showAll: function() {
  645. this.set('parentView.visibleHosts', this.get('parentView.hostNames'));
  646. this.set('parentView.hostNamesSkippedVisible', this.get('parentView.hostNamesSkipped'));
  647. this.set('parentView.expanded', true);
  648. },
  649. putHostNamesToTextarea: function() {
  650. var hostNames = this.get('parentView.hostNames');
  651. if (this.get('textareaVisible')) {
  652. var wrapper = $(".task-detail-log-maintext");
  653. $('.task-detail-log-clipboard').html(hostNames).width(wrapper.width()).height(250);
  654. Em.run.next(function() {
  655. $('.task-detail-log-clipboard').select();
  656. });
  657. }
  658. }.observes('textareaVisible')
  659. })
  660. });
  661. },
  662. /**
  663. * @param {object} json
  664. * @param {object[]} hosts
  665. * @param {object} operationData
  666. * @returns {string[]}
  667. * @private
  668. * @method _getSkippedForDecommissionHosts
  669. */
  670. _getSkippedForDecommissionHosts: function (json, hosts, operationData) {
  671. var hostComponentStatusMap = {}; // "DATANODE_c6401.ambari.apache.org" => "STARTED"
  672. var hostComponentIdMap = {}; // "DATANODE_c6401.ambari.apache.org" => "DATANODE"
  673. if (json.items) {
  674. json.items.forEach(function(host) {
  675. if (host.host_components) {
  676. host.host_components.forEach(function(component) {
  677. hostComponentStatusMap[component.id] = component.HostRoles.state;
  678. hostComponentIdMap[component.id] = component.HostRoles.component_name;
  679. });
  680. }
  681. });
  682. }
  683. return hosts.filter(function(host) {
  684. return host.hostComponents.filter(function(component) {
  685. return hostComponentIdMap[component] == operationData.realComponentName && hostComponentStatusMap[component] == 'INSTALLED';
  686. }).length > 0;
  687. }).mapProperty('hostName');
  688. },
  689. /**
  690. * Exclude <code>outOfSyncHosts</code> hosts for PASSIVE request
  691. *
  692. * @param {object[]} hosts
  693. * @returns {string[]}
  694. * @private
  695. * @method _getSkippedForPassiveStateHosts
  696. */
  697. _getSkippedForPassiveStateHosts: function (hosts) {
  698. var hostNames = hosts.mapProperty('hostName');
  699. var hostNamesSkipped = [];
  700. var outOfSyncHosts = App.StackVersion.find().findProperty('isCurrent').get('outOfSyncHosts');
  701. for (var i = 0; i < outOfSyncHosts.length; i++) {
  702. if (hostNames.contains(outOfSyncHosts[i])) {
  703. hostNamesSkipped.push(outOfSyncHosts[i]);
  704. }
  705. }
  706. return hostNamesSkipped;
  707. }
  708. });