bulk_operations_controller.js 32 KB

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