host.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var App = require('app');
  19. var validator = require('utils/validator');
  20. var batchUtils = require('utils/batch_scheduled_requests');
  21. App.MainHostController = Em.ArrayController.extend({
  22. name: 'mainHostController',
  23. dataSource: App.Host.find(),
  24. clearFilters: null,
  25. filteredCount: 0,
  26. resetStartIndex: false,
  27. /**
  28. * flag responsible for updating status counters of hosts
  29. */
  30. isCountersUpdating: false,
  31. hostsCountMap: {},
  32. startIndex: 1,
  33. /**
  34. * Components which will be shown in component filter
  35. * @returns {Array}
  36. */
  37. componentsForFilter: function () {
  38. var installedComponents = App.StackServiceComponent.find().toArray();
  39. installedComponents.setEach('checkedForHostFilter', false);
  40. return installedComponents;
  41. }.property('App.router.clusterController.isLoaded'),
  42. /**
  43. * Master components
  44. * @returns {Array}
  45. */
  46. masterComponents: function () {
  47. return this.get('componentsForFilter').filterProperty('isMaster', true);
  48. }.property('componentsForFilter'),
  49. /**
  50. * Slave components
  51. * @returns {Array}
  52. */
  53. slaveComponents: function () {
  54. return this.get('componentsForFilter').filterProperty('isSlave', true);
  55. }.property('componentsForFilter'),
  56. /**
  57. * Client components
  58. * @returns {Array}
  59. */
  60. clientComponents: function () {
  61. return this.get('componentsForFilter').filterProperty('isClient', true);
  62. }.property('componentsForFilter'),
  63. content: function () {
  64. return this.get('dataSource').filterProperty('isRequested');
  65. }.property('dataSource.@each.isRequested'),
  66. /**
  67. * filterProperties support follow types of filter:
  68. * MATCH - match of RegExp
  69. * EQUAL - equality "="
  70. * MULTIPLE - multiple values to compare
  71. * CUSTOM - substitute values with keys "{#}" in alias
  72. */
  73. filterProperties: [
  74. {
  75. key: 'publicHostName',
  76. alias: 'Hosts/host_name',
  77. type: 'MATCH'
  78. },
  79. {
  80. key: 'ip',
  81. alias: 'Hosts/ip',
  82. type: 'MATCH'
  83. },
  84. {
  85. key: 'cpu',
  86. alias: 'Hosts/cpu_count',
  87. type: 'EQUAL'
  88. },
  89. {
  90. key: 'memoryFormatted',
  91. alias: 'Hosts/total_mem',
  92. type: 'EQUAL'
  93. },
  94. {
  95. key: 'loadAvg',
  96. alias: 'metrics/load/load_one',
  97. type: 'EQUAL'
  98. },
  99. {
  100. key: 'hostComponents',
  101. alias: 'host_components/HostRoles/component_name',
  102. type: 'MULTIPLE'
  103. },
  104. {
  105. key: 'healthClass',
  106. alias: 'Hosts/host_status',
  107. type: 'EQUAL'
  108. },
  109. {
  110. key: 'criticalAlertsCount',
  111. alias: 'alerts/summary/CRITICAL{0}|alerts/summary/WARNING{1}',
  112. type: 'CUSTOM'
  113. },
  114. {
  115. key: 'componentsWithStaleConfigsCount',
  116. alias: 'host_components/HostRoles/stale_configs',
  117. type: 'EQUAL'
  118. },
  119. {
  120. key: 'componentsInPassiveStateCount',
  121. alias: 'host_components/HostRoles/maintenance_state',
  122. type: 'MULTIPLE'
  123. },
  124. {
  125. key: 'selected',
  126. alias: 'Hosts/host_name',
  127. type: 'MULTIPLE'
  128. }
  129. ],
  130. viewProperties: [
  131. Em.Object.create({
  132. key: 'displayLength',
  133. getValue: function (controller) {
  134. var name = controller.get('name');
  135. var dbValue = App.db.getDisplayLength(name);
  136. if (Em.isNone(this.get('viewValue'))) {
  137. this.set('viewValue', dbValue || '25'); //25 is default displayLength value for hosts page
  138. }
  139. return this.get('viewValue');
  140. },
  141. viewValue: null,
  142. alias: 'page_size'
  143. }),
  144. Em.Object.create({
  145. key: 'startIndex',
  146. getValue: function (controller) {
  147. var name = controller.get('name');
  148. var startIndex = App.db.getStartIndex(name);
  149. var value = this.get('viewValue');
  150. if (Em.isNone(value)) {
  151. if (Em.isNone(startIndex)) {
  152. value = 0;
  153. } else {
  154. value = startIndex;
  155. }
  156. }
  157. return (value > 0) ? value - 1 : value;
  158. },
  159. viewValue: null,
  160. alias: 'from'
  161. })
  162. ],
  163. sortProps: [
  164. {
  165. key: 'publicHostName',
  166. alias: 'Hosts/host_name'
  167. },
  168. {
  169. key: 'ip',
  170. alias: 'Hosts/ip'
  171. },
  172. {
  173. key: 'cpu',
  174. alias: 'Hosts/cpu_count'
  175. },
  176. {
  177. key: 'memoryFormatted',
  178. alias: 'Hosts/total_mem'
  179. },
  180. {
  181. key: 'diskUsage',
  182. //TODO disk_usage is relative property and need support from API, metrics/disk/disk_free used temporarily
  183. alias: 'metrics/disk/disk_free'
  184. },
  185. {
  186. key: 'loadAvg',
  187. alias: 'metrics/load/load_one'
  188. }
  189. ],
  190. /**
  191. * Validate and convert input string to valid url parameter.
  192. * Detect if user have passed string as regular expression or extend
  193. * string to regexp.
  194. *
  195. * @param {String} value
  196. * @return {String}
  197. **/
  198. getRegExp: function (value) {
  199. value = validator.isValidMatchesRegexp(value) ? value.replace(/(\.+\*?|(\.\*)+)$/, '') + '.*' : '^$';
  200. value = /^\.\*/.test(value) || value == '^$' ? value : '.*' + value;
  201. return value;
  202. },
  203. /**
  204. * get query parameters computed from filter properties, sort properties and custom properties of view
  205. * @return {Array}
  206. */
  207. getQueryParameters: function () {
  208. var queryParams = [];
  209. var savedFilterConditions = App.db.getFilterConditions(this.get('name')) || [];
  210. var savedSortConditions = App.db.getSortingStatuses(this.get('name')) || [];
  211. var colPropAssoc = this.get('colPropAssoc');
  212. var filterProperties = this.get('filterProperties');
  213. var sortProperties = this.get('sortProps');
  214. var oldProperties = App.router.get('updateController.queryParams.Hosts');
  215. this.set('resetStartIndex', false);
  216. this.get('viewProperties').forEach(function (property) {
  217. queryParams.push({
  218. key: property.get('alias'),
  219. value: property.getValue(this),
  220. type: 'EQUAL'
  221. })
  222. }, this);
  223. savedFilterConditions.forEach(function (filter) {
  224. var property = filterProperties.findProperty('key', colPropAssoc[filter.iColumn]);
  225. if (property && filter.value.length > 0 && !filter.skipFilter) {
  226. var result = {
  227. key: property.alias,
  228. value: filter.value,
  229. type: property.type,
  230. isFilter: true
  231. };
  232. if (filter.type === 'string' && sortProperties.someProperty('key', colPropAssoc[filter.iColumn])) {
  233. result.value = this.getRegExp(filter.value);
  234. }
  235. if (filter.type === 'number' || filter.type === 'ambari-bandwidth') {
  236. result.type = this.getComparisonType(filter.value);
  237. result.value = this.getProperValue(filter.value);
  238. }
  239. // enter an exact number for RAM filter, need to do a range number match for this
  240. if (filter.type === 'ambari-bandwidth' && result.type == 'EQUAL' && result.value) {
  241. var valuePair = this.convertMemoryToRange(filter.value);
  242. queryParams.push({
  243. key: result.key,
  244. value: valuePair[0],
  245. type: 'MORE'
  246. });
  247. queryParams.push({
  248. key: result.key,
  249. value: valuePair[1],
  250. type: 'LESS'
  251. });
  252. } else if (filter.type === 'ambari-bandwidth' && result.type != 'EQUAL' && result.value){
  253. // enter a comparison type, eg > 1, just do regular match
  254. result.value = this.convertMemory(filter.value);
  255. queryParams.push(result);
  256. } else if (result.value) {
  257. queryParams.push(result);
  258. }
  259. }
  260. }, this);
  261. if (queryParams.filterProperty('isFilter').length !== oldProperties.filterProperty('isFilter').length) {
  262. queryParams.findProperty('key', 'from').value = 0;
  263. this.set('resetStartIndex', true);
  264. } else {
  265. queryParams.filterProperty('isFilter').forEach(function (queryParam) {
  266. var oldProperty = oldProperties.filterProperty('isFilter').findProperty('key', queryParam.key);
  267. if (!oldProperty || JSON.stringify(oldProperty.value) !== JSON.stringify(queryParam.value)) {
  268. queryParams.findProperty('key', 'from').value = 0;
  269. this.set('resetStartIndex', true);
  270. }
  271. }, this);
  272. }
  273. savedSortConditions.forEach(function (sort) {
  274. var property = sortProperties.findProperty('key', sort.name);
  275. if (property && (sort.status === 'sorting_asc' || sort.status === 'sorting_desc')) {
  276. queryParams.push({
  277. key: property.alias,
  278. value: sort.status.replace('sorting_', ''),
  279. type: 'SORT'
  280. });
  281. }
  282. });
  283. return queryParams;
  284. },
  285. /**
  286. * update status counters of hosts
  287. */
  288. updateStatusCounters: function () {
  289. var self = this;
  290. if (this.get('isCountersUpdating')) {
  291. App.ajax.send({
  292. name: 'host.status.counters',
  293. sender: this,
  294. data: {},
  295. success: 'updateStatusCountersSuccessCallback',
  296. error: 'updateStatusCountersErrorCallback'
  297. });
  298. setTimeout(function () {
  299. self.updateStatusCounters();
  300. }, App.get('componentsUpdateInterval'));
  301. }
  302. },
  303. /**
  304. * success callback on <code>updateStatusCounters()</code>
  305. * map counters' value to categories
  306. * @param data
  307. */
  308. updateStatusCountersSuccessCallback: function (data) {
  309. var hostsCountMap = {
  310. 'HEALTHY': data.Clusters.health_report['Host/host_status/HEALTHY'],
  311. 'UNHEALTHY': data.Clusters.health_report['Host/host_status/UNHEALTHY'],
  312. 'ALERT': data.Clusters.health_report['Host/host_status/ALERT'],
  313. 'UNKNOWN': data.Clusters.health_report['Host/host_status/UNKNOWN'],
  314. 'health-status-WITH-ALERTS': (data.alerts) ? data.alerts.summary.CRITICAL + data.alerts.summary.WARNING : 0,
  315. 'health-status-RESTART': data.Clusters.health_report['Host/stale_config'],
  316. 'health-status-PASSIVE_STATE': data.Clusters.health_report['Host/maintenance_state'],
  317. 'TOTAL': data.Clusters.total_hosts
  318. };
  319. this.set('hostsCountMap', hostsCountMap);
  320. },
  321. /**
  322. * success callback on <code>updateStatusCounters()</code>
  323. */
  324. updateStatusCountersErrorCallback: function() {
  325. console.warn('ERROR: updateStatusCounters failed')
  326. },
  327. /**
  328. * Return value without predicate
  329. * @param {String} value
  330. * @return {String}
  331. */
  332. getProperValue: function (value) {
  333. return (value.charAt(0) === '>' || value.charAt(0) === '<' || value.charAt(0) === '=') ? value.substr(1, value.length) : value;
  334. },
  335. /**
  336. * Return value converted to kilobytes
  337. * @param {String} value
  338. * @return {*}
  339. */
  340. convertMemory: function (value) {
  341. var scale = value.charAt(value.length - 1);
  342. // first char may be predicate for comparison
  343. value = this.getProperValue(value);
  344. var parsedValue = parseFloat(value);
  345. if (isNaN(parsedValue)) {
  346. return value;
  347. }
  348. switch (scale) {
  349. case 'g':
  350. parsedValue *= 1048576;
  351. break;
  352. case 'm':
  353. parsedValue *= 1024;
  354. break;
  355. case 'k':
  356. break;
  357. default:
  358. //default value in GB
  359. parsedValue *= 1048576;
  360. }
  361. return Math.round(parsedValue);
  362. },
  363. /**
  364. * Return value converted to a range of kilobytes
  365. * @param {String} value
  366. * @return {Array}
  367. */
  368. convertMemoryToRange: function (value) {
  369. var scale = value.charAt(value.length - 1);
  370. // first char may be predicate for comparison
  371. value = this.getProperValue(value);
  372. var parsedValue = parseFloat(value);
  373. if (isNaN(parsedValue)) {
  374. return value;
  375. }
  376. var parsedValuePair = this.rangeConvertNumber(parsedValue, scale);
  377. var multiplyingFactor = 1;
  378. switch (scale) {
  379. case 'g':
  380. multiplyingFactor = 1048576;
  381. break;
  382. case 'm':
  383. multiplyingFactor = 1024;
  384. break;
  385. case 'k':
  386. break;
  387. default:
  388. //default value in GB
  389. multiplyingFactor = 1048576;
  390. }
  391. parsedValuePair[0] = Math.round( parsedValuePair[0] * multiplyingFactor);
  392. parsedValuePair[1] = Math.round( parsedValuePair[1] * multiplyingFactor);
  393. return parsedValuePair;
  394. },
  395. /**
  396. * Return value converted to a range of kilobytes
  397. * eg, return value 1.83 g will target 1.82500 ~ 1.83499 g
  398. * eg, return value 1.8 k will target 1.7500 ~ 1.8499 k
  399. * eg, return value 1.8 m will target 1.7500 ~ 1.8499 m
  400. * @param {number} value
  401. * @param {String} scale
  402. * @return {Array}
  403. */
  404. rangeConvertNumber: function (value, scale) {
  405. if (isNaN(value)) {
  406. return value;
  407. }
  408. var valuePair = [];
  409. switch (scale) {
  410. case 'g':
  411. valuePair = [value - 0.005000, value + 0.004999999];
  412. break;
  413. case 'm':
  414. case 'k':
  415. valuePair = [value - 0.05000, value + 0.04999];
  416. break;
  417. default:
  418. //default value in GB
  419. valuePair = [value - 0.005000, value + 0.004999999];
  420. }
  421. return valuePair;
  422. },
  423. /**
  424. * Return comparison type depending on populated predicate
  425. * @param value
  426. * @return {String}
  427. */
  428. getComparisonType: function (value) {
  429. var comparisonChar = value.charAt(0);
  430. var result = 'EQUAL';
  431. if (isNaN(comparisonChar)) {
  432. switch (comparisonChar) {
  433. case '>':
  434. result = 'MORE';
  435. break;
  436. case '<':
  437. result = 'LESS';
  438. break;
  439. }
  440. }
  441. return result;
  442. },
  443. /**
  444. * Filter hosts by componentName of <code>component</code>
  445. * @param {App.HostComponent} component
  446. */
  447. filterByComponent: function (component) {
  448. if (!component)
  449. return;
  450. var id = component.get('componentName');
  451. var column = 6;
  452. this.get('componentsForFilter').setEach('checkedForHostFilter', false);
  453. var filterForComponent = {
  454. iColumn: column,
  455. value: [id],
  456. type: 'multiple'
  457. };
  458. App.db.setFilterConditions(this.get('name'), [filterForComponent]);
  459. },
  460. showAlertsPopup: function (event) {
  461. var host = event.context;
  462. App.router.get('mainAlertsController').loadAlerts(host.get('hostName'), "HOST");
  463. App.ModalPopup.show({
  464. header: this.t('services.alerts.headingOfList'),
  465. bodyClass: Ember.View.extend({
  466. templateName: require('templates/main/host/alerts_popup'),
  467. controllerBinding: 'App.router.mainAlertsController',
  468. alerts: function () {
  469. return this.get('controller.alerts');
  470. }.property('controller.alerts'),
  471. closePopup: function () {
  472. this.get('parentView').hide();
  473. }
  474. }),
  475. primary: Em.I18n.t('common.close'),
  476. secondary: null,
  477. didInsertElement: function () {
  478. this.$().find('.modal-footer').addClass('align-center');
  479. this.$().children('.modal').css({'margin-top': '-350px'});
  480. }
  481. });
  482. event.stopPropagation();
  483. },
  484. /**
  485. * remove selected hosts
  486. */
  487. removeHosts: function () {
  488. var hosts = this.get('content');
  489. var selectedHosts = hosts.filterProperty('isChecked', true);
  490. selectedHosts.forEach(function (_hostInfo) {
  491. console.log('Removing: ' + _hostInfo.hostName);
  492. });
  493. this.get('fullContent').removeObjects(selectedHosts);
  494. },
  495. /**
  496. * remove hosts with id equal host_id
  497. * @param {String} host_id
  498. */
  499. checkRemoved: function (host_id) {
  500. var hosts = this.get('content');
  501. var selectedHosts = hosts.filterProperty('id', host_id);
  502. this.get('fullContent').removeObjects(selectedHosts);
  503. },
  504. /**
  505. * Bulk operation wrapper
  506. * @param {Object} operationData - data about bulk operation (action, hosts or hostComponents etc)
  507. * @param {Array} hosts - list of affected hosts
  508. */
  509. bulkOperation: function (operationData, hosts) {
  510. if (operationData.componentNameFormatted) {
  511. if (operationData.action === 'RESTART') {
  512. this.bulkOperationForHostComponentsRestart(operationData, hosts);
  513. }
  514. else {
  515. if (operationData.action.indexOf('DECOMMISSION') != -1) {
  516. this.bulkOperationForHostComponentsDecommission(operationData, hosts);
  517. }
  518. else {
  519. this.bulkOperationForHostComponents(operationData, hosts);
  520. }
  521. }
  522. }
  523. else {
  524. if (operationData.action === 'RESTART') {
  525. this.bulkOperationForHostsRestart(operationData, hosts);
  526. }
  527. else {
  528. if (operationData.action === 'PASSIVE_STATE') {
  529. this.bulkOperationForHostsPassiveState(operationData, hosts);
  530. }
  531. else {
  532. this.bulkOperationForHosts(operationData, hosts);
  533. }
  534. }
  535. }
  536. },
  537. /**
  538. * Bulk operation (start/stop all) for selected hosts
  539. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  540. * @param {Array} hosts - list of affected hosts
  541. */
  542. bulkOperationForHosts: function (operationData, hosts) {
  543. var self = this;
  544. batchUtils.getComponentsFromServer({
  545. hosts: hosts.mapProperty('hostName'),
  546. workStatus: operationData.actionToCheck,
  547. passiveState: 'OFF',
  548. displayParams: ['host_components/HostRoles/component_name']
  549. }, function (data) {
  550. self.bulkOperationForHostsCallback(operationData, data);
  551. });
  552. },
  553. /**
  554. * run Bulk operation (start/stop all) for selected hosts
  555. * after host and components are loaded
  556. * @param operationData
  557. * @param data
  558. */
  559. bulkOperationForHostsCallback: function (operationData, data) {
  560. var query = [];
  561. var hostNames = [];
  562. var hostsMap = {};
  563. data.items.forEach(function (host) {
  564. host.host_components.forEach(function (hostComponent) {
  565. if (!App.components.get('clients').contains((hostComponent.HostRoles.component_name))) {
  566. if (hostsMap[host.Hosts.host_name]) {
  567. hostsMap[host.Hosts.host_name].push(hostComponent.HostRoles.component_name);
  568. } else {
  569. hostsMap[host.Hosts.host_name] = [hostComponent.HostRoles.component_name];
  570. }
  571. }
  572. });
  573. });
  574. for (var hostName in hostsMap) {
  575. var subQuery = '(HostRoles/component_name.in(%@)&HostRoles/host_name=' + hostName + ')';
  576. var components = hostsMap[hostName];
  577. if (components.length) {
  578. query.push(subQuery.fmt(components.join(',')));
  579. }
  580. hostNames.push(hostName);
  581. }
  582. hostNames = hostNames.join(",");
  583. if (query.length) {
  584. query = query.join('|');
  585. App.ajax.send({
  586. name: 'bulk_request.hosts.all_components',
  587. sender: this,
  588. data: {
  589. query: query,
  590. state: operationData.action,
  591. requestInfo: operationData.message,
  592. hostName: hostNames
  593. },
  594. success: 'bulkOperationForHostComponentsSuccessCallback'
  595. });
  596. }
  597. else {
  598. App.ModalPopup.show({
  599. header: Em.I18n.t('rolling.nothingToDo.header'),
  600. body: Em.I18n.t('rolling.nothingToDo.body').format(Em.I18n.t('hosts.host.maintainance.allComponents.context')),
  601. secondary: false
  602. });
  603. }
  604. },
  605. /**
  606. * Bulk restart for selected hosts
  607. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  608. * @param {Ember.Enumerable} hosts - list of affected hosts
  609. */
  610. bulkOperationForHostsRestart: function (operationData, hosts) {
  611. batchUtils.getComponentsFromServer({
  612. passiveState: 'OFF',
  613. hosts: hosts.mapProperty('hostName'),
  614. displayParams: ['host_components/HostRoles/component_name']
  615. }, function (data) {
  616. var hostComponents = [];
  617. data.items.forEach(function (host) {
  618. host.host_components.forEach(function (hostComponent) {
  619. hostComponents.push(Em.Object.create({
  620. componentName: hostComponent.HostRoles.component_name,
  621. hostName: host.Hosts.host_name
  622. }));
  623. })
  624. });
  625. batchUtils.restartHostComponents(hostComponents, Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST");
  626. });
  627. },
  628. /**
  629. * Bulk turn on/off passive state for selected hosts
  630. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  631. * @param {Array} hosts - list of affected hosts
  632. */
  633. bulkOperationForHostsPassiveState: function (operationData, hosts) {
  634. var self = this;
  635. batchUtils.getComponentsFromServer({
  636. hosts: hosts.mapProperty('hostName'),
  637. displayParams: ['Hosts/maintenance_state']
  638. }, function (data) {
  639. var hostNames = [];
  640. data.items.forEach(function (host) {
  641. if (host.Hosts.maintenance_state !== operationData.state) {
  642. hostNames.push(host.Hosts.host_name);
  643. }
  644. });
  645. if (hostNames.length) {
  646. App.ajax.send({
  647. name: 'bulk_request.hosts.passive_state',
  648. sender: self,
  649. data: {
  650. hostNames: hostNames.join(','),
  651. passive_state: operationData.state,
  652. requestInfo: operationData.message
  653. },
  654. success: 'updateHostPassiveState'
  655. });
  656. } else {
  657. App.ModalPopup.show({
  658. header: Em.I18n.t('rolling.nothingToDo.header'),
  659. body: Em.I18n.t('hosts.bulkOperation.passiveState.nothingToDo.body'),
  660. secondary: false
  661. });
  662. }
  663. });
  664. },
  665. updateHostPassiveState: function (data, opt, params) {
  666. batchUtils.infoPassiveState(params.passive_state);
  667. },
  668. /**
  669. * Bulk operation for selected hostComponents
  670. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  671. * @param {Array} hosts - list of affected hosts
  672. */
  673. bulkOperationForHostComponents: function (operationData, hosts) {
  674. var self = this;
  675. batchUtils.getComponentsFromServer({
  676. components: [operationData.componentName],
  677. hosts: hosts.mapProperty('hostName'),
  678. passiveState: 'OFF'
  679. }, function (data) {
  680. if (data.items.length) {
  681. var hostsWithComponentInProperState = data.items.mapProperty('Hosts.host_name');
  682. App.ajax.send({
  683. name: 'bulk_request.host_components',
  684. sender: self,
  685. data: {
  686. hostNames: hostsWithComponentInProperState.join(','),
  687. state: operationData.action,
  688. requestInfo: operationData.message + ' ' + operationData.componentNameFormatted,
  689. componentName: operationData.componentName
  690. },
  691. success: 'bulkOperationForHostComponentsSuccessCallback'
  692. });
  693. }
  694. else {
  695. App.ModalPopup.show({
  696. header: Em.I18n.t('rolling.nothingToDo.header'),
  697. body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
  698. secondary: false
  699. });
  700. }
  701. });
  702. },
  703. /**
  704. * Bulk decommission/recommission for selected hostComponents
  705. * @param {Object} operationData
  706. * @param {Array} hosts
  707. */
  708. bulkOperationForHostComponentsDecommission: function (operationData, hosts) {
  709. var self = this;
  710. batchUtils.getComponentsFromServer({
  711. components: [operationData.realComponentName],
  712. hosts: hosts.mapProperty('hostName'),
  713. passiveState: 'OFF',
  714. displayParams: ['host_components/HostRoles/state']
  715. }, function (data) {
  716. self.bulkOperationForHostComponentsDecommissionCallBack(operationData, data)
  717. });
  718. },
  719. /**
  720. * run Bulk decommission/recommission for selected hostComponents
  721. * after host and components are loaded
  722. * @param operationData
  723. * @param data
  724. */
  725. bulkOperationForHostComponentsDecommissionCallBack: function (operationData, data) {
  726. var service = App.Service.find(operationData.serviceName);
  727. var components = [];
  728. data.items.forEach(function (host) {
  729. host.host_components.forEach(function (hostComponent) {
  730. components.push(Em.Object.create({
  731. componentName: hostComponent.HostRoles.component_name,
  732. hostName: host.Hosts.host_name,
  733. workStatus: hostComponent.HostRoles.state
  734. }))
  735. });
  736. });
  737. if (components.length) {
  738. var hostsWithComponentInProperState = components.mapProperty('hostName');
  739. var turn_off = operationData.action.indexOf('OFF') !== -1;
  740. var svcName = operationData.serviceName;
  741. var masterName = operationData.componentName;
  742. var slaveName = operationData.realComponentName;
  743. var hostNames = hostsWithComponentInProperState.join(',');
  744. if (turn_off) {
  745. // For recommession
  746. if (svcName === "YARN" || svcName === "HBASE" || svcName === "HDFS") {
  747. App.router.get('mainHostDetailsController').doRecommissionAndStart(hostNames, svcName, masterName, slaveName);
  748. }
  749. else if (svcName === "MAPREDUCE") {
  750. App.router.get('mainHostDetailsController').doRecommissionAndRestart(hostNames, svcName, masterName, slaveName);
  751. }
  752. } else {
  753. hostsWithComponentInProperState = components.filterProperty('workStatus', 'STARTED').mapProperty('hostName');
  754. //For decommession
  755. if (svcName == "HBASE") {
  756. // HBASE service, decommission RegionServer in batch requests
  757. App.router.get('mainHostDetailsController').doDecommissionRegionServer(hostNames, svcName, masterName, slaveName);
  758. } else {
  759. var parameters = {
  760. "slave_type": slaveName
  761. };
  762. var contextString = turn_off ? 'hosts.host.' + slaveName.toLowerCase() + '.recommission' :
  763. 'hosts.host.' + slaveName.toLowerCase() + '.decommission';
  764. if (turn_off) {
  765. parameters['included_hosts'] = hostsWithComponentInProperState.join(',')
  766. }
  767. else {
  768. parameters['excluded_hosts'] = hostsWithComponentInProperState.join(',');
  769. }
  770. App.ajax.send({
  771. name: 'bulk_request.decommission',
  772. sender: this,
  773. data: {
  774. context: Em.I18n.t(contextString),
  775. serviceName: service.get('serviceName'),
  776. componentName: operationData.componentName,
  777. parameters: parameters
  778. },
  779. success: 'bulkOperationForHostComponentsSuccessCallback'
  780. });
  781. }
  782. }
  783. }
  784. else {
  785. App.ModalPopup.show({
  786. header: Em.I18n.t('rolling.nothingToDo.header'),
  787. body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
  788. secondary: false
  789. });
  790. }
  791. },
  792. /**
  793. * Bulk restart for selected hostComponents
  794. * @param {Object} operationData
  795. * @param {Array} hosts
  796. */
  797. bulkOperationForHostComponentsRestart: function (operationData, hosts) {
  798. var service = App.Service.find(operationData.serviceName);
  799. batchUtils.getComponentsFromServer({
  800. components: [operationData.componentName],
  801. hosts: hosts.mapProperty('hostName'),
  802. passiveState: 'OFF',
  803. displayParams: ['Hosts/maintenance_state', 'host_components/HostRoles/stale_configs', 'host_components/HostRoles/maintenance_state']
  804. }, function (data) {
  805. var wrappedHostComponents = [];
  806. data.items.forEach(function (host) {
  807. host.host_components.forEach(function (hostComponent) {
  808. wrappedHostComponents.push(Em.Object.create({
  809. componentName: hostComponent.HostRoles.component_name,
  810. serviceName: App.QuickDataMapper.componentServiceMap()[hostComponent.HostRoles.component_name],
  811. hostName: host.Hosts.host_name,
  812. hostPassiveState: host.Hosts.maintenance_state,
  813. staleConfigs: hostComponent.HostRoles.stale_configs,
  814. passiveState: hostComponent.HostRoles.maintenance_state
  815. }))
  816. });
  817. });
  818. if (wrappedHostComponents.length) {
  819. batchUtils.showRollingRestartPopup(wrappedHostComponents.objectAt(0).get('componentName'), service.get('displayName'), service.get('passiveState') === "ON", false, wrappedHostComponents);
  820. } else {
  821. App.ModalPopup.show({
  822. header: Em.I18n.t('rolling.nothingToDo.header'),
  823. body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
  824. secondary: false
  825. });
  826. }
  827. });
  828. },
  829. updateHostComponentsPassiveState: function (data, opt, params) {
  830. batchUtils.infoPassiveState(params.passive_state);
  831. },
  832. /**
  833. * Show BO popup after bulk request
  834. */
  835. bulkOperationForHostComponentsSuccessCallback: function () {
  836. App.router.get('applicationController').dataLoading().done(function (initValue) {
  837. if (initValue) {
  838. App.router.get('backgroundOperationsController').showPopup();
  839. }
  840. });
  841. },
  842. /**
  843. * associations between host property and column index
  844. * @type {Array}
  845. */
  846. colPropAssoc: function () {
  847. var associations = [];
  848. associations[0] = 'healthClass';
  849. associations[1] = 'publicHostName';
  850. associations[2] = 'ip';
  851. associations[3] = 'cpu';
  852. associations[4] = 'memoryFormatted';
  853. associations[5] = 'loadAvg';
  854. associations[6] = 'hostComponents';
  855. associations[7] = 'criticalAlertsCount';
  856. associations[8] = 'componentsWithStaleConfigsCount';
  857. associations[9] = 'componentsInPassiveStateCount';
  858. associations[10] = 'selected';
  859. return associations;
  860. }.property()
  861. });