host.js 29 KB

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