host_progress_popup.js 36 KB

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