host.js 29 KB

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