item.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  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 batchUtils = require('utils/batch_scheduled_requests');
  20. var componentsUtils = require('utils/components');
  21. App.MainServiceItemController = Em.Controller.extend({
  22. name: 'mainServiceItemController',
  23. /**
  24. * Callback functions for start and stop service have few differences
  25. *
  26. * Used with currentCallBack property
  27. */
  28. callBackConfig: {
  29. 'STARTED': {
  30. 'c': 'STARTING',
  31. 'f': 'starting',
  32. 'c2': 'live',
  33. 'hs': 'started',
  34. 's': 'start'
  35. },
  36. 'INSTALLED': {
  37. 'c': 'STOPPING',
  38. 'f': 'stopping',
  39. 'c2': 'dead',
  40. 'hs': 'stopped',
  41. 's': 'stop'
  42. }
  43. },
  44. initHosts: function() {
  45. if (App.get('components.masters').length !== 0) {
  46. var self = this;
  47. var hostNames = App.Host.find().mapProperty('hostName');
  48. this.set('allHosts', hostNames);
  49. ['HBASE_MASTER', 'HIVE_METASTORE', 'ZOOKEEPER_SERVER', 'FLUME_HANDLER', 'HIVE_SERVER'].forEach(function(componentName) {
  50. self.loadHostsWithoutComponent(componentName);
  51. });
  52. }
  53. }.observes('App.components.masters', 'content.hostComponents.length'),
  54. loadHostsWithoutComponent: function (componentName) {
  55. var self = this;
  56. var hostsWithComponent = App.HostComponent.find().filterProperty('componentName', componentName).mapProperty('hostName');
  57. var hostsWithoutComponent = this.get('allHosts').filter(function(hostName) {
  58. return !hostsWithComponent.contains(hostName);
  59. });
  60. self.set('add' + componentName, function() {
  61. App.get('router.mainAdminKerberosController').getKDCSessionState(function() {
  62. self.addComponent(componentName);
  63. });
  64. });
  65. Em.defineProperty(self, 'addDisabledTooltip-' + componentName, Em.computed('isAddDisabled-' + componentName, 'addDisabledMsg-' + componentName, function() {
  66. if (self.get('isAddDisabled-' + componentName)) {
  67. return self.get('addDisabledMsg-' + componentName);
  68. }
  69. }));
  70. Em.defineProperty(self, 'isAddDisabled-' + componentName, Em.computed('hostsWithoutComponent-' + componentName, function() {
  71. return self.get('hostsWithoutComponent-' + componentName).length === 0 ? 'disabled' : '';
  72. }));
  73. var disabledMsg = Em.I18n.t('services.summary.allHostsAlreadyRunComponent').format(componentName);
  74. self.set('hostsWithoutComponent-' + componentName, hostsWithoutComponent);
  75. self.set('addDisabledMsg-' + componentName, disabledMsg);
  76. },
  77. /**
  78. * flag to control router switch between service summary and configs
  79. * @type {boolean}
  80. */
  81. routeToConfigs: false,
  82. isClientsOnlyService: function() {
  83. return App.get('services.clientOnly').contains(this.get('content.serviceName'));
  84. }.property('content.serviceName'),
  85. isConfigurable: function () {
  86. return !App.get('services.noConfigTypes').contains(this.get('content.serviceName'));
  87. }.property('App.services.noConfigTypes','content.serviceName'),
  88. allHosts: [],
  89. clientComponents: function () {
  90. var clientNames = [];
  91. var clients = App.StackServiceComponent.find().filterProperty('serviceName', this.get('content.serviceName')).filterProperty('isClient');
  92. clients.forEach(function (item) {
  93. clientNames.push({
  94. action: 'downloadClientConfigs',
  95. context: {
  96. name: item.get('componentName'),
  97. label: item.get('displayName')
  98. }
  99. });
  100. });
  101. return clientNames;
  102. }.property('content.serviceName'),
  103. /**
  104. * Common method for ajax (start/stop service) responses
  105. * @param data
  106. * @param ajaxOptions
  107. * @param params
  108. */
  109. startStopPopupSuccessCallback: function (data, ajaxOptions, params) {
  110. if (data && data.Requests) {
  111. params.query.set('status', 'SUCCESS');
  112. var config = this.get('callBackConfig')[(JSON.parse(ajaxOptions.data)).Body.ServiceInfo.state];
  113. var self = this;
  114. console.log('Send request for ' + config.c + ' successfully');
  115. if (App.get('testMode')) {
  116. self.set('content.workStatus', App.Service.Health[config.f]);
  117. self.get('content.hostComponents').setEach('workStatus', App.HostComponentStatus[config.f]);
  118. setTimeout(function () {
  119. self.set('content.workStatus', App.Service.Health[config.c2]);
  120. self.get('content.hostComponents').setEach('workStatus', App.HostComponentStatus[config.hs]);
  121. }, App.get('testModeDelayForActions'));
  122. }
  123. // load data (if we need to show this background operations popup) from persist
  124. App.router.get('applicationController').dataLoading().done(function (initValue) {
  125. if (initValue) {
  126. App.router.get('backgroundOperationsController').showPopup();
  127. }
  128. });
  129. } else {
  130. params.query.set('status', 'FAIL');
  131. console.log('cannot get request id from ', data);
  132. }
  133. },
  134. startStopPopupErrorCallback: function(request, ajaxOptions, error, opt, params){
  135. params.query.set('status', 'FAIL');
  136. },
  137. /**
  138. * Confirmation popup for start/stop services
  139. * @param event
  140. * @param serviceHealth - 'STARTED' or 'INSTALLED'
  141. */
  142. startStopPopup: function(event, serviceHealth) {
  143. if ($(event.target).hasClass('disabled') || $(event.target.parentElement).hasClass('disabled')) {
  144. return;
  145. }
  146. var self = this;
  147. var serviceDisplayName = this.get('content.displayName');
  148. var isMaintenanceOFF = this.get('content.passiveState') === 'OFF';
  149. var bodyMessage = Em.Object.create({
  150. putInMaintenance: (serviceHealth == 'INSTALLED' && isMaintenanceOFF) || (serviceHealth == 'STARTED' && !isMaintenanceOFF),
  151. turnOnMmMsg: serviceHealth == 'INSTALLED' ? Em.I18n.t('passiveState.turnOnFor').format(serviceDisplayName) : Em.I18n.t('passiveState.turnOffFor').format(serviceDisplayName),
  152. confirmMsg: serviceHealth == 'INSTALLED'? Em.I18n.t('services.service.stop.confirmMsg').format(serviceDisplayName) : Em.I18n.t('services.service.start.confirmMsg').format(serviceDisplayName),
  153. confirmButton: serviceHealth == 'INSTALLED'? Em.I18n.t('services.service.stop.confirmButton') : Em.I18n.t('services.service.start.confirmButton'),
  154. additionalWarningMsg: isMaintenanceOFF && serviceHealth == 'INSTALLED'? Em.I18n.t('services.service.stop.warningMsg.turnOnMM').format(serviceDisplayName) : null
  155. });
  156. return App.showConfirmationFeedBackPopup(function(query, runMmOperation) {
  157. self.set('isPending', true);
  158. self.startStopWithMmode(serviceHealth, query, runMmOperation);
  159. }, bodyMessage);
  160. },
  161. startStopWithMmode: function(serviceHealth, query, runMmOperation) {
  162. var self = this;
  163. if (runMmOperation) {
  164. if (serviceHealth == "STARTED") {
  165. this.startStopPopupPrimary(serviceHealth, query).complete(function() {
  166. batchUtils.turnOnOffPassiveRequest("OFF", Em.I18n.t('passiveState.turnOff'), self.get('content.serviceName').toUpperCase());
  167. });
  168. } else {
  169. batchUtils.turnOnOffPassiveRequest("ON", Em.I18n.t('passiveState.turnOn'), this.get('content.serviceName').toUpperCase()).complete(function() {
  170. self.startStopPopupPrimary(serviceHealth, query);
  171. })
  172. }
  173. } else {
  174. this.startStopPopupPrimary(serviceHealth, query);
  175. }
  176. },
  177. startStopPopupPrimary: function (serviceHealth, query) {
  178. var requestInfo = (serviceHealth == "STARTED")
  179. ? App.BackgroundOperationsController.CommandContexts.START_SERVICE.format(this.get('content.serviceName'))
  180. : App.BackgroundOperationsController.CommandContexts.STOP_SERVICE.format(this.get('content.serviceName'));
  181. var data = {
  182. 'context': requestInfo,
  183. 'serviceName': this.get('content.serviceName').toUpperCase(),
  184. 'ServiceInfo': {
  185. 'state': serviceHealth
  186. },
  187. 'query': query
  188. };
  189. return App.ajax.send({
  190. 'name': 'common.service.update',
  191. 'sender': this,
  192. 'success': 'startStopPopupSuccessCallback',
  193. 'error': 'startStopPopupErrorCallback',
  194. 'data': data
  195. });
  196. },
  197. /**
  198. * On click callback for <code>start service</code> button
  199. * @param event
  200. */
  201. startService: function (event) {
  202. this.startStopPopup(event, App.HostComponentStatus.started);
  203. },
  204. /**
  205. * On click callback for <code>stop service</code> button
  206. * @param event
  207. */
  208. stopService: function (event) {
  209. this.startStopPopup(event, App.HostComponentStatus.stopped);
  210. },
  211. /**
  212. * On click callback for <code>run rebalancer</code> button
  213. * @param event
  214. */
  215. runRebalancer: function (event) {
  216. var self = this;
  217. return App.showConfirmationPopup(function() {
  218. self.set("content.runRebalancer", true);
  219. // load data (if we need to show this background operations popup) from persist
  220. App.router.get('applicationController').dataLoading().done(function (initValue) {
  221. if (initValue) {
  222. App.router.get('backgroundOperationsController').showPopup();
  223. }
  224. });
  225. });
  226. },
  227. /**
  228. * On click handler for Yarn Refresh Queues command from items menu
  229. * @param event
  230. */
  231. refreshYarnQueues : function (event) {
  232. var controller = this;
  233. var hosts = App.Service.find('YARN').get('hostComponents').filterProperty('componentName', 'RESOURCEMANAGER').mapProperty('hostName');
  234. return App.showConfirmationPopup(function() {
  235. App.ajax.send({
  236. name : 'service.item.refreshQueueYarnRequest',
  237. sender: controller,
  238. data : {
  239. command : "REFRESHQUEUES",
  240. context : Em.I18n.t('services.service.actions.run.yarnRefreshQueues.context') ,
  241. hosts : hosts.join(','),
  242. serviceName : "YARN",
  243. componentName : "RESOURCEMANAGER",
  244. forceRefreshConfigTags : "capacity-scheduler"
  245. },
  246. success : 'refreshYarnQueuesSuccessCallback',
  247. error : 'refreshYarnQueuesErrorCallback'
  248. });
  249. });
  250. },
  251. refreshYarnQueuesSuccessCallback : function(data, ajaxOptions, params) {
  252. if (data.Requests.id) {
  253. App.router.get('backgroundOperationsController').showPopup();
  254. } else {
  255. console.warn('Error during refreshYarnQueues');
  256. }
  257. },
  258. refreshYarnQueuesErrorCallback : function(data) {
  259. var error = Em.I18n.t('services.service.actions.run.yarnRefreshQueues.error');
  260. if(data && data.responseText){
  261. try {
  262. var json = $.parseJSON(data.responseText);
  263. error += json.message;
  264. } catch (err) {}
  265. }
  266. App.showAlertPopup(Em.I18n.t('services.service.actions.run.yarnRefreshQueues.error'), error);
  267. console.warn('Error during refreshYarnQueues:'+error);
  268. },
  269. startLdapKnox: function(event) {
  270. var context = Em.I18n.t('services.service.actions.run.startLdapKnox.context');
  271. this.startStopLdapKnox('STARTDEMOLDAP',context);
  272. },
  273. stopLdapKnox: function(event) {
  274. var context = Em.I18n.t('services.service.actions.run.stopLdapKnox.context');
  275. this.startStopLdapKnox('STOPDEMOLDAP',context);
  276. },
  277. startStopLdapKnox: function(command,context) {
  278. var controller = this;
  279. var host = App.HostComponent.find().findProperty('componentName', 'KNOX_GATEWAY').get('hostName');
  280. return App.showConfirmationPopup(function() {
  281. App.ajax.send({
  282. name: 'service.item.startStopLdapKnox',
  283. sender: controller,
  284. data: {
  285. command: command,
  286. context: context,
  287. host: host,
  288. serviceName: "KNOX",
  289. componentName: "KNOX_GATEWAY"
  290. },
  291. success: 'startStopLdapKnoxSuccessCallback',
  292. error: 'startStopLdapKnoxErrorCallback'
  293. });
  294. });
  295. },
  296. startStopLdapKnoxSuccessCallback : function(data, ajaxOptions, params) {
  297. if (data.Requests.id) {
  298. App.router.get('backgroundOperationsController').showPopup();
  299. } else {
  300. console.warn('Error during startStopLdapKnox');
  301. }
  302. },
  303. startStopLdapKnoxErrorCallback : function(data) {
  304. var error = Em.I18n.t('services.service.actions.run.startStopLdapKnox.error');
  305. if(data && data.responseText){
  306. try {
  307. var json = $.parseJSON(data.responseText);
  308. error += json.message;
  309. } catch (err) {}
  310. }
  311. App.showAlertPopup(Em.I18n.t('services.service.actions.run.yarnRefreshQueues.error'), error);
  312. console.warn('Error during refreshYarnQueues:'+ error);
  313. },
  314. /**
  315. * On click handler for rebalance Hdfs command from items menu
  316. */
  317. rebalanceHdfsNodes: function () {
  318. var controller = this;
  319. App.ModalPopup.show({
  320. classNames: ['fourty-percent-width-modal'],
  321. header: Em.I18n.t('services.service.actions.run.rebalanceHdfsNodes.context'),
  322. primary: Em.I18n.t('common.start'),
  323. secondary: Em.I18n.t('common.cancel'),
  324. inputValue: 10,
  325. errorMessage: Em.I18n.t('services.service.actions.run.rebalanceHdfsNodes.promptError'),
  326. isInvalid: function () {
  327. var intValue = Number(this.get('inputValue'));
  328. return this.get('inputValue')!=='DEBUG' && (isNaN(intValue) || intValue < 1 || intValue > 100);
  329. }.property('inputValue'),
  330. disablePrimary : function() {
  331. return this.get('isInvalid');
  332. }.property('isInvalid'),
  333. onPrimary: function () {
  334. if (this.get('isInvalid')) {
  335. return;
  336. }
  337. App.ajax.send({
  338. name : 'service.item.rebalanceHdfsNodes',
  339. sender: controller,
  340. data : {
  341. hosts : App.Service.find('HDFS').get('hostComponents').findProperty('componentName', 'NAMENODE').get('hostName'),
  342. threshold: this.get('inputValue')
  343. },
  344. success : 'rebalanceHdfsNodesSuccessCallback',
  345. error : 'rebalanceHdfsNodesErrorCallback'
  346. });
  347. this.hide();
  348. },
  349. bodyClass: Ember.View.extend({
  350. templateName: require('templates/common/modal_popups/prompt_popup'),
  351. text: Em.I18n.t('services.service.actions.run.rebalanceHdfsNodes.prompt'),
  352. didInsertElement: function () {
  353. App.tooltip(this.$(".prompt-input"), {
  354. placement: "bottom",
  355. title: Em.I18n.t('services.service.actions.run.rebalanceHdfsNodes.promptTooltip')
  356. });
  357. }
  358. })
  359. });
  360. },
  361. rebalanceHdfsNodesSuccessCallback: function (data) {
  362. if (data.Requests.id) {
  363. App.router.get('backgroundOperationsController').showPopup();
  364. } else {
  365. console.warn('Error during runRebalanceHdfsNodes');
  366. }
  367. },
  368. rebalanceHdfsNodesErrorCallback : function(data) {
  369. var error = Em.I18n.t('services.service.actions.run.rebalanceHdfsNodes.error');
  370. if(data && data.responseText){
  371. try {
  372. var json = $.parseJSON(data.responseText);
  373. error += json.message;
  374. } catch (err) {
  375. }
  376. }
  377. App.showAlertPopup(Em.I18n.t('services.service.actions.run.rebalanceHdfsNodes.error'), error);
  378. console.warn('Error during runRebalanceHdfsNodes:'+error);
  379. },
  380. /**
  381. * On click callback for <code>run compaction</code> button
  382. * @param event
  383. */
  384. runCompaction: function (event) {
  385. var self = this;
  386. return App.showConfirmationPopup(function() {
  387. self.set("content.runCompaction", true);
  388. // load data (if we need to show this background operations popup) from persist
  389. App.router.get('applicationController').dataLoading().done(function (initValue) {
  390. if (initValue) {
  391. App.router.get('backgroundOperationsController').showPopup();
  392. }
  393. });
  394. });
  395. },
  396. /**
  397. * On click callback for <code>run smoke test</code> button
  398. * @param event
  399. */
  400. runSmokeTest: function (event) {
  401. var self = this;
  402. if (this.get('content.serviceName') === 'MAPREDUCE2' && !App.Service.find('YARN').get('isStarted')) {
  403. return App.showAlertPopup(Em.I18n.t('common.error'), Em.I18n.t('services.mapreduce2.smokeTest.requirement'));
  404. }
  405. return App.showConfirmationFeedBackPopup(function(query) {
  406. self.runSmokeTestPrimary(query);
  407. });
  408. },
  409. restartAllHostComponents : function(serviceName) {
  410. var serviceDisplayName = this.get('content.displayName');
  411. var bodyMessage = Em.Object.create({
  412. putInMaintenance: this.get('content.passiveState') === 'OFF',
  413. turnOnMmMsg: Em.I18n.t('passiveState.turnOnFor').format(serviceDisplayName),
  414. confirmMsg: Em.I18n.t('services.service.restartAll.confirmMsg').format(serviceDisplayName),
  415. confirmButton: Em.I18n.t('services.service.restartAll.confirmButton'),
  416. additionalWarningMsg: this.get('content.passiveState') === 'OFF' ? Em.I18n.t('services.service.restartAll.warningMsg.turnOnMM').format(serviceDisplayName): null
  417. });
  418. return App.showConfirmationFeedBackPopup(function(query, runMmOperation) {
  419. batchUtils.restartAllServiceHostComponents(serviceName, false, query, runMmOperation);
  420. }, bodyMessage);
  421. },
  422. turnOnOffPassive: function(label) {
  423. var self = this;
  424. var state = this.get('content.passiveState') == 'OFF' ? 'ON' : 'OFF';
  425. var onOff = state === 'ON' ? "On" : "Off";
  426. return App.showConfirmationPopup(function() {
  427. batchUtils.turnOnOffPassiveRequest(state, label, self.get('content.serviceName').toUpperCase(), function(data, opt, params) {
  428. self.set('content.passiveState', params.passive_state);
  429. batchUtils.infoPassiveState(params.passive_state);})
  430. },
  431. Em.I18n.t('hosts.passiveMode.popup').format(onOff,self.get('content.displayName'))
  432. );
  433. },
  434. rollingRestart: function(hostComponentName) {
  435. batchUtils.launchHostComponentRollingRestart(hostComponentName, this.get('content.displayName'), this.get('content.passiveState') === "ON", false, this.get('content.passiveState') === "ON");
  436. },
  437. runSmokeTestPrimary: function(query) {
  438. var clusterLevelRequired = ['KERBEROS'];
  439. var requestData = {
  440. 'serviceName': this.get('content.serviceName'),
  441. 'displayName': this.get('content.displayName'),
  442. 'actionName': this.get('content.serviceName') === 'ZOOKEEPER' ? 'ZOOKEEPER_QUORUM_SERVICE_CHECK' : this.get('content.serviceName') + '_SERVICE_CHECK',
  443. 'query': query
  444. };
  445. if (clusterLevelRequired.contains(this.get('content.serviceName'))) {
  446. requestData.operationLevel = {
  447. "level": "CLUSTER",
  448. "cluster_name": App.get('clusterName')
  449. };
  450. }
  451. App.ajax.send({
  452. 'name': 'service.item.smoke',
  453. 'sender': this,
  454. 'success':'runSmokeTestSuccessCallBack',
  455. 'error':'runSmokeTestErrorCallBack',
  456. 'data': requestData
  457. });
  458. },
  459. runSmokeTestSuccessCallBack: function (data, ajaxOptions, params) {
  460. if (data.Requests.id) {
  461. // load data (if we need to show this background operations popup) from persist
  462. App.router.get('applicationController').dataLoading().done(function (initValue) {
  463. params.query.set('status', 'SUCCESS');
  464. if (initValue) {
  465. App.router.get('backgroundOperationsController').showPopup();
  466. }
  467. });
  468. }
  469. else {
  470. params.query.set('status', 'FAIL');
  471. console.warn('error during runSmokeTestSuccessCallBack');
  472. }
  473. },
  474. runSmokeTestErrorCallBack: function (request, ajaxOptions, error, opt, params) {
  475. params.query.set('status', 'FAIL');
  476. },
  477. /**
  478. * On click callback for <code>Reassign <master component></code> button
  479. * @param hostComponent
  480. */
  481. reassignMaster: function (hostComponent) {
  482. var component = App.HostComponent.find().findProperty('componentName', hostComponent);
  483. console.log('In Reassign Master', hostComponent);
  484. if (component) {
  485. var reassignMasterController = App.router.get('reassignMasterController');
  486. reassignMasterController.saveComponentToReassign(component);
  487. reassignMasterController.getSecurityStatus();
  488. reassignMasterController.setCurrentStep('1');
  489. App.router.transitionTo('reassign');
  490. }
  491. },
  492. /**
  493. * On click callback for <code>action</code> dropdown menu
  494. * Calls runSmokeTest, runRebalancer, runCompaction or reassignMaster depending on context
  495. * @param event
  496. */
  497. doAction: function (event) {
  498. if ($(event.target).hasClass('disabled') || $(event.target.parentElement).hasClass('disabled')) {
  499. return;
  500. }
  501. var methodName = event.context.action;
  502. var context = event.context.context;
  503. if (methodName) {
  504. this[methodName](context);
  505. }
  506. },
  507. /**
  508. * Restart clients host components to apply config changes
  509. */
  510. refreshConfigs: function () {
  511. var self = this;
  512. if (this.get('isClientsOnlyService') || this.get('content.serviceName') == "FLUME") {
  513. return App.showConfirmationFeedBackPopup(function (query) {
  514. batchUtils.getComponentsFromServer({
  515. services: [self.get('content.serviceName')]
  516. }, function (data) {
  517. var hostComponents = [];
  518. data.items.forEach(function (host) {
  519. host.host_components.forEach(function (hostComponent) {
  520. hostComponents.push(Em.Object.create({
  521. componentName: hostComponent.HostRoles.component_name,
  522. hostName: host.Hosts.host_name
  523. }))
  524. });
  525. });
  526. batchUtils.restartHostComponents(hostComponents, Em.I18n.t('rollingrestart.context.allForSelectedService').format(self.get('content.serviceName')), "SERVICE", query);
  527. })
  528. });
  529. }
  530. },
  531. /**
  532. * Send command to server to install client on selected host
  533. * @param componentName
  534. */
  535. addComponent: function (componentName) {
  536. var self = this;
  537. var component = App.StackServiceComponent.find().findProperty('componentName', componentName);
  538. var componentDisplayName = component.get('displayName');
  539. self.loadHostsWithoutComponent(componentName);
  540. return App.ModalPopup.show({
  541. primary: function() {
  542. if (this.get('anyHostsWithoutComponent')) {
  543. return Em.I18n.t('hosts.host.addComponent.popup.confirm')
  544. } else {
  545. return undefined;
  546. }
  547. }.property('anyHostsWithoutComponent'),
  548. header: Em.I18n.t('popup.confirmation.commonHeader'),
  549. addComponentMsg: function () {
  550. return Em.I18n.t('hosts.host.addComponent.msg').format(componentDisplayName);
  551. }.property(),
  552. selectHostMsg: function () {
  553. return Em.I18n.t('services.summary.selectHostForComponent').format(this.get('componentDisplayName'))
  554. }.property('componentDisplayName'),
  555. thereIsNoHostsMsg: function () {
  556. return Em.I18n.t('services.summary.allHostsAlreadyRunComponent').format(this.get('componentDisplayName'))
  557. }.property('componentDisplayName'),
  558. hostsWithoutComponent: function() {
  559. return self.get("hostsWithoutComponent-" + this.get('componentName'));
  560. }.property('componentName', 'self.hostsWithoutComponent-' + this.get('componentName')),
  561. anyHostsWithoutComponent: function() {
  562. return this.get('hostsWithoutComponent').length > 0
  563. }.property('hostsWithoutComponent'),
  564. selectedHost: null,
  565. componentName: function() {
  566. return componentName;
  567. }.property(),
  568. componentDisplayName: function() {
  569. return componentDisplayName;
  570. }.property(),
  571. bodyClass: Em.View.extend({
  572. templateName: require('templates/main/service/add_host_popup')
  573. }),
  574. onPrimary: function () {
  575. var selectedHost = this.get('selectedHost');
  576. // Install
  577. if(component.get('componentName') == "HIVE_METASTORE" && !!selectedHost){
  578. App.router.get('mainHostDetailsController').addComponent(
  579. {
  580. context: component,
  581. hiveMetastoreHost: selectedHost
  582. }
  583. );
  584. } else {
  585. componentsUtils.installHostComponent(selectedHost, component);
  586. }
  587. // Remove host from 'without' collection to immediate recalculate add menu item state
  588. var hostsWithoutComponent = this.get('hostsWithoutComponent');
  589. var index = hostsWithoutComponent.indexOf(this.get('selectedHost'));
  590. if (index > -1) {
  591. hostsWithoutComponent.splice(index, 1);
  592. }
  593. self.set('hostsWithoutComponent-' + this.get('componentName'), hostsWithoutComponent);
  594. this.hide();
  595. }
  596. });
  597. },
  598. /**
  599. * set property isPending (if this property is true - means that service has task in BGO)
  600. * and this makes start/stop button disabled
  601. */
  602. setStartStopState: function () {
  603. var serviceName = this.get('content.serviceName');
  604. var backgroundOperations = App.router.get('backgroundOperationsController.services');
  605. if (backgroundOperations && backgroundOperations.length > 0) {
  606. for (var i = 0; i < backgroundOperations.length; i++) {
  607. if (backgroundOperations[i].isRunning &&
  608. (backgroundOperations[i].dependentService === "ALL_SERVICES" ||
  609. backgroundOperations[i].dependentService === serviceName)) {
  610. this.set('isPending', true);
  611. return;
  612. }
  613. }
  614. this.set('isPending', false);
  615. } else {
  616. this.set('isPending', true);
  617. }
  618. }.observes('App.router.backgroundOperationsController.serviceTimestamp'),
  619. isStartDisabled: function () {
  620. if(this.get('isPending')) return true;
  621. return !(this.get('content.healthStatus') == 'red');
  622. }.property('content.healthStatus','isPending'),
  623. isStopDisabled: function () {
  624. if(this.get('isPending')) return true;
  625. if (App.get('isHaEnabled') && this.get('content.serviceName') == 'HDFS' && this.get('content.hostComponents').filterProperty('componentName', 'NAMENODE').someProperty('workStatus', App.HostComponentStatus.started)) {
  626. return false;
  627. }
  628. return (this.get('content.healthStatus') != 'green');
  629. }.property('content.healthStatus','isPending'),
  630. /**
  631. * Determine if service has than one service client components
  632. */
  633. isSeveralClients: function () {
  634. return App.StackServiceComponent.find().filterProperty('serviceName', this.get('content.serviceName')).filterProperty('isClient').length > 1;
  635. }.property('content.serviceName'),
  636. enableHighAvailability: function() {
  637. var ability_controller = App.router.get('mainAdminHighAvailabilityController');
  638. ability_controller.enableHighAvailability();
  639. },
  640. disableHighAvailability: function() {
  641. var ability_controller = App.router.get('mainAdminHighAvailabilityController');
  642. ability_controller.disableHighAvailability();
  643. },
  644. enableRMHighAvailability: function() {
  645. var ability_controller = App.router.get('mainAdminHighAvailabilityController');
  646. ability_controller.enableRMHighAvailability();
  647. },
  648. enableRAHighAvailability: function() {
  649. var ability_controller = App.router.get('mainAdminHighAvailabilityController');
  650. ability_controller.enableRAHighAvailability();
  651. },
  652. downloadClientConfigs: function (event) {
  653. var component = this.get('content.clientComponents').rejectProperty('totalCount', 0)[0];
  654. componentsUtils.downloadClientConfigs.call(this, {
  655. serviceName: this.get('content.serviceName'),
  656. componentName: (event && event.name) || component.get('componentName'),
  657. displayName: (event && event.label) || component.get('displayName')
  658. });
  659. },
  660. /**
  661. * On click handler for custom command from items menu
  662. * @param context
  663. */
  664. executeCustomCommand: function(context) {
  665. var controller = this;
  666. return App.showConfirmationPopup(function() {
  667. App.ajax.send({
  668. name : 'service.item.executeCustomCommand',
  669. sender: controller,
  670. data : {
  671. command : context.command,
  672. context : 'Execute ' + context.command,
  673. hosts : App.Service.find(context.service).get('hostComponents').findProperty('componentName', context.component).get('hostName'),
  674. serviceName : context.service,
  675. componentName : context.component,
  676. forceRefreshConfigTags : "capacity-scheduler"
  677. },
  678. success : 'executeCustomCommandSuccessCallback',
  679. error : 'executeCustomCommandErrorCallback'
  680. });
  681. });
  682. },
  683. executeCustomCommandSuccessCallback : function(data, ajaxOptions, params) {
  684. if (data.Requests.id) {
  685. App.router.get('backgroundOperationsController').showPopup();
  686. } else {
  687. console.warn('Error during execution of ' + params.command + ' custom command on' + params.componentName);
  688. }
  689. },
  690. executeCustomCommandErrorCallback : function(data) {
  691. var error = Em.I18n.t('services.service.actions.run.executeCustomCommand.error');
  692. if(data && data.responseText){
  693. try {
  694. var json = $.parseJSON(data.responseText);
  695. error += json.message;
  696. } catch (err) {}
  697. }
  698. App.showAlertPopup(Em.I18n.t('services.service.actions.run.executeCustomCommand.error'), error);
  699. console.warn('Error during executing custom command');
  700. },
  701. isPending:true
  702. });