bulk_operations_controller.js 26 KB

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