host.js 30 KB

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