host_progress_popup.js 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  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 date = require('utils/date');
  21. /**
  22. * App.HostPopup is for the popup that shows up upon clicking already-performed or currently-in-progress operations
  23. */
  24. App.HostPopup = Em.Object.create({
  25. name: 'hostPopup',
  26. servicesInfo: null,
  27. hosts: null,
  28. inputData: null,
  29. /**
  30. * @type {string}
  31. */
  32. serviceName: "",
  33. /**
  34. * @type {Number}
  35. */
  36. currentServiceId: null,
  37. previousServiceId: null,
  38. /**
  39. * @type {string}
  40. */
  41. popupHeaderName: "",
  42. /**
  43. * @type {App.Controller}
  44. */
  45. dataSourceController: null,
  46. /**
  47. * @type {bool}
  48. */
  49. isBackgroundOperations: false,
  50. /**
  51. * @type {string}
  52. */
  53. currentHostName: null,
  54. /**
  55. * @type {App.ModalPopup}
  56. */
  57. isPopup: null,
  58. /**
  59. * Entering point of this component
  60. * @param {String} serviceName
  61. * @param {Object} controller
  62. * @param {Boolean} isBackgroundOperations
  63. * @param {Integer} requestId
  64. */
  65. initPopup: function (serviceName, controller, isBackgroundOperations, requestId) {
  66. if (!isBackgroundOperations) {
  67. this.clearHostPopup();
  68. this.set("popupHeaderName", serviceName);
  69. }
  70. this.set('currentServiceId', requestId);
  71. this.set("serviceName", serviceName);
  72. this.set("dataSourceController", controller);
  73. this.set("isBackgroundOperations", isBackgroundOperations);
  74. this.set("inputData", this.get("dataSourceController.services"));
  75. if(isBackgroundOperations){
  76. this.onServiceUpdate();
  77. } else {
  78. this.onHostUpdate();
  79. }
  80. return this.createPopup();
  81. },
  82. /**
  83. * clear info popup data
  84. */
  85. clearHostPopup: function () {
  86. this.set('servicesInfo', null);
  87. this.set('hosts', null);
  88. this.set('inputData', null);
  89. this.set('serviceName', "");
  90. this.set('currentServiceId', null);
  91. this.set('previousServiceId', null);
  92. this.set('popupHeaderName', "");
  93. this.set('dataSourceController', null);
  94. this.set('currentHostName', null);
  95. this.get('isPopup') ? this.get('isPopup').remove() : null;
  96. },
  97. /**
  98. * Depending on tasks status
  99. * @param {Array} tasks
  100. * @return {Array} [Status, Icon type, Progressbar color, is IN_PROGRESS]
  101. */
  102. getStatus: function(tasks){
  103. var isCompleted = true;
  104. var status;
  105. var tasksLength = tasks.length;
  106. var isFailed = false;
  107. var isAborted = false;
  108. var isTimedout = false;
  109. var isInProgress = false;
  110. for (var i = 0; i < tasksLength; i++) {
  111. if (tasks[i].Tasks.status !== 'COMPLETED') {
  112. isCompleted = false;
  113. }
  114. if(tasks[i].Tasks.status === 'FAILED'){
  115. isFailed = true;
  116. }
  117. if (tasks[i].Tasks.status === 'ABORTED') {
  118. isAborted = true;
  119. }
  120. if (tasks[i].Tasks.status === 'TIMEDOUT') {
  121. isTimedout = true;
  122. }
  123. if (tasks[i].Tasks.status === 'IN_PROGRESS') {
  124. isInProgress = true;
  125. }
  126. }
  127. if (isFailed) {
  128. status = ['FAILED', 'icon-exclamation-sign', 'progress-danger', false];
  129. } else if (isAborted) {
  130. status = ['ABORTED', 'icon-minus', 'progress-warning', false];
  131. } else if (isTimedout) {
  132. status = ['TIMEDOUT', 'icon-time', 'progress-warning', false];
  133. } else if (isInProgress) {
  134. status = ['IN_PROGRESS', 'icon-cogs', 'progress-info', true];
  135. }
  136. if(status){
  137. return status;
  138. } else if(isCompleted){
  139. return ['SUCCESS', 'icon-ok', 'progress-success', false];
  140. } else {
  141. return ['PENDING', 'icon-cog', 'progress-info', true];
  142. }
  143. },
  144. /**
  145. * Progress of host or service depending on tasks status
  146. * @param {Array} tasks
  147. * @return {Number} percent of completion
  148. */
  149. getProgress: function (tasks) {
  150. if (!tasks || tasks.length === 0) return 0;
  151. var completedActions = 0;
  152. var queuedActions = 0;
  153. var inProgressActions = 0;
  154. tasks.forEach(function (task) {
  155. if (['COMPLETED', 'FAILED', 'ABORTED', 'TIMEDOUT'].contains(task.Tasks.status)) {
  156. completedActions++;
  157. } else if (task.Tasks.status === 'QUEUED') {
  158. queuedActions++;
  159. } else if (task.Tasks.status === 'IN_PROGRESS') {
  160. inProgressActions++;
  161. }
  162. });
  163. return Math.ceil(((queuedActions * 0.09) + (inProgressActions * 0.35) + completedActions ) / tasks.length * 100);
  164. },
  165. /**
  166. * Count number of operations for select box options
  167. * @param {Object[]} obj
  168. * @param {Object[]} categories
  169. */
  170. setSelectCount: function (obj, categories) {
  171. if (!obj) return;
  172. var countAll = obj.length;
  173. var countPending = 0;
  174. var countInProgress = 0;
  175. var countFailed = 0;
  176. var countCompleted = 0;
  177. var countAborted = 0;
  178. var countTimedout = 0;
  179. obj.forEach(function(item){
  180. switch (item.status){
  181. case 'pending':
  182. countPending++;
  183. break;
  184. case 'queued':
  185. countPending++;
  186. break;
  187. case 'in_progress':
  188. countInProgress++;
  189. break;
  190. case 'failed':
  191. countFailed++;
  192. break;
  193. case 'success':
  194. countCompleted++;
  195. break;
  196. case 'completed':
  197. countCompleted++;
  198. break;
  199. case 'aborted':
  200. countAborted++;
  201. break;
  202. case 'timedout':
  203. countTimedout++;
  204. break;
  205. }
  206. });
  207. categories.findProperty("value", 'all').set("count", countAll);
  208. categories.findProperty("value", 'pending').set("count", countPending);
  209. categories.findProperty("value", 'in_progress').set("count", countInProgress);
  210. categories.findProperty("value", 'failed').set("count", countFailed);
  211. categories.findProperty("value", 'completed').set("count", countCompleted);
  212. categories.findProperty("value", 'aborted').set("count", countAborted);
  213. categories.findProperty("value", 'timedout').set("count", countTimedout);
  214. },
  215. /**
  216. * For Background operation popup calculate number of running Operations, and set popup header
  217. * @param {bool} isServiceListHidden
  218. */
  219. setBackgroundOperationHeader: function (isServiceListHidden) {
  220. if (this.get('isBackgroundOperations') && !isServiceListHidden) {
  221. var numRunning = App.router.get('backgroundOperationsController.allOperationsCount');
  222. this.set("popupHeaderName", numRunning + Em.I18n.t('hostPopup.header.postFix'));
  223. }
  224. },
  225. /**
  226. * Create services obj data structure for popup
  227. * Set data for services
  228. * @param {bool} isServiceListHidden
  229. */
  230. onServiceUpdate: function (isServiceListHidden) {
  231. if (this.get('isBackgroundOperations') && this.get("inputData")) {
  232. var self = this;
  233. var allNewServices = [];
  234. var statuses = {
  235. 'FAILED': ['FAILED', 'icon-exclamation-sign', 'progress-danger', false],
  236. 'ABORTED': ['ABORTED', 'icon-minus', 'progress-warning', false],
  237. 'TIMEDOUT': ['TIMEDOUT', 'icon-time', 'progress-warning', false],
  238. 'IN_PROGRESS': ['IN_PROGRESS', 'icon-cogs', 'progress-info', true],
  239. 'COMPLETED': ['SUCCESS', 'icon-ok', 'progress-success', false]
  240. };
  241. var pendingStatus = ['PENDING', 'icon-cog', 'progress-info', true];
  242. this.set("servicesInfo", null);
  243. this.get("inputData").forEach(function (service) {
  244. var status = statuses[service.status] || pendingStatus;
  245. var newService = Ember.Object.create({
  246. id: service.id,
  247. displayName: service.displayName,
  248. progress: service.progress,
  249. status: App.format.taskStatus(status[0]),
  250. isRunning: service.isRunning,
  251. name: service.name,
  252. isVisible: true,
  253. startTime: date.startTime(service.startTime),
  254. duration: date.durationSummary(service.startTime, service.endTime),
  255. icon: status[1],
  256. barColor: status[2],
  257. isInProgress: status[3],
  258. barWidth: "width:" + service.progress + "%;",
  259. sourceRequestScheduleId: service.get('sourceRequestScheduleId'),
  260. contextCommand: service.get('contextCommand')
  261. });
  262. allNewServices.push(newService);
  263. });
  264. self.set('servicesInfo', allNewServices);
  265. this.setBackgroundOperationHeader(isServiceListHidden);
  266. }
  267. },
  268. /**
  269. * create task Ember object
  270. * @param {Object} _task
  271. * @return {Em.Object}
  272. */
  273. createTask: function (_task) {
  274. return Em.Object.create({
  275. id: _task.Tasks.id,
  276. hostName: _task.Tasks.host_name,
  277. command: ( _task.Tasks.command.toLowerCase() != 'service_check') ? _task.Tasks.command.toLowerCase() : '',
  278. commandDetail: App.format.commandDetail(_task.Tasks.command_detail, _task.Tasks.request_inputs),
  279. status: App.format.taskStatus(_task.Tasks.status),
  280. role: App.format.role(_task.Tasks.role),
  281. stderr: _task.Tasks.stderr,
  282. stdout: _task.Tasks.stdout,
  283. isVisible: true,
  284. startTime: date.startTime(_task.Tasks.start_time),
  285. duration: date.durationSummary(_task.Tasks.start_time, _task.Tasks.end_time),
  286. icon: function () {
  287. var statusIconMap = {
  288. 'pending': 'icon-cog',
  289. 'queued': 'icon-cog',
  290. 'in_progress': 'icon-cogs',
  291. 'completed': 'icon-ok',
  292. 'failed': 'icon-exclamation-sign',
  293. 'aborted': 'icon-minus',
  294. 'timedout': 'icon-time'
  295. };
  296. return statusIconMap[this.get('status')] || 'icon-cog';
  297. }.property('status')
  298. });
  299. },
  300. /**
  301. * Create hosts and tasks data structure for popup
  302. * Set data for hosts and tasks
  303. */
  304. onHostUpdate: function () {
  305. var self = this;
  306. var inputData = this.get("inputData");
  307. if (inputData) {
  308. var hostsArr = [];
  309. var hostsData;
  310. var hostsMap = {};
  311. if(this.get('isBackgroundOperations') && this.get("currentServiceId")){
  312. //hosts popup for Background Operations
  313. hostsData = inputData.findProperty("id", this.get("currentServiceId"));
  314. } else if (this.get("serviceName")) {
  315. //hosts popup for Wizards
  316. hostsData = inputData.findProperty("name", this.get("serviceName"));
  317. }
  318. if (hostsData) {
  319. if (hostsData.hostsMap) {
  320. //hosts data come from Background Operations as object map
  321. hostsMap = hostsData.hostsMap;
  322. } else if (hostsData.hosts) {
  323. //hosts data come from Wizard as array
  324. hostsData.hosts.forEach(function (_host) {
  325. hostsMap[_host.name] = _host;
  326. });
  327. }
  328. }
  329. var existedHosts = self.get('hosts');
  330. if (existedHosts && (existedHosts.length > 0) && this.get('currentServiceId') === this.get('previousServiceId')) {
  331. existedHosts.forEach(function (host) {
  332. var newHostInfo = hostsMap[host.get('name')];
  333. //update only hosts with changed tasks or currently opened tasks of host
  334. if (newHostInfo && (!this.get('isBackgroundOperations') || newHostInfo.isModified || this.get('currentHostName') === host.get('name'))) {
  335. var hostStatus = self.getStatus(newHostInfo.logTasks);
  336. var hostProgress = self.getProgress(newHostInfo.logTasks);
  337. host.set('status', App.format.taskStatus(hostStatus[0]));
  338. host.set('icon', hostStatus[1]);
  339. host.set('barColor', hostStatus[2]);
  340. host.set('isInProgress', hostStatus[3]);
  341. host.set('progress', hostProgress);
  342. host.set('barWidth', "width:" + hostProgress + "%;");
  343. host.set('logTasks', newHostInfo.logTasks);
  344. var existTasks = host.get('tasks');
  345. if (existTasks) {
  346. newHostInfo.logTasks.forEach(function (_task) {
  347. var existTask = existTasks.findProperty('id', _task.Tasks.id);
  348. if (existTask) {
  349. existTask.set('status', App.format.taskStatus(_task.Tasks.status));
  350. existTask.set('stdout', _task.Tasks.stdout);
  351. existTask.set('stderr', _task.Tasks.stderr);
  352. // Verified that this is needed.
  353. existTask.set('outputLog', _task.Tasks.output_log);
  354. existTask.set('errorLog', _task.Tasks.error_log);
  355. existTask.set('startTime', date.startTime(_task.Tasks.start_time));
  356. existTask.set('duration', date.durationSummary(_task.Tasks.start_time, _task.Tasks.end_time));
  357. // Puts some command information to render it
  358. var isRebalanceHDFSTask = (_task.Tasks.command === 'CUSTOM_COMMAND' && _task.Tasks.custom_command_name === 'REBALANCEHDFS');
  359. existTask.set('isRebalanceHDFSTask', isRebalanceHDFSTask);
  360. if(isRebalanceHDFSTask){
  361. var structuredOut = _task.Tasks.structured_out;
  362. if (!structuredOut || structuredOut === 'null') {
  363. structuredOut = {};
  364. }
  365. existTask.set('dataMoved', structuredOut['dataMoved'] || '0');
  366. existTask.set('dataLeft', structuredOut['dataLeft'] || '0');
  367. existTask.set('dataBeingMoved', structuredOut['dataBeingMoved'] || '0');
  368. existTask.set('completionProgressStyle', 'width:' + (structuredOut['completePercent'] || 0) * 100 + '%;');
  369. existTask.set('command', _task.Tasks.command);
  370. existTask.set('custom_command_name', _task.Tasks.custom_command_name);
  371. }
  372. } else {
  373. existTasks.pushObject(this.createTask(_task));
  374. }
  375. }, this);
  376. }
  377. }
  378. }, this);
  379. } else {
  380. for (var hostName in hostsMap) {
  381. var _host = hostsMap[hostName];
  382. var tasks = _host.logTasks;
  383. var hostInfo = Ember.Object.create({
  384. name: hostName,
  385. publicName: _host.publicName,
  386. displayName: function () {
  387. return this.get('name').length < 43 ? this.get('name') : (this.get('name').substr(0, 40) + '...');
  388. }.property('name'),
  389. progress: 0,
  390. status: App.format.taskStatus("PENDING"),
  391. serviceName: _host.serviceName,
  392. isVisible: true,
  393. icon: "icon-cog",
  394. barColor: "progress-info",
  395. barWidth: "width:0%;"
  396. });
  397. if (tasks.length) {
  398. tasks = tasks.sortProperty('Tasks.id');
  399. var hostStatus = self.getStatus(tasks);
  400. var hostProgress = self.getProgress(tasks);
  401. hostInfo.set('status', App.format.taskStatus(hostStatus[0]));
  402. hostInfo.set('icon', hostStatus[1]);
  403. hostInfo.set('barColor', hostStatus[2]);
  404. hostInfo.set('isInProgress', hostStatus[3]);
  405. hostInfo.set('progress', hostProgress);
  406. hostInfo.set('barWidth', "width:" + hostProgress + "%;");
  407. }
  408. hostInfo.set('logTasks', tasks);
  409. hostsArr.push(hostInfo);
  410. }
  411. hostsArr = hostsArr.sortProperty('name');
  412. hostsArr.setEach("serviceName", this.get("serviceName"));
  413. self.set("hosts", hostsArr);
  414. self.set('previousServiceId', this.get('currentServiceId'));
  415. }
  416. }
  417. },
  418. /**
  419. * Show popup
  420. * @return {App.ModalPopup} PopupObject For testing purposes
  421. */
  422. createPopup: function () {
  423. var self = this;
  424. var hostsInfo = this.get("hosts");
  425. var servicesInfo = this.get("servicesInfo");
  426. var isBackgroundOperations = this.get('isBackgroundOperations');
  427. var categoryObject = Em.Object.extend({
  428. value: '',
  429. count: 0,
  430. labelPath: '',
  431. label: function(){
  432. return Em.I18n.t(this.get('labelPath')).format(this.get('count'));
  433. }.property('count')
  434. });
  435. self.set('isPopup', App.ModalPopup.show({
  436. isHideBodyScroll: true,
  437. /**
  438. * no need to track is it loaded when popup contain only list of hosts
  439. * @type {bool}
  440. */
  441. isLoaded: !isBackgroundOperations,
  442. /**
  443. * is BG-popup opened
  444. * @type {bool}
  445. */
  446. isOpen: false,
  447. didInsertElement: function(){
  448. this._super();
  449. this.set('isOpen', true);
  450. },
  451. /**
  452. * @type {Em.View}
  453. */
  454. headerClass: Em.View.extend({
  455. controller: this,
  456. template: Ember.Handlebars.compile('{{popupHeaderName}}')
  457. }),
  458. /**
  459. * @type {String[]}
  460. */
  461. classNames: ['sixty-percent-width-modal', 'host-progress-popup'],
  462. /**
  463. * for the checkbox: do not show this dialog again
  464. * @type {bool}
  465. */
  466. hasFooterCheckbox: true,
  467. /**
  468. * Auto-display BG-popup
  469. * @type {bool}
  470. */
  471. isNotShowBgChecked : null,
  472. /**
  473. * Save user pref about auto-display BG-popup
  474. */
  475. updateNotShowBgChecked: function () {
  476. var curVal = !this.get('isNotShowBgChecked');
  477. var key = App.router.get('applicationController').persistKey();
  478. if (!App.get('testMode')) {
  479. App.router.get('applicationController').postUserPref(key, curVal);
  480. }
  481. }.observes('isNotShowBgChecked'),
  482. autoHeight: false,
  483. closeModelPopup: function () {
  484. this.set('isOpen', false);
  485. if(isBackgroundOperations){
  486. $(this.get('element')).detach();
  487. App.router.get('backgroundOperationsController').set('levelInfo.name', 'REQUESTS_LIST');
  488. } else {
  489. this.hide();
  490. self.set('isPopup', null);
  491. }
  492. },
  493. onPrimary: function () {
  494. this.closeModelPopup();
  495. },
  496. onClose: function () {
  497. this.closeModelPopup();
  498. },
  499. secondary: null,
  500. bodyClass: App.TableView.extend({
  501. templateName: require('templates/common/host_progress_popup'),
  502. isLogWrapHidden: true,
  503. isTaskListHidden: true,
  504. isHostListHidden: true,
  505. isServiceListHidden: false,
  506. showTextArea: false,
  507. isServiceEmptyList: true,
  508. isTasksEmptyList: true,
  509. controller: this,
  510. sourceRequestScheduleId: -1,
  511. sourceRequestScheduleRunning: false,
  512. sourceRequestScheduleAborted: false,
  513. sourceRequestScheduleCommand: null,
  514. hosts: self.get('hosts'),
  515. services: self.get('servicesInfo'),
  516. filterMap: {
  517. pending: ["pending", "queued"],
  518. in_progress: ["in_progress", "upgrading"],
  519. failed: ["failed"],
  520. completed: ["completed", "success"],
  521. aborted: ["aborted"],
  522. timedout: ["timedout"]
  523. },
  524. pagination: true,
  525. isPaginate: false,
  526. /**
  527. * Select box, display names and values
  528. */
  529. categories: [
  530. categoryObject.create({value: 'all', labelPath: 'hostPopup.status.category.all'}),
  531. categoryObject.create({value: 'pending', labelPath: 'hostPopup.status.category.pending'}),
  532. categoryObject.create({value: 'in_progress', labelPath: 'hostPopup.status.category.inProgress'}),
  533. categoryObject.create({value: 'failed', labelPath: 'hostPopup.status.category.failed'}),
  534. categoryObject.create({value: 'completed', labelPath: 'hostPopup.status.category.success'}),
  535. categoryObject.create({value: 'aborted', labelPath: 'hostPopup.status.category.aborted'}),
  536. categoryObject.create({value: 'timedout', labelPath: 'hostPopup.status.category.timedout'})
  537. ],
  538. /**
  539. * Selected option is bound to this values
  540. */
  541. serviceCategory: null,
  542. hostCategory: null,
  543. taskCategory: null,
  544. /**
  545. * flag to indicate whether level data has already been loaded
  546. * applied only to HOSTS_LIST and TASK_DETAILS levels, whereas async query used to obtain data
  547. */
  548. isLevelLoaded: true,
  549. isHostEmptyList: function() {
  550. return !this.get('pageContent.length');
  551. }.property('pageContent.length'),
  552. currentHost: function () {
  553. return this.get('hosts') && this.get('hosts').findProperty('name', this.get('controller.currentHostName'));
  554. }.property('controller.currentHostName'),
  555. tasks: function () {
  556. var currentHost = this.get('currentHost');
  557. if (currentHost) {
  558. return currentHost.get('tasks');
  559. }
  560. return [];
  561. }.property('currentHost.tasks', 'currentHost.tasks.@each.status'),
  562. /**
  563. * Preset values on init
  564. */
  565. setOnStart: function () {
  566. this.set('serviceCategory', this.get('categories').findProperty('value','all'));
  567. if (this.get("controller.isBackgroundOperations")) {
  568. this.get('controller').setSelectCount(this.get("services"), this.get('categories'));
  569. this.updateHostInfo();
  570. } else {
  571. this.set("isHostListHidden", false);
  572. this.set("isServiceListHidden", true);
  573. }
  574. },
  575. /**
  576. * force popup to show list of operations
  577. */
  578. resetState: function(){
  579. if(this.get('parentView.isOpen')){
  580. this.set('isLogWrapHidden', true);
  581. this.set('isTaskListHidden', true);
  582. this.set('isHostListHidden', true);
  583. this.set('isServiceListHidden', false);
  584. this.get("controller").setBackgroundOperationHeader(false);
  585. this.setOnStart();
  586. }
  587. }.observes('parentView.isOpen'),
  588. /**
  589. * When popup is opened, and data after polling has changed, update this data in component
  590. */
  591. updateHostInfo: function () {
  592. if(!this.get('parentView.isOpen')) return;
  593. this.set('parentView.isLoaded', false);
  594. this.get("controller").set("inputData", this.get("controller.dataSourceController.services"));
  595. this.get("controller").onServiceUpdate(this.get('isServiceListHidden'));
  596. this.get("controller").onHostUpdate();
  597. this.set('parentView.isLoaded', true);
  598. this.set("hosts", this.get("controller.hosts"));
  599. this.set("services", this.get("controller.servicesInfo"));
  600. this.set('isLevelLoaded', true);
  601. }.observes("controller.dataSourceController.serviceTimestamp"),
  602. /**
  603. * Depending on service filter, set which services should be shown
  604. */
  605. visibleServices: function () {
  606. if (this.get("services")) {
  607. this.set("isServiceEmptyList", true);
  608. if (this.get('serviceCategory.value')) {
  609. var filter = this.get('serviceCategory.value');
  610. var services = this.get('services');
  611. this.set("isServiceEmptyList", this.setVisibility(filter, services));
  612. }
  613. }
  614. }.observes('serviceCategory', 'services', 'services.@each.status'),
  615. /**
  616. * Depending on hosts filter, set which hosts should be shown
  617. */
  618. filter: function() {
  619. var _this = this,
  620. filter = this.get('hostCategory.value'),
  621. hosts = this.get('hosts') || [];
  622. if (!filter || !hosts.length) return;
  623. if (filter === 'all') {
  624. this.set('filteredContent', hosts);
  625. } else {
  626. this.set('filteredContent', hosts.filter(function(item) {
  627. return _this.get('filterMap')[filter].contains(item.status);
  628. }));
  629. }
  630. }.observes('hosts.length', 'hostCategory.value'),
  631. /**
  632. * Reset startIndex property back to 1 when filter type has been changed.
  633. */
  634. resetIndex: function() {
  635. if (this.get('hostCategory.value')) this.set('startIndex', 1)
  636. }.observes('hostCategory.value'),
  637. /**
  638. * Depending on tasks filter, set which tasks should be shown
  639. */
  640. visibleTasks: function () {
  641. this.set("isTasksEmptyList", true);
  642. if (this.get('taskCategory.value') && this.get('tasks')) {
  643. var filter = this.get('taskCategory.value');
  644. var tasks = this.get('tasks');
  645. this.set("isTasksEmptyList", this.setVisibility(filter, tasks));
  646. }
  647. }.observes('taskCategory', 'tasks', 'tasks.@each.status'),
  648. /**
  649. * Depending on selected filter type, set object visibility value
  650. * @param filter
  651. * @param obj
  652. * @return {bool} isEmptyList
  653. */
  654. setVisibility: function (filter, obj) {
  655. var isEmptyList = true;
  656. if (filter == "all") {
  657. obj.setEach("isVisible", true);
  658. isEmptyList = !(obj.length > 0);
  659. } else {
  660. obj.forEach(function(item){
  661. item.set('isVisible', this.get('filterMap')[filter].contains(item.status));
  662. isEmptyList = (isEmptyList) ? !item.get('isVisible') : false;
  663. }, this)
  664. }
  665. return isEmptyList;
  666. },
  667. /**
  668. * Depending on currently viewed tab, call setSelectCount function
  669. */
  670. updateSelectView: function () {
  671. var isPaginate;
  672. if (!this.get('isHostListHidden')) {
  673. //since lazy loading used for hosts, we need to get hosts info directly from controller, that always contains entire array of data
  674. this.get('controller').setSelectCount(this.get("controller.hosts"), this.get('categories'));
  675. isPaginate = true;
  676. } else if (!this.get('isTaskListHidden')) {
  677. this.get('controller').setSelectCount(this.get("tasks"), this.get('categories'));
  678. } else if (!this.get('isServiceListHidden')) {
  679. this.get('controller').setSelectCount(this.get("services"), this.get('categories'));
  680. }
  681. this.set('isPaginate', !!isPaginate);
  682. }.observes('tasks.@each.status', 'hosts.@each.status', 'isTaskListHidden', 'isHostListHidden', 'services.length', 'services.@each.status'),
  683. /**
  684. * control data uploading, depending on which display level is showed
  685. * @param levelName
  686. */
  687. switchLevel: function (levelName) {
  688. var dataSourceController = this.get('controller.dataSourceController');
  689. var securityControllers = [
  690. 'mainAdminSecurityDisableController',
  691. 'mainAdminSecurityAddStep4Controller'
  692. ];
  693. if (this.get("controller.isBackgroundOperations")) {
  694. var levelInfo = dataSourceController.get('levelInfo');
  695. levelInfo.set('taskId', this.get('openedTaskId'));
  696. levelInfo.set('requestId', this.get('controller.currentServiceId'));
  697. levelInfo.set('name', levelName);
  698. if (levelName === 'HOSTS_LIST') {
  699. this.set('isLevelLoaded', dataSourceController.requestMostRecent());
  700. this.set('hostCategory', this.get('categories').findProperty('value','all'));
  701. } else if (levelName === 'TASK_DETAILS') {
  702. dataSourceController.requestMostRecent();
  703. this.set('isLevelLoaded', false);
  704. } else if (levelName === 'REQUESTS_LIST') {
  705. this.set('serviceCategory', this.get('categories').findProperty('value','all'));
  706. this.get('controller.hosts').clear();
  707. dataSourceController.requestMostRecent();
  708. } else {
  709. this.set('taskCategory', this.get('categories').findProperty('value','all'));
  710. }
  711. } else if (securityControllers.contains(dataSourceController.get('name'))) {
  712. if (levelName === 'TASK_DETAILS') {
  713. this.set('isLevelLoaded', false);
  714. dataSourceController.startUpdatingTask(this.get('controller.currentServiceId'), this.get('openedTaskId'));
  715. } else {
  716. dataSourceController.stopUpdatingTask(this.get('controller.currentServiceId'));
  717. }
  718. }
  719. },
  720. /**
  721. * Onclick handler for button <-Tasks
  722. */
  723. backToTaskList: function () {
  724. this.destroyClipBoard();
  725. this.set("openedTaskId", 0);
  726. this.set("isLogWrapHidden", true);
  727. this.set("isTaskListHidden", false);
  728. this.switchLevel("TASKS_LIST");
  729. },
  730. /**
  731. * Onclick handler for button <-Hosts
  732. */
  733. backToHostList: function () {
  734. this.set("isHostListHidden", false);
  735. this.set("isTaskListHidden", true);
  736. this.get("controller").set("popupHeaderName", this.get("controller.serviceName"));
  737. this.switchLevel("HOSTS_LIST");
  738. },
  739. /**
  740. * Onclick handler for button <-Services
  741. */
  742. backToServiceList: function () {
  743. this.get("controller").set("serviceName", "");
  744. this.set("isHostListHidden", true);
  745. this.set("isServiceListHidden", false);
  746. this.set("isTaskListHidden", true);
  747. this.set("hosts", null);
  748. this.get("controller").setBackgroundOperationHeader(false);
  749. this.switchLevel("REQUESTS_LIST");
  750. },
  751. /**
  752. * Onclick handler for Show more ..
  753. */
  754. requestMoreOperations: function () {
  755. var count = App.db.getBGOOperationsCount();
  756. App.db.setBGOOperationsCount(count + 10);
  757. App.router.get('backgroundOperationsController').requestMostRecent();
  758. },
  759. setShowMoreAvailable: function () {
  760. if (this.get('parentView.isOpen')) {
  761. this.set('isShowMore', App.router.get("backgroundOperationsController.isShowMoreAvailable"));
  762. }
  763. }.observes('parentView.isOpen', 'App.router.backgroundOperationsController.isShowMoreAvailable'),
  764. isShowMore: true,
  765. /**
  766. * Onclick handler for selected Service
  767. * @param {Object} event
  768. */
  769. gotoHosts: function (event) {
  770. this.get("controller").set("serviceName", event.context.get("name"));
  771. this.get("controller").set("currentServiceId", event.context.get("id"));
  772. this.get("controller").set("currentHostName", null);
  773. this.get("controller").onHostUpdate();
  774. this.switchLevel("HOSTS_LIST");
  775. var servicesInfo = this.get("controller.hosts");
  776. if (servicesInfo.length) {
  777. this.get("controller").set("popupHeaderName", event.context.get("name"));
  778. }
  779. //apply lazy loading on cluster with more than 100 nodes
  780. if (servicesInfo.length > 100) {
  781. this.set('hosts', servicesInfo.slice(0, 50));
  782. } else {
  783. this.set('hosts', servicesInfo);
  784. }
  785. this.set("isServiceListHidden", true);
  786. this.set("isHostListHidden", false);
  787. $(".modal").scrollTop(0);
  788. $(".modal-body").scrollTop(0);
  789. if (servicesInfo.length > 100) {
  790. Em.run.next(this, function(){
  791. this.set('hosts', this.get('hosts').concat(servicesInfo.slice(50, servicesInfo.length)));
  792. });
  793. }
  794. // Determine if source request schedule is present
  795. this.set('sourceRequestScheduleId', event.context.get("sourceRequestScheduleId"));
  796. this.set('sourceRequestScheduleCommand', event.context.get('contextCommand'));
  797. this.refreshRequestScheduleInfo();
  798. },
  799. isRequestSchedule : function() {
  800. var id = this.get('sourceRequestScheduleId');
  801. return id != null && !isNaN(id) && id > -1;
  802. }.property('sourceRequestScheduleId'),
  803. refreshRequestScheduleInfo : function() {
  804. var self = this;
  805. var id = this.get('sourceRequestScheduleId');
  806. batchUtils.getRequestSchedule(id, function(data) {
  807. if (data != null && data.RequestSchedule != null &&
  808. data.RequestSchedule.status != null) {
  809. switch (data.RequestSchedule.status) {
  810. case 'DISABLED':
  811. self.set('sourceRequestScheduleRunning', false);
  812. self.set('sourceRequestScheduleAborted', true);
  813. break;
  814. case 'COMPLETED':
  815. self.set('sourceRequestScheduleRunning', false);
  816. self.set('sourceRequestScheduleAborted', false);
  817. break;
  818. case 'SCHEDULED':
  819. self.set('sourceRequestScheduleRunning', true);
  820. self.set('sourceRequestScheduleAborted', false);
  821. break;
  822. }
  823. } else {
  824. self.set('sourceRequestScheduleRunning', false);
  825. self.set('sourceRequestScheduleAborted', false);
  826. }
  827. }, function(xhr, textStatus, error, opt) {
  828. console.log("Error getting request schedule information: ", textStatus, error, opt);
  829. self.set('sourceRequestScheduleRunning', false);
  830. self.set('sourceRequestScheduleAborted', false);
  831. });
  832. }.observes('sourceRequestScheduleId'),
  833. /**
  834. * Attempts to abort the current request schedule
  835. */
  836. doAbortRequestSchedule: function(event){
  837. var self = this;
  838. var id = event.context;
  839. console.log("Aborting request schedule: ", id);
  840. batchUtils.doAbortRequestSchedule(id, function(){
  841. self.refreshRequestScheduleInfo();
  842. });
  843. },
  844. requestScheduleAbortLabel : function() {
  845. var label = Em.I18n.t("common.abort");
  846. var command = this.get('sourceRequestScheduleCommand');
  847. if (command != null && "ROLLING-RESTART" == command) {
  848. label = Em.I18n.t("hostPopup.bgop.abort.rollingRestart");
  849. }
  850. return label;
  851. }.property('sourceRequestScheduleCommand'),
  852. /**
  853. * Onclick handler for selected Host
  854. * @param {Object} event
  855. */
  856. gotoTasks: function (event) {
  857. var tasksInfo = [];
  858. event.context.logTasks.forEach(function (_task) {
  859. tasksInfo.pushObject(this.get("controller").createTask(_task));
  860. }, this);
  861. if (tasksInfo.length) {
  862. this.get("controller").set("popupHeaderName", event.context.publicName);
  863. this.get("controller").set("currentHostName", event.context.publicName);
  864. }
  865. this.switchLevel("TASKS_LIST");
  866. this.set('currentHost.tasks', tasksInfo);
  867. this.set("isHostListHidden", true);
  868. this.set("isTaskListHidden", false);
  869. $(".modal").scrollTop(0);
  870. $(".modal-body").scrollTop(0);
  871. },
  872. stopRebalanceHDFS: function () {
  873. var hostPopup = this;
  874. return App.showConfirmationPopup(function () {
  875. App.ajax.send({
  876. name : 'cancel.background.operation',
  877. sender : hostPopup,
  878. data : {
  879. cancelTaskId : hostPopup.get('openedTaskId'),
  880. command : "REFRESHQUEUES",
  881. context : Em.I18n.t('services.service.actions.run.yarnRefreshQueues.context') ,
  882. hosts : App.Service.find('HDFS').get('hostComponents').findProperty('componentName', 'NAMENODE').get('hostName'),
  883. serviceName : "HDFS",
  884. componentName : "NAMENODE"
  885. }
  886. });
  887. hostPopup.backToServiceList();
  888. });
  889. },
  890. /**
  891. * Onclick handler for selected Task
  892. */
  893. openTaskLogInDialog: function () {
  894. if ($(".task-detail-log-clipboard").length > 0) {
  895. this.destroyClipBoard();
  896. }
  897. var newWindow = window.open();
  898. var newDocument = newWindow.document;
  899. newDocument.write($(".task-detail-log-info").html());
  900. newDocument.close();
  901. },
  902. openedTaskId: 0,
  903. /**
  904. * Return task detail info of opened task
  905. */
  906. openedTask: function () {
  907. if (!(this.get('openedTaskId') && this.get('tasks'))) {
  908. return Ember.Object.create();
  909. }
  910. return this.get('tasks').findProperty('id', this.get('openedTaskId'));
  911. }.property('tasks', 'tasks.@each.stderr', 'tasks.@each.stdout', 'openedTaskId'),
  912. /**
  913. * Onclick event for show task detail info
  914. * @param {Object} event
  915. */
  916. toggleTaskLog: function (event) {
  917. var taskInfo = event.context;
  918. this.set("isLogWrapHidden", false);
  919. if ($(".task-detail-log-clipboard").length > 0) {
  920. this.destroyClipBoard();
  921. }
  922. this.set("isHostListHidden", true);
  923. this.set("isTaskListHidden", true);
  924. this.set('openedTaskId', taskInfo.id);
  925. this.switchLevel("TASK_DETAILS");
  926. $(".modal").scrollTop(0);
  927. $(".modal-body").scrollTop(0);
  928. },
  929. /**
  930. * Onclick event for copy to clipboard button
  931. */
  932. textTrigger: function () {
  933. $(".task-detail-log-clipboard").length > 0 ? this.destroyClipBoard() : this.createClipBoard();
  934. },
  935. /**
  936. * Create Clip Board
  937. */
  938. createClipBoard: function () {
  939. var logElement = $(".task-detail-log-maintext");
  940. $(".task-detail-log-clipboard-wrap").html('<textarea class="task-detail-log-clipboard"></textarea>');
  941. $(".task-detail-log-clipboard")
  942. .html("stderr: \n" + $(".stderr").html() + "\n stdout:\n" + $(".stdout").html())
  943. .css("display", "block")
  944. .width(logElement.width())
  945. .height(logElement.height())
  946. .select();
  947. logElement.css("display", "none")
  948. },
  949. /**
  950. * Destroy Clip Board
  951. */
  952. destroyClipBoard: function () {
  953. $(".task-detail-log-clipboard").remove();
  954. $(".task-detail-log-maintext").css("display", "block");
  955. }
  956. })
  957. }));
  958. return self.get('isPopup');
  959. }
  960. });