host.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933
  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: 'criticalWarningAlertsCount',
  98. key: 'alerts_summary/CRITICAL{0}|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.alerts_summary_hosts) ? data.alerts_summary_hosts.CRITICAL + data.alerts_summary_hosts.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. goToHostAlerts: function (event) {
  452. var host = event && event.context;
  453. if (host) {
  454. App.router.transitionTo('main.hosts.hostDetails.alerts', host);
  455. }
  456. },
  457. /**
  458. * remove selected hosts
  459. */
  460. removeHosts: function () {
  461. var hosts = this.get('content');
  462. var selectedHosts = hosts.filterProperty('isChecked', true);
  463. selectedHosts.forEach(function (_hostInfo) {
  464. console.log('Removing: ' + _hostInfo.hostName);
  465. });
  466. this.get('fullContent').removeObjects(selectedHosts);
  467. },
  468. /**
  469. * remove hosts with id equal host_id
  470. * @param {String} host_id
  471. */
  472. checkRemoved: function (host_id) {
  473. var hosts = this.get('content');
  474. var selectedHosts = hosts.filterProperty('id', host_id);
  475. this.get('fullContent').removeObjects(selectedHosts);
  476. },
  477. /**
  478. * Bulk operation wrapper
  479. * @param {Object} operationData - data about bulk operation (action, hosts or hostComponents etc)
  480. * @param {Array} hosts - list of affected hosts
  481. */
  482. bulkOperation: function (operationData, hosts) {
  483. if (operationData.componentNameFormatted) {
  484. if (operationData.action === 'RESTART') {
  485. this.bulkOperationForHostComponentsRestart(operationData, hosts);
  486. }
  487. else {
  488. if (operationData.action.indexOf('DECOMMISSION') != -1) {
  489. this.bulkOperationForHostComponentsDecommission(operationData, hosts);
  490. }
  491. else {
  492. this.bulkOperationForHostComponents(operationData, hosts);
  493. }
  494. }
  495. }
  496. else {
  497. if (operationData.action === 'RESTART') {
  498. this.bulkOperationForHostsRestart(operationData, hosts);
  499. }
  500. else {
  501. if (operationData.action === 'PASSIVE_STATE') {
  502. this.bulkOperationForHostsPassiveState(operationData, hosts);
  503. }
  504. else {
  505. this.bulkOperationForHosts(operationData, hosts);
  506. }
  507. }
  508. }
  509. },
  510. /**
  511. * Bulk operation (start/stop all) for selected hosts
  512. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  513. * @param {Array} hosts - list of affected hosts
  514. */
  515. bulkOperationForHosts: function (operationData, hosts) {
  516. var self = this;
  517. batchUtils.getComponentsFromServer({
  518. hosts: hosts.mapProperty('hostName'),
  519. passiveState: 'OFF',
  520. displayParams: ['host_components/HostRoles/component_name']
  521. }, function (data) {
  522. self.bulkOperationForHostsCallback(operationData, data);
  523. });
  524. },
  525. /**
  526. * run Bulk operation (start/stop all) for selected hosts
  527. * after host and components are loaded
  528. * @param operationData
  529. * @param data
  530. */
  531. bulkOperationForHostsCallback: function (operationData, data) {
  532. var query = [];
  533. var hostNames = [];
  534. var hostsMap = {};
  535. data.items.forEach(function (host) {
  536. host.host_components.forEach(function (hostComponent) {
  537. if (!App.components.get('clients').contains((hostComponent.HostRoles.component_name))) {
  538. if (hostsMap[host.Hosts.host_name]) {
  539. hostsMap[host.Hosts.host_name].push(hostComponent.HostRoles.component_name);
  540. } else {
  541. hostsMap[host.Hosts.host_name] = [hostComponent.HostRoles.component_name];
  542. }
  543. }
  544. });
  545. });
  546. for (var hostName in hostsMap) {
  547. var subQuery = '(HostRoles/component_name.in(%@)&HostRoles/host_name=' + hostName + ')';
  548. var components = hostsMap[hostName];
  549. if (components.length) {
  550. query.push(subQuery.fmt(components.join(',')));
  551. }
  552. hostNames.push(hostName);
  553. }
  554. hostNames = hostNames.join(",");
  555. if (query.length) {
  556. query = query.join('|');
  557. App.ajax.send({
  558. name: 'common.host_components.update',
  559. sender: this,
  560. data: {
  561. query: query,
  562. HostRoles: {
  563. state: operationData.action
  564. },
  565. context: operationData.message,
  566. hostName: hostNames
  567. },
  568. success: 'bulkOperationForHostComponentsSuccessCallback'
  569. });
  570. }
  571. else {
  572. App.ModalPopup.show({
  573. header: Em.I18n.t('rolling.nothingToDo.header'),
  574. body: Em.I18n.t('rolling.nothingToDo.body').format(Em.I18n.t('hosts.host.maintainance.allComponents.context')),
  575. secondary: false
  576. });
  577. }
  578. },
  579. /**
  580. * Bulk restart for selected hosts
  581. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  582. * @param {Ember.Enumerable} hosts - list of affected hosts
  583. */
  584. bulkOperationForHostsRestart: function (operationData, hosts) {
  585. batchUtils.getComponentsFromServer({
  586. passiveState: 'OFF',
  587. hosts: hosts.mapProperty('hostName'),
  588. displayParams: ['host_components/HostRoles/component_name']
  589. }, function (data) {
  590. var hostComponents = [];
  591. data.items.forEach(function (host) {
  592. host.host_components.forEach(function (hostComponent) {
  593. hostComponents.push(Em.Object.create({
  594. componentName: hostComponent.HostRoles.component_name,
  595. hostName: host.Hosts.host_name
  596. }));
  597. })
  598. });
  599. batchUtils.restartHostComponents(hostComponents, Em.I18n.t('rollingrestart.context.allOnSelectedHosts'), "HOST");
  600. });
  601. },
  602. /**
  603. * Bulk turn on/off passive state for selected hosts
  604. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  605. * @param {Array} hosts - list of affected hosts
  606. */
  607. bulkOperationForHostsPassiveState: function (operationData, hosts) {
  608. var self = this;
  609. batchUtils.getComponentsFromServer({
  610. hosts: hosts.mapProperty('hostName'),
  611. displayParams: ['Hosts/maintenance_state']
  612. }, function (data) {
  613. var hostNames = [];
  614. data.items.forEach(function (host) {
  615. if (host.Hosts.maintenance_state !== operationData.state) {
  616. hostNames.push(host.Hosts.host_name);
  617. }
  618. });
  619. if (hostNames.length) {
  620. App.ajax.send({
  621. name: 'bulk_request.hosts.passive_state',
  622. sender: self,
  623. data: {
  624. hostNames: hostNames.join(','),
  625. passive_state: operationData.state,
  626. requestInfo: operationData.message
  627. },
  628. success: 'updateHostPassiveState'
  629. });
  630. } else {
  631. App.ModalPopup.show({
  632. header: Em.I18n.t('rolling.nothingToDo.header'),
  633. body: Em.I18n.t('hosts.bulkOperation.passiveState.nothingToDo.body'),
  634. secondary: false
  635. });
  636. }
  637. });
  638. },
  639. updateHostPassiveState: function (data, opt, params) {
  640. batchUtils.infoPassiveState(params.passive_state);
  641. },
  642. /**
  643. * Bulk operation for selected hostComponents
  644. * @param {Object} operationData - data about bulk operation (action, hostComponents etc)
  645. * @param {Array} hosts - list of affected hosts
  646. */
  647. bulkOperationForHostComponents: function (operationData, hosts) {
  648. var self = this;
  649. batchUtils.getComponentsFromServer({
  650. components: [operationData.componentName],
  651. hosts: hosts.mapProperty('hostName'),
  652. passiveState: 'OFF'
  653. }, function (data) {
  654. if (data.items.length) {
  655. var hostsWithComponentInProperState = data.items.mapProperty('Hosts.host_name');
  656. App.ajax.send({
  657. name: 'common.host_components.update',
  658. sender: self,
  659. data: {
  660. HostRoles: {
  661. state: operationData.action
  662. },
  663. query: 'HostRoles/component_name=' + operationData.componentName + '&HostRoles/host_name.in(' + hostsWithComponentInProperState.join(',') + ')&HostRoles/maintenance_state=OFF',
  664. context: operationData.message + ' ' + operationData.componentNameFormatted
  665. },
  666. success: 'bulkOperationForHostComponentsSuccessCallback'
  667. });
  668. }
  669. else {
  670. App.ModalPopup.show({
  671. header: Em.I18n.t('rolling.nothingToDo.header'),
  672. body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
  673. secondary: false
  674. });
  675. }
  676. });
  677. },
  678. /**
  679. * Bulk decommission/recommission for selected hostComponents
  680. * @param {Object} operationData
  681. * @param {Array} hosts
  682. */
  683. bulkOperationForHostComponentsDecommission: function (operationData, hosts) {
  684. var self = this;
  685. batchUtils.getComponentsFromServer({
  686. components: [operationData.realComponentName],
  687. hosts: hosts.mapProperty('hostName'),
  688. passiveState: 'OFF',
  689. displayParams: ['host_components/HostRoles/state']
  690. }, function (data) {
  691. self.bulkOperationForHostComponentsDecommissionCallBack(operationData, data)
  692. });
  693. },
  694. /**
  695. * run Bulk decommission/recommission for selected hostComponents
  696. * after host and components are loaded
  697. * @param operationData
  698. * @param data
  699. */
  700. bulkOperationForHostComponentsDecommissionCallBack: function (operationData, data) {
  701. var service = App.Service.find(operationData.serviceName);
  702. var components = [];
  703. data.items.forEach(function (host) {
  704. host.host_components.forEach(function (hostComponent) {
  705. components.push(Em.Object.create({
  706. componentName: hostComponent.HostRoles.component_name,
  707. hostName: host.Hosts.host_name,
  708. workStatus: hostComponent.HostRoles.state
  709. }))
  710. });
  711. });
  712. if (components.length) {
  713. var hostsWithComponentInProperState = components.mapProperty('hostName');
  714. var turn_off = operationData.action.indexOf('OFF') !== -1;
  715. var svcName = operationData.serviceName;
  716. var masterName = operationData.componentName;
  717. var slaveName = operationData.realComponentName;
  718. var hostNames = hostsWithComponentInProperState.join(',');
  719. if (turn_off) {
  720. // For recommession
  721. if (svcName === "YARN" || svcName === "HBASE" || svcName === "HDFS") {
  722. App.router.get('mainHostDetailsController').doRecommissionAndStart(hostNames, svcName, masterName, slaveName);
  723. }
  724. else if (svcName === "MAPREDUCE") {
  725. App.router.get('mainHostDetailsController').doRecommissionAndRestart(hostNames, svcName, masterName, slaveName);
  726. }
  727. } else {
  728. hostsWithComponentInProperState = components.filterProperty('workStatus', 'STARTED').mapProperty('hostName');
  729. //For decommession
  730. if (svcName == "HBASE") {
  731. // HBASE service, decommission RegionServer in batch requests
  732. this.warnBeforeDecommission(hostNames);
  733. } else {
  734. var parameters = {
  735. "slave_type": slaveName
  736. };
  737. var contextString = turn_off ? 'hosts.host.' + slaveName.toLowerCase() + '.recommission' :
  738. 'hosts.host.' + slaveName.toLowerCase() + '.decommission';
  739. if (turn_off) {
  740. parameters['included_hosts'] = hostsWithComponentInProperState.join(',')
  741. }
  742. else {
  743. parameters['excluded_hosts'] = hostsWithComponentInProperState.join(',');
  744. }
  745. App.ajax.send({
  746. name: 'bulk_request.decommission',
  747. sender: this,
  748. data: {
  749. context: Em.I18n.t(contextString),
  750. serviceName: service.get('serviceName'),
  751. componentName: operationData.componentName,
  752. parameters: parameters
  753. },
  754. success: 'bulkOperationForHostComponentsSuccessCallback'
  755. });
  756. }
  757. }
  758. }
  759. else {
  760. App.ModalPopup.show({
  761. header: Em.I18n.t('rolling.nothingToDo.header'),
  762. body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
  763. secondary: false
  764. });
  765. }
  766. },
  767. /**
  768. * get info about regionserver passive_state
  769. * @method warnBeforeDecommission
  770. * @param {String} hostNames
  771. * @return {$.ajax}
  772. */
  773. warnBeforeDecommission: function (hostNames) {
  774. return App.ajax.send({
  775. 'name': 'host_components.hbase_regionserver.active',
  776. 'sender': this,
  777. 'data': {
  778. hostNames: hostNames
  779. },
  780. success: 'warnBeforeDecommissionSuccess'
  781. });
  782. },
  783. /**
  784. * check is hbase regionserver in mm. If so - run decommission
  785. * otherwise shows warning
  786. * @method warnBeforeDecommission
  787. * @param {Object} data
  788. * @param {Object} opt
  789. * @param {Object} params
  790. */
  791. warnBeforeDecommissionSuccess: function(data, opt, params) {
  792. if (Em.get(data, 'items.length')) {
  793. App.router.get('mainHostDetailsController').showHbaseActiveWarning();
  794. } else {
  795. App.router.get('mainHostDetailsController').checkRegionServerState(params.hostNames);
  796. }
  797. },
  798. /**
  799. * Bulk restart for selected hostComponents
  800. * @param {Object} operationData
  801. * @param {Array} hosts
  802. */
  803. bulkOperationForHostComponentsRestart: function (operationData, hosts) {
  804. var service = App.Service.find(operationData.serviceName);
  805. batchUtils.getComponentsFromServer({
  806. components: [operationData.componentName],
  807. hosts: hosts.mapProperty('hostName'),
  808. passiveState: 'OFF',
  809. displayParams: ['Hosts/maintenance_state', 'host_components/HostRoles/stale_configs', 'host_components/HostRoles/maintenance_state']
  810. }, function (data) {
  811. var wrappedHostComponents = [];
  812. data.items.forEach(function (host) {
  813. host.host_components.forEach(function (hostComponent) {
  814. wrappedHostComponents.push(Em.Object.create({
  815. componentName: hostComponent.HostRoles.component_name,
  816. serviceName: operationData.serviceName,
  817. hostName: host.Hosts.host_name,
  818. hostPassiveState: host.Hosts.maintenance_state,
  819. staleConfigs: hostComponent.HostRoles.stale_configs,
  820. passiveState: hostComponent.HostRoles.maintenance_state
  821. }))
  822. });
  823. });
  824. if (wrappedHostComponents.length) {
  825. batchUtils.showRollingRestartPopup(wrappedHostComponents.objectAt(0).get('componentName'), service.get('displayName'), service.get('passiveState') === "ON", false, wrappedHostComponents);
  826. } else {
  827. App.ModalPopup.show({
  828. header: Em.I18n.t('rolling.nothingToDo.header'),
  829. body: Em.I18n.t('rolling.nothingToDo.body').format(operationData.componentNameFormatted),
  830. secondary: false
  831. });
  832. }
  833. });
  834. },
  835. updateHostComponentsPassiveState: function (data, opt, params) {
  836. batchUtils.infoPassiveState(params.passive_state);
  837. },
  838. /**
  839. * Show BO popup after bulk request
  840. */
  841. bulkOperationForHostComponentsSuccessCallback: function () {
  842. App.router.get('applicationController').dataLoading().done(function (initValue) {
  843. if (initValue) {
  844. App.router.get('backgroundOperationsController').showPopup();
  845. }
  846. });
  847. },
  848. /**
  849. * associations between host property and column index
  850. * @type {Array}
  851. */
  852. colPropAssoc: function () {
  853. var associations = [];
  854. associations[0] = 'healthClass';
  855. associations[1] = 'hostName';
  856. associations[2] = 'ip';
  857. associations[3] = 'cpu';
  858. associations[4] = 'memoryFormatted';
  859. associations[5] = 'loadAvg';
  860. associations[6] = 'hostComponents';
  861. associations[7] = 'criticalWarningAlertsCount';
  862. associations[8] = 'componentsWithStaleConfigsCount';
  863. associations[9] = 'componentsInPassiveStateCount';
  864. associations[10] = 'selected';
  865. associations[11] = 'stackVersions';
  866. return associations;
  867. }.property()
  868. });