host_progress_popup.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  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 = ['CANCELLED', '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': ['CANCELLED', '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),
  279. status: App.format.taskStatus(_task.Tasks.status),
  280. role: App.format.role(_task.Tasks.role),
  281. outputLog: Em.I18n.t('common.hostLog.popup.logDir.path') + Em.I18n.t('common.hostLog.popup.outputLog.value').format(_task.Tasks.id),
  282. errorLog: Em.I18n.t('common.hostLog.popup.logDir.path') + Em.I18n.t('common.hostLog.popup.errorLog.value').format(_task.Tasks.id),
  283. stderr: _task.Tasks.stderr,
  284. stdout: _task.Tasks.stdout,
  285. isVisible: true,
  286. startTime: date.startTime(_task.Tasks.start_time),
  287. duration: date.durationSummary(_task.Tasks.start_time, _task.Tasks.end_time),
  288. icon: function () {
  289. var statusIconMap = {
  290. 'pending': 'icon-cog',
  291. 'queued': 'icon-cog',
  292. 'in_progress': 'icon-cogs',
  293. 'completed': 'icon-ok',
  294. 'failed': 'icon-exclamation-sign',
  295. 'aborted': 'icon-minus',
  296. 'timedout': 'icon-time'
  297. };
  298. return statusIconMap[this.get('status')] || 'icon-cog';
  299. }.property('status')
  300. });
  301. },
  302. /**
  303. * Create hosts and tasks data structure for popup
  304. * Set data for hosts and tasks
  305. */
  306. onHostUpdate: function () {
  307. var self = this;
  308. var inputData = this.get("inputData");
  309. if (inputData) {
  310. var hostsArr = [];
  311. var hostsData;
  312. var hostsMap = {};
  313. if(this.get('isBackgroundOperations') && this.get("currentServiceId")){
  314. //hosts popup for Background Operations
  315. hostsData = inputData.findProperty("id", this.get("currentServiceId"));
  316. } else if (this.get("serviceName")) {
  317. //hosts popup for Wizards
  318. hostsData = inputData.findProperty("name", this.get("serviceName"));
  319. }
  320. if (hostsData) {
  321. if (hostsData.hostsMap) {
  322. //hosts data come from Background Operations as object map
  323. hostsMap = hostsData.hostsMap;
  324. } else if (hostsData.hosts) {
  325. //hosts data come from Wizard as array
  326. hostsData.hosts.forEach(function (_host) {
  327. hostsMap[_host.name] = _host;
  328. });
  329. }
  330. }
  331. var existedHosts = self.get('hosts');
  332. if (existedHosts && (existedHosts.length > 0) && this.get('currentServiceId') === this.get('previousServiceId')) {
  333. existedHosts.forEach(function (host) {
  334. var newHostInfo = hostsMap[host.get('name')];
  335. //update only hosts with changed tasks or currently opened tasks of host
  336. if (newHostInfo && (!this.get('isBackgroundOperations') || newHostInfo.isModified || this.get('currentHostName') === host.get('name'))) {
  337. var hostStatus = self.getStatus(newHostInfo.logTasks);
  338. var hostProgress = self.getProgress(newHostInfo.logTasks);
  339. host.set('status', App.format.taskStatus(hostStatus[0]));
  340. host.set('icon', hostStatus[1]);
  341. host.set('barColor', hostStatus[2]);
  342. host.set('isInProgress', hostStatus[3]);
  343. host.set('progress', hostProgress);
  344. host.set('barWidth', "width:" + hostProgress + "%;");
  345. host.set('logTasks', newHostInfo.logTasks);
  346. var existTasks = host.get('tasks');
  347. if (existTasks) {
  348. newHostInfo.logTasks.forEach(function (_task) {
  349. var existTask = existTasks.findProperty('id', _task.Tasks.id);
  350. if (existTask) {
  351. existTask.set('status', App.format.taskStatus(_task.Tasks.status));
  352. existTask.set('stdout', _task.Tasks.stdout);
  353. existTask.set('stderr', _task.Tasks.stderr);
  354. existTask.set('startTime', date.startTime(_task.Tasks.start_time));
  355. existTask.set('duration', date.durationSummary(_task.Tasks.start_time, _task.Tasks.end_time));
  356. } else {
  357. existTasks.pushObject(this.createTask(_task));
  358. }
  359. }, this);
  360. }
  361. }
  362. }, this);
  363. } else {
  364. for (var hostName in hostsMap) {
  365. var _host = hostsMap[hostName];
  366. var tasks = _host.logTasks;
  367. var hostInfo = Ember.Object.create({
  368. name: hostName,
  369. publicName: _host.publicName,
  370. displayName: function () {
  371. return this.get('name').length < 43 ? this.get('name') : (this.get('name').substr(0, 40) + '...');
  372. }.property('name'),
  373. progress: 0,
  374. status: App.format.taskStatus("PENDING"),
  375. serviceName: _host.serviceName,
  376. isVisible: true,
  377. icon: "icon-cog",
  378. barColor: "progress-info",
  379. barWidth: "width:0%;"
  380. });
  381. if (tasks.length) {
  382. tasks = tasks.sortProperty('Tasks.id');
  383. var hostStatus = self.getStatus(tasks);
  384. var hostProgress = self.getProgress(tasks);
  385. hostInfo.set('status', App.format.taskStatus(hostStatus[0]));
  386. hostInfo.set('icon', hostStatus[1]);
  387. hostInfo.set('barColor', hostStatus[2]);
  388. hostInfo.set('isInProgress', hostStatus[3]);
  389. hostInfo.set('progress', hostProgress);
  390. hostInfo.set('barWidth', "width:" + hostProgress + "%;");
  391. }
  392. hostInfo.set('logTasks', tasks);
  393. hostsArr.push(hostInfo);
  394. }
  395. hostsArr = hostsArr.sortProperty('name');
  396. hostsArr.setEach("serviceName", this.get("serviceName"));
  397. self.set("hosts", hostsArr);
  398. self.set('previousServiceId', this.get('currentServiceId'));
  399. }
  400. }
  401. },
  402. /**
  403. * Show popup
  404. * @return {App.ModalPopup} PopupObject For testing purposes
  405. */
  406. createPopup: function () {
  407. var self = this;
  408. var hostsInfo = this.get("hosts");
  409. var servicesInfo = this.get("servicesInfo");
  410. var isBackgroundOperations = this.get('isBackgroundOperations');
  411. var categoryObject = Em.Object.extend({
  412. value: '',
  413. count: 0,
  414. labelPath: '',
  415. label: function(){
  416. return Em.I18n.t(this.get('labelPath')).format(this.get('count'));
  417. }.property('count')
  418. });
  419. self.set('isPopup', App.ModalPopup.show({
  420. isHideBodyScroll: true,
  421. /**
  422. * no need to track is it loaded when popup contain only list of hosts
  423. * @type {bool}
  424. */
  425. isLoaded: !isBackgroundOperations,
  426. /**
  427. * is BG-popup opened
  428. * @type {bool}
  429. */
  430. isOpen: false,
  431. didInsertElement: function(){
  432. this._super();
  433. this.set('isOpen', true);
  434. },
  435. /**
  436. * @type {Em.View}
  437. */
  438. headerClass: Em.View.extend({
  439. controller: this,
  440. template: Ember.Handlebars.compile('{{popupHeaderName}}')
  441. }),
  442. /**
  443. * @type {String[]}
  444. */
  445. classNames: ['sixty-percent-width-modal', 'host-progress-popup'],
  446. /**
  447. * for the checkbox: do not show this dialog again
  448. * @type {bool}
  449. */
  450. hasFooterCheckbox: true,
  451. /**
  452. * Auto-display BG-popup
  453. * @type {bool}
  454. */
  455. isNotShowBgChecked : null,
  456. /**
  457. * Save user pref about auto-display BG-popup
  458. */
  459. updateNotShowBgChecked: function () {
  460. var curVal = !this.get('isNotShowBgChecked');
  461. var key = App.router.get('applicationController').persistKey();
  462. if (!App.testMode) {
  463. App.router.get('applicationController').postUserPref(key, curVal);
  464. }
  465. }.observes('isNotShowBgChecked'),
  466. autoHeight: false,
  467. closeModelPopup: function () {
  468. this.set('isOpen', false);
  469. if(isBackgroundOperations){
  470. $(this.get('element')).detach();
  471. App.router.get('backgroundOperationsController').set('levelInfo.name', 'REQUESTS_LIST');
  472. } else {
  473. this.hide();
  474. self.set('isPopup', null);
  475. }
  476. },
  477. onPrimary: function () {
  478. this.closeModelPopup();
  479. },
  480. onClose: function () {
  481. this.closeModelPopup();
  482. },
  483. secondary: null,
  484. bodyClass: App.TableView.extend({
  485. templateName: require('templates/common/host_progress_popup'),
  486. isLogWrapHidden: true,
  487. isTaskListHidden: true,
  488. isHostListHidden: true,
  489. isServiceListHidden: false,
  490. showTextArea: false,
  491. isServiceEmptyList: true,
  492. isHostEmptyList: true,
  493. isTasksEmptyList: true,
  494. controller: this,
  495. sourceRequestScheduleId: -1,
  496. sourceRequestScheduleRunning: false,
  497. sourceRequestScheduleAborted: false,
  498. sourceRequestScheduleCommand: null,
  499. hosts: self.get('hosts'),
  500. services: self.get('servicesInfo'),
  501. filterMap: {
  502. pending: ["pending", "queued"],
  503. in_progress: ["in_progress", "upgrading"],
  504. failed: ["failed"],
  505. completed: ["completed", "success"],
  506. aborted: ["aborted"],
  507. timedout: ["timedout"]
  508. },
  509. pagination: true,
  510. isPaginate: false,
  511. content: function() {
  512. return this.get('hosts') || [];
  513. }.property('hosts.length', 'isHostListHidden'),
  514. currentHost: function () {
  515. return this.get('hosts') && this.get('hosts').findProperty('name', this.get('controller.currentHostName'));
  516. }.property('controller.currentHostName'),
  517. tasks: function () {
  518. var currentHost = this.get('currentHost');
  519. if (currentHost) {
  520. return currentHost.get('tasks');
  521. }
  522. return [];
  523. }.property('currentHost.tasks', 'currentHost.tasks.@each.status'),
  524. /**
  525. * Preset values on init
  526. */
  527. setOnStart: function () {
  528. this.set('serviceCategory', this.get('categories').findProperty('value','all'));
  529. if (this.get("controller.isBackgroundOperations")) {
  530. this.get('controller').setSelectCount(this.get("services"), this.get('categories'));
  531. this.updateHostInfo();
  532. } else {
  533. this.set("isHostListHidden", false);
  534. this.set("isServiceListHidden", true);
  535. }
  536. },
  537. /**
  538. * force popup to show list of operations
  539. */
  540. resetState: function(){
  541. if(this.get('parentView.isOpen')){
  542. this.set('isLogWrapHidden', true);
  543. this.set('isTaskListHidden', true);
  544. this.set('isHostListHidden', true);
  545. this.set('isServiceListHidden', false);
  546. this.get("controller").setBackgroundOperationHeader(false);
  547. this.setOnStart();
  548. }
  549. }.observes('parentView.isOpen'),
  550. /**
  551. * When popup is opened, and data after polling has changed, update this data in component
  552. */
  553. updateHostInfo: function () {
  554. if(!this.get('parentView.isOpen')) return;
  555. this.set('parentView.isLoaded', false);
  556. this.get("controller").set("inputData", this.get("controller.dataSourceController.services"));
  557. this.get("controller").onServiceUpdate(this.get('isServiceListHidden'));
  558. this.get("controller").onHostUpdate();
  559. this.set('parentView.isLoaded', true);
  560. //push hosts into view when none or all hosts are loaded
  561. if(this.get('hosts') == null || this.get('hosts').length === this.get("controller.hosts").length){
  562. this.set("hosts", this.get("controller.hosts"));
  563. }
  564. this.set("services", this.get("controller.servicesInfo"));
  565. }.observes("controller.dataSourceController.serviceTimestamp"),
  566. /**
  567. * Depending on service filter, set which services should be shown
  568. */
  569. visibleServices: function () {
  570. if (this.get("services")) {
  571. this.set("isServiceEmptyList", true);
  572. if (this.get('serviceCategory.value')) {
  573. var filter = this.get('serviceCategory.value');
  574. var services = this.get('services');
  575. this.set("isServiceEmptyList", this.setVisibility(filter, services));
  576. }
  577. }
  578. }.observes('serviceCategory', 'services', 'services.@each.status'),
  579. /**
  580. * Depending on hosts filter, set which hosts should be shown
  581. */
  582. filter: function() {
  583. var _this = this,
  584. filter = this.get('hostCategory.value'),
  585. hosts = this.get('content');
  586. if (!filter || !hosts.length) return;
  587. if (filter === 'all') {
  588. this.set('filteredContent', hosts);
  589. } else {
  590. this.set('filteredContent', hosts.filter(function(item) {
  591. return _this.get('filterMap')[filter].contains(item.status);
  592. }));
  593. }
  594. this.set("isHostEmptyList", !this.get('pageContent.length'));
  595. }.observes('content.length', 'hostCategory.value'),
  596. /**
  597. * Reset startIndex property back to 1 when filter type has been changed.
  598. */
  599. resetIndex: function() {
  600. if (this.get('hostCategory.value')) this.set('startIndex', 1)
  601. }.observes('hostCategory.value'),
  602. /**
  603. * Depending on tasks filter, set which tasks should be shown
  604. */
  605. visibleTasks: function () {
  606. this.set("isTasksEmptyList", true);
  607. if (this.get('taskCategory.value') && this.get('tasks')) {
  608. var filter = this.get('taskCategory.value');
  609. var tasks = this.get('tasks');
  610. this.set("isTasksEmptyList", this.setVisibility(filter, tasks));
  611. }
  612. }.observes('taskCategory', 'tasks', 'tasks.@each.status'),
  613. /**
  614. * Depending on selected filter type, set object visibility value
  615. * @param filter
  616. * @param obj
  617. * @return {bool} isEmptyList
  618. */
  619. setVisibility: function (filter, obj) {
  620. var isEmptyList = true;
  621. if (filter == "all") {
  622. obj.setEach("isVisible", true);
  623. isEmptyList = !(obj.length > 0);
  624. } else {
  625. obj.forEach(function(item){
  626. item.set('isVisible', this.get('filterMap')[filter].contains(item.status));
  627. isEmptyList = (isEmptyList) ? !item.get('isVisible') : false;
  628. }, this)
  629. }
  630. return isEmptyList;
  631. },
  632. /**
  633. * Select box, display names and values
  634. */
  635. categories: [
  636. categoryObject.create({value: 'all', labelPath: 'hostPopup.status.category.all'}),
  637. categoryObject.create({value: 'pending', labelPath: 'hostPopup.status.category.pending'}),
  638. categoryObject.create({value: 'in_progress', labelPath: 'hostPopup.status.category.inProgress'}),
  639. categoryObject.create({value: 'failed', labelPath: 'hostPopup.status.category.failed'}),
  640. categoryObject.create({value: 'completed', labelPath: 'hostPopup.status.category.success'}),
  641. categoryObject.create({value: 'aborted', labelPath: 'hostPopup.status.category.aborted'}),
  642. categoryObject.create({value: 'timedout', labelPath: 'hostPopup.status.category.timedout'})
  643. ],
  644. /**
  645. * Selected option is binded to this values
  646. */
  647. serviceCategory: null,
  648. hostCategory: null,
  649. taskCategory: null,
  650. /**
  651. * Depending on currently viewed tab, call setSelectCount function
  652. */
  653. updateSelectView: function () {
  654. var isPaginate;
  655. if (!this.get('isHostListHidden')) {
  656. //since lazy loading used for hosts, we need to get hosts info directly from controller, that always contains entire array of data
  657. this.get('controller').setSelectCount(this.get("controller.hosts"), this.get('categories'));
  658. isPaginate = true;
  659. } else if (!this.get('isTaskListHidden')) {
  660. this.get('controller').setSelectCount(this.get("tasks"), this.get('categories'));
  661. } else if (!this.get('isServiceListHidden')) {
  662. this.get('controller').setSelectCount(this.get("services"), this.get('categories'));
  663. }
  664. this.set('isPaginate', !!isPaginate);
  665. }.observes('tasks.@each.status', 'hosts.@each.status', 'isTaskListHidden', 'isHostListHidden', 'services.length', 'services.@each.status'),
  666. /**
  667. * control data uploading, depending on which display level is showed
  668. * @param levelName
  669. */
  670. switchLevel: function (levelName) {
  671. var dataSourceController = this.get('controller.dataSourceController');
  672. var securityControllers = [
  673. 'mainAdminSecurityDisableController',
  674. 'mainAdminSecurityAddStep4Controller'
  675. ];
  676. if (this.get("controller.isBackgroundOperations")) {
  677. var levelInfo = dataSourceController.get('levelInfo');
  678. levelInfo.set('taskId', this.get('openedTaskId'));
  679. levelInfo.set('requestId', this.get('controller.currentServiceId'));
  680. levelInfo.set('name', levelName);
  681. if (levelName === 'HOSTS_LIST') {
  682. levelInfo.set('sync', (this.get('controller.hosts').length === 0));
  683. dataSourceController.requestMostRecent();
  684. } else if (levelName === 'TASK_DETAILS') {
  685. levelInfo.set('sync', true);
  686. dataSourceController.requestMostRecent();
  687. } else if (levelName === 'REQUESTS_LIST') {
  688. this.get('controller.hosts').clear();
  689. dataSourceController.requestMostRecent();
  690. }
  691. } else if (securityControllers.contains(dataSourceController.get('name'))) {
  692. if (levelName === 'TASK_DETAILS') {
  693. dataSourceController.startUpdatingTask(this.get('controller.currentServiceId'), this.get('openedTaskId'));
  694. } else {
  695. dataSourceController.stopUpdatingTask(this.get('controller.currentServiceId'));
  696. }
  697. }
  698. },
  699. /**
  700. * Onclick handler for button <-Tasks
  701. */
  702. backToTaskList: function () {
  703. this.destroyClipBoard();
  704. this.set("openedTaskId", 0);
  705. this.set("isLogWrapHidden", true);
  706. this.set("isTaskListHidden", false);
  707. this.switchLevel("TASKS_LIST");
  708. },
  709. /**
  710. * Onclick handler for button <-Hosts
  711. */
  712. backToHostList: function () {
  713. this.set("isHostListHidden", false);
  714. this.set("isTaskListHidden", true);
  715. this.get("controller").set("popupHeaderName", this.get("controller.serviceName"));
  716. this.switchLevel("HOSTS_LIST");
  717. },
  718. /**
  719. * Onclick handler for button <-Services
  720. */
  721. backToServiceList: function () {
  722. this.get("controller").set("serviceName", "");
  723. this.set("isHostListHidden", true);
  724. this.set("isServiceListHidden", false);
  725. this.set("isTaskListHidden", true);
  726. this.set("hosts", null);
  727. this.get("controller").setBackgroundOperationHeader(false);
  728. this.switchLevel("REQUESTS_LIST");
  729. },
  730. /**
  731. * Onclick handler for selected Service
  732. * @param {Object} event
  733. */
  734. gotoHosts: function (event) {
  735. this.get("controller").set("serviceName", event.context.get("name"));
  736. this.get("controller").set("currentServiceId", event.context.get("id"));
  737. this.get("controller").set("currentHostName", null);
  738. this.get("controller").onHostUpdate();
  739. this.switchLevel("HOSTS_LIST");
  740. var servicesInfo = this.get("controller.hosts");
  741. if (servicesInfo.length) {
  742. this.get("controller").set("popupHeaderName", event.context.get("name"));
  743. }
  744. //apply lazy loading on cluster with more than 100 nodes
  745. if (servicesInfo.length > 100) {
  746. this.set('hosts', servicesInfo.slice(0, 50));
  747. } else {
  748. this.set('hosts', servicesInfo);
  749. }
  750. this.set("isServiceListHidden", true);
  751. this.set("isHostListHidden", false);
  752. $(".modal").scrollTop(0);
  753. $(".modal-body").scrollTop(0);
  754. if (servicesInfo.length > 100) {
  755. Em.run.next(this, function(){
  756. this.set('hosts', this.get('hosts').concat(servicesInfo.slice(50, servicesInfo.length)));
  757. });
  758. }
  759. // Determine if source request schedule is present
  760. this.set('sourceRequestScheduleId', event.context.get("sourceRequestScheduleId"));
  761. this.set('sourceRequestScheduleCommand', event.context.get('contextCommand'));
  762. this.refreshRequestScheduleInfo();
  763. },
  764. isRequestSchedule : function() {
  765. var id = this.get('sourceRequestScheduleId');
  766. return id != null && !isNaN(id) && id > -1;
  767. }.property('sourceRequestScheduleId'),
  768. refreshRequestScheduleInfo : function() {
  769. var self = this;
  770. var id = this.get('sourceRequestScheduleId');
  771. batchUtils.getRequestSchedule(id, function(data) {
  772. if (data != null && data.RequestSchedule != null &&
  773. data.RequestSchedule.status != null) {
  774. switch (data.RequestSchedule.status) {
  775. case 'DISABLED':
  776. self.set('sourceRequestScheduleRunning', false);
  777. self.set('sourceRequestScheduleAborted', true);
  778. break;
  779. case 'COMPLETED':
  780. self.set('sourceRequestScheduleRunning', false);
  781. self.set('sourceRequestScheduleAborted', false);
  782. break;
  783. case 'SCHEDULED':
  784. self.set('sourceRequestScheduleRunning', true);
  785. self.set('sourceRequestScheduleAborted', false);
  786. break;
  787. }
  788. } else {
  789. self.set('sourceRequestScheduleRunning', false);
  790. self.set('sourceRequestScheduleAborted', false);
  791. }
  792. }, function(xhr, textStatus, error, opt) {
  793. console.log("Error getting request schedule information: ", textStatus, error, opt);
  794. self.set('sourceRequestScheduleRunning', false);
  795. self.set('sourceRequestScheduleAborted', false);
  796. });
  797. }.observes('sourceRequestScheduleId'),
  798. /**
  799. * Attempts to abort the current request schedule
  800. */
  801. doAbortRequestSchedule: function(event){
  802. var self = this;
  803. var id = event.context;
  804. console.log("Aborting request schedule: ", id);
  805. batchUtils.doAbortRequestSchedule(id, function(){
  806. self.refreshRequestScheduleInfo();
  807. });
  808. },
  809. requestScheduleAbortLabel : function() {
  810. var label = Em.I18n.t("common.abort");
  811. var command = this.get('sourceRequestScheduleCommand');
  812. if (command != null && "ROLLING-RESTART" == command) {
  813. label = Em.I18n.t("hostPopup.bgop.abort.rollingRestart");
  814. }
  815. return label;
  816. }.property('sourceRequestScheduleCommand'),
  817. /**
  818. * Onclick handler for selected Host
  819. * @param {Object} event
  820. */
  821. gotoTasks: function (event) {
  822. var tasksInfo = [];
  823. event.context.logTasks.forEach(function (_task) {
  824. tasksInfo.pushObject(this.get("controller").createTask(_task));
  825. }, this);
  826. if (tasksInfo.length) {
  827. this.get("controller").set("popupHeaderName", event.context.publicName);
  828. this.get("controller").set("currentHostName", event.context.publicName);
  829. }
  830. this.switchLevel("TASKS_LIST");
  831. this.set('currentHost.tasks', tasksInfo);
  832. this.set("isHostListHidden", true);
  833. this.set("isTaskListHidden", false);
  834. $(".modal").scrollTop(0);
  835. $(".modal-body").scrollTop(0);
  836. },
  837. /**
  838. * Onclick handler for selected Task
  839. */
  840. openTaskLogInDialog: function () {
  841. if ($(".task-detail-log-clipboard").length > 0) {
  842. this.destroyClipBoard();
  843. }
  844. var newWindow = window.open();
  845. var newDocument = newWindow.document;
  846. newDocument.write($(".task-detail-log-info").html());
  847. newDocument.close();
  848. },
  849. openedTaskId: 0,
  850. /**
  851. * Return task detail info of opened task
  852. */
  853. openedTask: function () {
  854. if (!(this.get('openedTaskId') && this.get('tasks'))) {
  855. return Ember.Object.create();
  856. }
  857. return this.get('tasks').findProperty('id', this.get('openedTaskId'));
  858. }.property('tasks', 'tasks.@each.stderr', 'tasks.@each.stdout', 'openedTaskId'),
  859. /**
  860. * Onclick event for show task detail info
  861. * @param {Object} event
  862. */
  863. toggleTaskLog: function (event) {
  864. var taskInfo = event.context;
  865. this.set("isLogWrapHidden", false);
  866. if ($(".task-detail-log-clipboard").length > 0) {
  867. this.destroyClipBoard();
  868. }
  869. this.set("isHostListHidden", true);
  870. this.set("isTaskListHidden", true);
  871. this.set('openedTaskId', taskInfo.id);
  872. this.switchLevel("TASK_DETAILS");
  873. $(".modal").scrollTop(0);
  874. $(".modal-body").scrollTop(0);
  875. },
  876. /**
  877. * Onclick event for copy to clipboard button
  878. */
  879. textTrigger: function () {
  880. $(".task-detail-log-clipboard").length > 0 ? this.destroyClipBoard() : this.createClipBoard();
  881. },
  882. /**
  883. * Create Clip Board
  884. */
  885. createClipBoard: function () {
  886. var logElement = $(".task-detail-log-maintext");
  887. $(".task-detail-log-clipboard-wrap").html('<textarea class="task-detail-log-clipboard"></textarea>');
  888. $(".task-detail-log-clipboard")
  889. .html("stderr: \n" + $(".stderr").html() + "\n stdout:\n" + $(".stdout").html())
  890. .css("display", "block")
  891. .width(logElement.width())
  892. .height(logElement.height())
  893. .select();
  894. logElement.css("display", "none")
  895. },
  896. /**
  897. * Destroy Clip Board
  898. */
  899. destroyClipBoard: function () {
  900. $(".task-detail-log-clipboard").remove();
  901. $(".task-detail-log-maintext").css("display", "block");
  902. }
  903. })
  904. }));
  905. return self.get('isPopup');
  906. }
  907. });