progress_popup_controller.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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. App.HighAvailabilityProgressPopupController = Ember.Controller.extend({
  19. name: 'highAvailabilityProgressPopupController',
  20. /**
  21. * Id of current request
  22. * @type {Array}
  23. */
  24. requestIds: [],
  25. /**
  26. * Title for popup header
  27. * @type {String}
  28. */
  29. popupTitle: '',
  30. /**
  31. * Array with Hosts tasks data used in <code>App.HostPopup</code>
  32. * @type {Array}
  33. */
  34. services: [],
  35. /**
  36. * Timestamp used in <code>App.HostPopup</code>
  37. * @type {Number}
  38. */
  39. serviceTimestamp: null,
  40. /**
  41. * Progress controller. Used to get tasks data.
  42. * @type {App.HighAvailabilityProgressPageController}
  43. */
  44. progressController: null,
  45. /**
  46. * Requests data with tasks
  47. * @type {Array}
  48. */
  49. hostsData: [],
  50. /**
  51. * StageId for the command.
  52. * @type {Number}
  53. */
  54. stageId: null,
  55. /**
  56. * During loading and calculations show popup with spinner
  57. * @type {Object}
  58. */
  59. spinnerPopup: null,
  60. isTaskPolling: false,
  61. taskInfo: null,
  62. /**
  63. * Get info for <code>requestIds</code> and initialize <code>App.HostPopup</code>
  64. * @param popupTitle {String}
  65. * @param requestIds {Array}
  66. * @param progressController {App.HighAvailabilityProgressPageController}
  67. * @param showSpinner {Boolean}
  68. * @param stageId {Number}
  69. */
  70. initPopup: function (popupTitle, requestIds, progressController, showSpinner, stageId) {
  71. if (showSpinner) {
  72. var loadingPopup = App.ModalPopup.show({
  73. header: Em.I18n.t('jobs.loadingTasks'),
  74. primary: false,
  75. secondary: false,
  76. bodyClass: Ember.View.extend({
  77. template: Ember.Handlebars.compile('{{view App.SpinnerView}}')
  78. })
  79. });
  80. this.set('spinnerPopup', loadingPopup);
  81. }
  82. this.setProperties({
  83. progressController: progressController,
  84. popupTitle: popupTitle,
  85. requestIds: requestIds,
  86. hostsData: [],
  87. stageId: stageId
  88. });
  89. this.getHosts();
  90. },
  91. /**
  92. * Send AJAX request to get hosts tasks data
  93. */
  94. getHosts: function (successCallback) {
  95. var requestIds = this.get('requestIds');
  96. var stageId = this.get('stageId');
  97. var name = 'background_operations.get_by_request';
  98. if (!Em.isNone(stageId)) {
  99. name = 'common.request.polling';
  100. if (stageId === 0) {
  101. stageId = '0';
  102. }
  103. }
  104. if (Em.isNone(successCallback)) {
  105. successCallback = 'onGetHostsSuccess';
  106. }
  107. requestIds.forEach(function (requestId) {
  108. App.ajax.send({
  109. name: name,
  110. sender: this,
  111. data: {
  112. requestId: requestId,
  113. stageId: stageId
  114. },
  115. success: successCallback
  116. })
  117. }, this);
  118. },
  119. doPolling: function () {
  120. var self = this;
  121. this.set('progressController.logs', []);
  122. setTimeout(function () {
  123. self.getHosts('doPollingSuccessCallback');
  124. }, App.bgOperationsUpdateInterval);
  125. },
  126. doPollingSuccessCallback: function (data) {
  127. this.set('hostsData', [data]);
  128. var hostsData = this.get('hostsData');
  129. this.set('progressController.logs', data.tasks);
  130. if (this.isRequestRunning(hostsData)) {
  131. this.doPolling();
  132. }
  133. },
  134. /**
  135. * Callback for <code>getHosts</code> request
  136. * @param data
  137. */
  138. onGetHostsSuccess: function (data) {
  139. var hostsData = this.get('hostsData');
  140. hostsData.push(data);
  141. if (this.get('requestIds.length') === this.get('hostsData.length')) {
  142. var popupTitle = this.get('popupTitle');
  143. this.calculateHostsData(hostsData);
  144. App.HostPopup.initPopup(popupTitle, this);
  145. if (this.isRequestRunning(hostsData)) {
  146. if (this.get('progressController.name') === 'mainAdminStackAndUpgradeController') {
  147. this.doPolling();
  148. }
  149. this.addObserver('progressController.logs.length', this, 'getDataFromProgressController');
  150. }
  151. }
  152. if (this.get('spinnerPopup')) {
  153. this.get('spinnerPopup').hide();
  154. this.set('spinnerPopup', null);
  155. }
  156. },
  157. /**
  158. * Convert data to format used in <code>App.HostPopup</code>
  159. * @param data {Array}
  160. */
  161. calculateHostsData: function (data) {
  162. var hosts = [];
  163. var hostsMap = {};
  164. var popupTitle = this.get('popupTitle');
  165. data.forEach(function (request) {
  166. request.tasks.forEach(function (task) {
  167. var host = task.Tasks.host_name;
  168. if (hostsMap[host]) {
  169. hostsMap[host].logTasks.push(task);
  170. } else {
  171. hostsMap[host] = {
  172. name: task.Tasks.host_name,
  173. publicName: task.Tasks.host_name,
  174. logTasks: [task]
  175. };
  176. }
  177. });
  178. });
  179. for (var host in hostsMap) {
  180. hosts.push(hostsMap[host]);
  181. }
  182. this.set('services', [
  183. {name: popupTitle, hosts: hosts}
  184. ]);
  185. this.set('serviceTimestamp', App.dateTime());
  186. if (!this.isRequestRunning(data)) {
  187. this.removeObserver('progressController.logs.length', this, 'getDataFromProgressController');
  188. }
  189. },
  190. /**
  191. * Get hosts tasks data from <code>progressController</code>
  192. */
  193. getDataFromProgressController: function () {
  194. var data = this.get('hostsData');
  195. var tasksData = [];
  196. var stageId = this.get('stageId');
  197. // If the progress page is broken into stages then update host with only stage's tasks
  198. if (!!stageId) {
  199. tasksData = this.get('progressController.logs').filterProperty('Tasks.stage_id', stageId);
  200. } else {
  201. tasksData = this.get('progressController.logs');
  202. }
  203. if (tasksData.length) {
  204. var tasks = [];
  205. tasksData.forEach(function (logs) {
  206. tasks.pushObjects(logs);
  207. }, this);
  208. data.forEach(function (request) {
  209. tasks = tasks.filterProperty('Tasks.request_id', request.Requests.id);
  210. request.tasks = tasks;
  211. });
  212. this.calculateHostsData(data);
  213. }
  214. },
  215. /**
  216. * Identify whether request is running by task counters
  217. * @param requests {Array}
  218. * @return {Boolean}
  219. */
  220. isRequestRunning: function (requests) {
  221. var result = false;
  222. requests.forEach(function (request) {
  223. if ((request.Requests.task_count -
  224. (request.Requests.aborted_task_count +
  225. request.Requests.completed_task_count +
  226. request.Requests.failed_task_count +
  227. request.Requests.timed_out_task_count -
  228. request.Requests.queued_task_count)) > 0) {
  229. result = true;
  230. }
  231. });
  232. return result;
  233. },
  234. startTaskPolling: function (requestId, taskId) {
  235. this.setProperties({
  236. isTaskPolling: true,
  237. taskInfo: {
  238. id: taskId,
  239. requestId: requestId
  240. }
  241. });
  242. App.updater.run(this, 'updateTask', 'isTaskPolling', App.bgOperationsUpdateInterval);
  243. App.updater.immediateRun('updateTask');
  244. },
  245. stopTaskPolling: function () {
  246. this.set('isTaskPolling', false);
  247. },
  248. updateTask: function (callback) {
  249. App.ajax.send({
  250. name: 'background_operations.get_by_task',
  251. sender: this,
  252. data: {
  253. requestId: this.get('taskInfo.requestId'),
  254. taskId: this.get('taskInfo.id')
  255. },
  256. success: 'updateTaskSuccessCallback',
  257. callback: callback
  258. })
  259. },
  260. updateTaskSuccessCallback: function (data) {
  261. this.setProperties({
  262. 'taskInfo.stderr': data.Tasks.stderr,
  263. 'taskInfo.stdout': data.Tasks.stdout,
  264. 'taskInfo.outputLog': data.Tasks.output_log,
  265. 'taskInfo.errorLog': data.Tasks.error_log,
  266. 'isTaskPolling': !['FAILED', 'COMPLETED', 'TIMEDOUT', 'ABORTED'].contains(data.Tasks.status)
  267. });
  268. }
  269. });