wizardProgressPageController.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  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 componentsUtils = require('utils/components');
  20. /**
  21. * Mixin for wizard controller for showing command progress on wizard pages
  22. * This should
  23. * @type {Ember.Mixin}
  24. */
  25. App.wizardProgressPageControllerMixin = Em.Mixin.create({
  26. controllerName: '',
  27. clusterDeployState: 'WIZARD_DEPLOY',
  28. status: 'IN_PROGRESS',
  29. tasks: [],
  30. commands: [],
  31. currentRequestIds: [], //todo: replace with using requestIds from tasks
  32. logs: [],
  33. currentTaskId: null,
  34. POLL_INTERVAL: 4000,
  35. isSubmitDisabled: true,
  36. isBackButtonDisabled: true,
  37. stages: [],
  38. /**
  39. * List of statuses that inform about the end of request progress.
  40. * @type {String[]}
  41. */
  42. completedStatuses: ['COMPLETED', 'FAILED', 'TIMEDOUT', 'ABORTED'],
  43. currentPageRequestId: null,
  44. isSingleRequestPage: false,
  45. isCommandLevelRetry: function () {
  46. return !this.get('isSingleRequestPage');
  47. }.property('isSingleRequestPage'),
  48. showRetry: false,
  49. /**
  50. * Show whether tasks data was loaded
  51. * @type {Boolean}
  52. */
  53. isLoading: false,
  54. k: Em.K,
  55. /**
  56. * tasksMessagesPrefix should be overloaded by any controller including the mixin
  57. */
  58. tasksMessagesPrefix: '',
  59. loadStep: function () {
  60. this.clearStep();
  61. var self = this;
  62. if (!self.isSingleRequestPage) {
  63. this.initStep();
  64. } else {
  65. var requestIds = this.get('content.tasksRequestIds');
  66. var currentRequestId = requestIds && requestIds[0][0];
  67. if (!currentRequestId) {
  68. this.set('isLoaded', false);
  69. this.submitRequest();
  70. } else {
  71. self.set('currentPageRequestId', currentRequestId);
  72. self.doPollingForPageRequest();
  73. }
  74. }
  75. },
  76. initStep: function () {
  77. this.initializeTasks();
  78. if (!this.isSingleRequestPage) {
  79. this.loadTasks();
  80. }
  81. this.addObserver('tasks.@each.status', this, 'onTaskStatusChange');
  82. if (this.isSingleRequestPage) {
  83. var dfd = $.Deferred();
  84. var dfdObject = {
  85. deferred: dfd,
  86. isJqueryPromise: true
  87. };
  88. this.onTaskStatusChange(dfdObject);
  89. return dfd.promise();
  90. } else {
  91. this.onTaskStatusChange();
  92. }
  93. },
  94. clearStep: function () {
  95. this.removeObserver('tasks.@each.status', this, 'onTaskStatusChange');
  96. this.set('isSubmitDisabled', true);
  97. this.set('isBackButtonDisabled', true);
  98. this.set('tasks', []);
  99. this.set('currentRequestIds', []);
  100. this.set('isLoaded', false);
  101. },
  102. /**
  103. * Clear stages info for single page request.
  104. */
  105. clearStage: function() {
  106. this.setDBProperty('tasksRequestIds', null);
  107. this.setDBProperty('tasksStatuses', null);
  108. this.set('showRetry', false);
  109. this.set('content.tasksRequestIds', null);
  110. this.set('content.tasksStatuses', null);
  111. this.set('content.currentTaskId', null);
  112. this.get('stages').clear();
  113. },
  114. retry: function () {
  115. this.set('showRetry', false);
  116. this.get('tasks').setEach('status','PENDING');
  117. this.loadStep();
  118. },
  119. submitRequest: function () {
  120. var self = this;
  121. return App.ajax.send({
  122. name: this.get('request.ajaxName'),
  123. data: this.get('request.ajaxData'),
  124. sender: this,
  125. error: 'onSingleRequestError',
  126. success: 'submitRequestSuccess',
  127. kdcCancelHandler: function() {
  128. self.set('status', 'FAILED');
  129. self.set('isLoaded', true);
  130. self.set('showRetry', true);
  131. }
  132. });
  133. },
  134. submitRequestSuccess: function(data, result, request) {
  135. if (data) {
  136. this.set('currentPageRequestId', data.Requests.id);
  137. this.doPollingForPageRequest();
  138. } else {
  139. //Step has been successfully completed
  140. if (request.status === 200) {
  141. this.set('status', 'COMPLETED');
  142. this.set('isSubmitDisabled', false);
  143. this.set('isLoaded', true);
  144. }
  145. }
  146. },
  147. doPollingForPageRequest: function () {
  148. App.ajax.send({
  149. name: 'admin.poll.kerberize.cluster.request',
  150. sender: this,
  151. data: {
  152. requestId: this.get('currentPageRequestId')
  153. },
  154. success: 'initializeStages'
  155. });
  156. },
  157. initializeStages: function (data) {
  158. var self = this;
  159. var stages = [];
  160. this.set('logs', []);
  161. data.stages.forEach(function (_stage) {
  162. stages.pushObject(Em.Object.create(_stage.Stage));
  163. }, this);
  164. if (!this.get('stages').length) {
  165. this.get('stages').pushObjects(stages);
  166. this.initStep().done(function(){
  167. self.updatePageWithPolledData(data);
  168. });
  169. } else {
  170. this.updatePageWithPolledData(data);
  171. }
  172. },
  173. updatePageWithPolledData: function(data) {
  174. // If all tasks completed no need to update each task status.
  175. // Preferable to skip polling of data for completed tasks after page refresh.
  176. if (this.get('status') === 'COMPLETED') return;
  177. var self = this;
  178. var tasks = [];
  179. var currentPageRequestId = this.get('currentPageRequestId');
  180. var currentTaskId = this.get('currentTaskId');
  181. var currentTask = this.get('tasks').findProperty('id', currentTaskId);
  182. var currentStage = data.stages.findProperty('Stage.stage_id', currentTask.get('stageId'));
  183. var tasksInCurrentStage = currentStage.tasks;
  184. this.set('logs',tasksInCurrentStage);
  185. this.setRequestIds(this.get('currentTaskId'), [this.get('currentPageRequestId')]);
  186. if (!tasksInCurrentStage.someProperty('Tasks.status', 'PENDING') && !tasksInCurrentStage.someProperty('Tasks.status', 'QUEUED') && !tasksInCurrentStage.someProperty('Tasks.status', 'IN_PROGRESS')) {
  187. this.set('currentRequestIds', []);
  188. if (tasksInCurrentStage.someProperty('Tasks.status', 'FAILED') || tasksInCurrentStage.someProperty('Tasks.status', 'TIMEDOUT') || tasksInCurrentStage.someProperty('Tasks.status', 'ABORTED')) {
  189. this.setTaskStatus(currentTaskId, 'FAILED');
  190. } else {
  191. this.setTaskStatus(currentTaskId, 'COMPLETED');
  192. }
  193. } else {
  194. var completedActions = tasksInCurrentStage.filterProperty('Tasks.status', 'COMPLETED').length
  195. + tasksInCurrentStage.filterProperty('Tasks.status', 'FAILED').length
  196. + tasksInCurrentStage.filterProperty('Tasks.status', 'ABORTED').length
  197. + tasksInCurrentStage.filterProperty('Tasks.status', 'TIMEDOUT').length;
  198. var queuedActions = tasksInCurrentStage.filterProperty('Tasks.status', 'QUEUED').length;
  199. var inProgressActions = tasksInCurrentStage.filterProperty('Tasks.status', 'IN_PROGRESS').length;
  200. var progress = Math.floor(((queuedActions * 0.09) + (inProgressActions * 0.35) + completedActions ) / tasksInCurrentStage.length * 100);
  201. this.get('tasks').findProperty('id', currentTaskId).set('progress', progress);
  202. }
  203. // start polling if current request not completed
  204. if (!(this.get('completedStatuses').contains(this.get('status')))) {
  205. window.setTimeout(function () {
  206. self.doPollingForPageRequest();
  207. }, self.POLL_INTERVAL);
  208. }
  209. },
  210. initializeTasks: function () {
  211. var self = this;
  212. var commands = this.isSingleRequestPage ? this.get('stages') : this.get('commands');
  213. var currentStep = App.router.get(this.get('content.controllerName') + '.currentStep');
  214. var tasksMessagesPrefix = this.get('tasksMessagesPrefix');
  215. // check that all stages have been completed for single request type
  216. var allStagesCompleted = commands.everyProperty('status', 'COMPLETED');
  217. for (var i = 0; i < commands.length; i++) {
  218. this.get('tasks').pushObject(Ember.Object.create({
  219. title: self.isSingleRequestPage ? commands[i].get('context') : Em.I18n.t(tasksMessagesPrefix + currentStep + '.task' + i + '.title'),
  220. // set COMPLETED status for task if all stages completed successfully
  221. status: allStagesCompleted ? 'COMPLETED' : 'PENDING',
  222. id: i,
  223. stageId: self.isSingleRequestPage ? commands[i].get('stage_id') : null,
  224. command: self.isSingleRequestPage ? 'k' : commands[i],
  225. showRetry: false,
  226. showRollback: false,
  227. name: self.isSingleRequestPage ? commands[i].get('context') : Em.I18n.t(tasksMessagesPrefix + currentStep + '.task' + i + '.title'),
  228. displayName: self.isSingleRequestPage ? commands[i].get('context') : Em.I18n.t(tasksMessagesPrefix + currentStep + '.task' + i + '.title'),
  229. progress: 0,
  230. isRunning: false,
  231. requestIds: self.isSingleRequestPage ? [this.get('stages')[0].request_id] : []
  232. }));
  233. }
  234. this.set('isLoaded', true);
  235. },
  236. loadTasks: function () {
  237. var self = this;
  238. var loadedStatuses = this.get('content.tasksStatuses');
  239. var loadedRequestIds = this.get('content.tasksRequestIds');
  240. if (loadedStatuses && loadedStatuses.length === this.get('tasks').length) {
  241. this.get('tasks').forEach(function (task, i) {
  242. self.setTaskStatus(task.get('id'), loadedStatuses[i]);
  243. self.setRequestIds(task.get('id'), loadedRequestIds[i]);
  244. });
  245. if (loadedStatuses.contains('IN_PROGRESS')) {
  246. var curTaskId = this.get('tasks')[loadedStatuses.indexOf('IN_PROGRESS')].get('id');
  247. this.set('currentRequestIds', this.get('content.requestIds'));
  248. this.set('currentTaskId', curTaskId);
  249. this.doPolling();
  250. } else if (loadedStatuses.contains('QUEUED')) {
  251. var curTaskId = this.get('tasks')[loadedStatuses.indexOf('QUEUED')].get('id');
  252. this.set('currentTaskId', curTaskId);
  253. this.runTask(curTaskId);
  254. }
  255. }
  256. },
  257. setTaskStatus: function (taskId, status) {
  258. this.get('tasks').findProperty('id', taskId).set('status', status);
  259. },
  260. setTaskCanSkip: function (taskId, canSkip) {
  261. this.get('tasks').findProperty('id', taskId).set('canSkip', true);
  262. },
  263. setRequestIds: function (taskId, requestIds) {
  264. this.get('tasks').findProperty('id', taskId).set('requestIds', requestIds);
  265. },
  266. retryTask: function () {
  267. var task = this.get('tasks').findProperty('status', 'FAILED');
  268. task.set('showRetry', false);
  269. task.set('showRollback', false);
  270. task.set('status', 'PENDING');
  271. },
  272. onTaskStatusChange: function (dfdObject) {
  273. var statuses = this.get('tasks').mapProperty('status');
  274. var tasksRequestIds = this.get('tasks').mapProperty('requestIds');
  275. var requestIds = this.get('currentRequestIds');
  276. // save task info
  277. App.router.get(this.get('content.controllerName')).saveTasksStatuses(statuses);
  278. App.router.get(this.get('content.controllerName')).saveTasksRequestIds(tasksRequestIds);
  279. App.router.get(this.get('content.controllerName')).saveRequestIds(requestIds);
  280. // call saving of cluster status asynchronous
  281. // synchronous executing cause problems in Firefox
  282. var successCallbackData;
  283. if (dfdObject && dfdObject.isJqueryPromise) {
  284. successCallbackData = {deferred: dfdObject.deferred};
  285. }
  286. App.clusterStatus.setClusterStatus({
  287. clusterName: App.router.getClusterName(),
  288. clusterState: this.get('clusterDeployState'),
  289. wizardControllerName: this.get('content.controllerName'),
  290. localdb: App.db.data
  291. }, {successCallback: this.statusChangeCallback, sender: this, successCallbackData: successCallbackData});
  292. },
  293. /**
  294. * Method that called after saving persist data to server.
  295. * Switch task according its status.
  296. */
  297. statusChangeCallback: function (data) {
  298. if (!this.get('tasks').someProperty('status', 'IN_PROGRESS') && !this.get('tasks').someProperty('status', 'QUEUED') && !this.get('tasks').someProperty('status', 'FAILED')) {
  299. var nextTask = this.get('tasks').findProperty('status', 'PENDING');
  300. if (nextTask) {
  301. this.set('status', 'IN_PROGRESS');
  302. var taskStatus = this.isSingleRequestPage ? 'IN_PROGRESS' : 'QUEUED';
  303. this.setTaskStatus(nextTask.get('id'), taskStatus);
  304. this.set('currentTaskId', nextTask.get('id'));
  305. this.runTask(nextTask.get('id'));
  306. } else {
  307. this.set('status', 'COMPLETED');
  308. this.set('isSubmitDisabled', false);
  309. this.set('isBackButtonDisabled', false);
  310. }
  311. } else if (this.get('tasks').someProperty('status', 'FAILED')) {
  312. this.set('status', 'FAILED');
  313. this.set('isBackButtonDisabled', false);
  314. if (this.get('isCommandLevelRetry')) {
  315. this.get('tasks').findProperty('status', 'FAILED').set('showRetry', true);
  316. } else {
  317. this.set('showRetry', true);
  318. }
  319. if (this.get('tasks').someProperty('canSkip', true)) {
  320. this.get('tasks').findProperty('canSkip', true).set('showSkip', true);
  321. }
  322. if (App.supports.autoRollbackHA) {
  323. this.get('tasks').findProperty('status', 'FAILED').set('showRollback', true);
  324. }
  325. }
  326. this.get('tasks').filterProperty('status', 'COMPLETED').setEach('showRetry', false);
  327. this.get('tasks').filterProperty('status', 'COMPLETED').setEach('showRollback', false);
  328. this.get('tasks').filterProperty('status', 'COMPLETED').setEach('showSkip', false);
  329. this.get('tasks').filterProperty('status', 'IN_PROGRESS').setEach('showSkip', false);
  330. if (data && data.deferred) {
  331. data.deferred.resolve();
  332. }
  333. },
  334. /**
  335. * Run command of appropriate task
  336. */
  337. runTask: function (taskId) {
  338. this[this.get('tasks').findProperty('id', taskId).get('command')]();
  339. },
  340. onTaskError: function () {
  341. this.setTaskStatus(this.get('currentTaskId'), 'FAILED');
  342. },
  343. onTaskErrorWithSkip: function () {
  344. this.onTaskError();
  345. this.setTaskCanSkip(this.get('currentTaskId'), true);
  346. },
  347. onSingleRequestError: function (jqXHR, ajaxOptions, error, opt) {
  348. App.ajax.defaultErrorHandler(jqXHR, opt.url, opt.method, jqXHR.status);
  349. this.set('status', 'FAILED');
  350. this.set('isLoaded', true);
  351. this.set('showRetry', true);
  352. },
  353. onTaskCompleted: function () {
  354. this.setTaskStatus(this.get('currentTaskId'), 'COMPLETED');
  355. },
  356. /**
  357. * check whether component installed on specified hosts
  358. * @param {string} componentName
  359. * @param {string[]} hostNames
  360. * @return {$.ajax}
  361. */
  362. checkInstalledComponents: function (componentName, hostNames) {
  363. return App.ajax.send({
  364. name: 'host_component.installed.on_hosts',
  365. sender: this,
  366. data: {
  367. componentName: componentName,
  368. hostNames: hostNames.join(',')
  369. }
  370. });
  371. },
  372. /**
  373. * make server call to stop all services, except <code>excludedServices</code>
  374. * @param excludedServices
  375. * @returns {$.ajax}
  376. */
  377. stopServices: function (excludedServices) {
  378. var data = {
  379. 'ServiceInfo': {
  380. 'state': 'INSTALLED'
  381. }
  382. };
  383. if (excludedServices && excludedServices.length) {
  384. var servicesList = App.Service.find().mapProperty("serviceName").filter(function (s) {
  385. return !excludedServices.contains(s)
  386. }).join(',');
  387. data.context = "Stop required services";
  388. data.urlParams = "ServiceInfo/service_name.in(" + servicesList + ")";
  389. } else {
  390. data.context = "Stop all services";
  391. }
  392. return App.ajax.send({
  393. name: 'common.services.update',
  394. sender: this,
  395. data: data,
  396. success: 'startPolling',
  397. error: 'onTaskError'
  398. });
  399. },
  400. /**
  401. * make server call to start all services, except <code>excludedServices</code>
  402. * and run smoke tests if <code>runSmokeTest</code> is true
  403. * @param runSmokeTest
  404. * @param excludedServices
  405. * @returns {$.ajax}
  406. */
  407. startServices: function (runSmokeTest, excludedServices) {
  408. var skipServiceCheck = App.router.get('clusterController.ambariProperties')['skip.service.checks'] === "true";
  409. var data = {
  410. 'ServiceInfo': {
  411. 'state': 'STARTED'
  412. }
  413. };
  414. if (excludedServices && excludedServices.length) {
  415. var servicesList = App.Service.find().mapProperty("serviceName").filter(function (s) {
  416. return !excludedServices.contains(s)
  417. }).join(',');
  418. data.context = "Start required services";
  419. data.urlParams = "ServiceInfo/service_name.in(" + servicesList + ")";
  420. } else {
  421. data.context = "Start all services";
  422. }
  423. if (runSmokeTest) {
  424. data.urlParams = data.urlParams ? data.urlParams + '&' : '';
  425. data.urlParams += 'params/run_smoke_test=' + !skipServiceCheck;
  426. }
  427. return App.ajax.send({
  428. name: 'common.services.update',
  429. sender: this,
  430. data: data,
  431. success: 'startPolling',
  432. error: 'onTaskError'
  433. });
  434. },
  435. /**
  436. * Create component on single or multiple hosts.
  437. *
  438. * @method createComponent
  439. * @param {string} componentName - name of the component
  440. * @param {(string|string[])} hostName - host/hosts where components should be installed
  441. * @param {string} serviceName - name of the services
  442. */
  443. createComponent: function (componentName, hostName, serviceName) {
  444. var hostNames = (Array.isArray(hostName)) ? hostName : [hostName];
  445. var self = this;
  446. this.set('showRetry', false);
  447. this.checkInstalledComponents(componentName, hostNames).then(function (data) {
  448. var hostsWithComponents = data.items.mapProperty('HostRoles.host_name');
  449. var result = hostNames.map(function(item) {
  450. return {
  451. componentName: componentName,
  452. hostName: item,
  453. hasComponent: hostsWithComponents.contains(item)
  454. };
  455. });
  456. var hostsWithoutComponents = result.filterProperty('hasComponent', false).mapProperty('hostName');
  457. var taskNum = 1;
  458. var requestData = {
  459. "RequestInfo": {
  460. "query": hostsWithoutComponents.map(function(item) {
  461. return 'Hosts/host_name=' + item;
  462. }).join('|')
  463. },
  464. "Body": {
  465. "host_components": [
  466. {
  467. "HostRoles": {
  468. "component_name": componentName
  469. }
  470. }
  471. ]
  472. }
  473. };
  474. if (!!hostsWithoutComponents.length) {
  475. componentsUtils.updateAndCreateServiceComponent(componentName).done(function () {
  476. App.ajax.send({
  477. name: 'wizard.step8.register_host_to_component',
  478. sender: self,
  479. data: {
  480. data: JSON.stringify(requestData),
  481. hostName: result.mapProperty('hostName'),
  482. componentName: componentName,
  483. serviceName: serviceName,
  484. taskNum: taskNum,
  485. cluster: App.get('clusterName')
  486. },
  487. success: 'onCreateComponent',
  488. error: 'onCreateComponent'
  489. });
  490. });
  491. } else {
  492. self.onCreateComponent(null, null, {
  493. hostName: result.mapProperty('hostName'),
  494. componentName: componentName,
  495. serviceName: serviceName,
  496. taskNum: taskNum
  497. }, self);
  498. }
  499. });
  500. },
  501. onCreateComponent: function () {
  502. var hostName = arguments[2].hostName;
  503. var componentName = arguments[2].componentName;
  504. var taskNum = arguments[2].taskNum;
  505. var serviceName = arguments[2].serviceName;
  506. this.updateComponent(componentName, hostName, serviceName, "Install", taskNum);
  507. },
  508. onCreateComponentError: function (error) {
  509. if (error.responseText.indexOf('org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException') !== -1) {
  510. this.onCreateComponent();
  511. } else {
  512. this.onTaskError();
  513. }
  514. },
  515. /**
  516. * Update component status on selected hosts.
  517. *
  518. * @param {string} componentName
  519. * @param {(string|string[])} hostName
  520. * @param {string} serviceName
  521. * @param {string} context
  522. * @param {number} taskNum
  523. * @returns {$.ajax}
  524. */
  525. updateComponent: function (componentName, hostName, serviceName, context, taskNum) {
  526. if (!(hostName instanceof Array)) {
  527. hostName = [hostName];
  528. }
  529. var state = context.toLowerCase() == "start" ? "STARTED" : "INSTALLED";
  530. return App.ajax.send({
  531. name: 'common.host_components.update',
  532. sender: this,
  533. data: {
  534. HostRoles: {
  535. state: state
  536. },
  537. query: 'HostRoles/component_name=' + componentName + '&HostRoles/host_name.in(' + hostName.join(',') + ')&HostRoles/maintenance_state=OFF',
  538. context: context + " " + App.format.role(componentName),
  539. hostName: hostName,
  540. taskNum: taskNum || 1,
  541. componentName: componentName,
  542. serviceName: serviceName
  543. },
  544. success: 'startPolling',
  545. error: 'onTaskError'
  546. });
  547. },
  548. startPolling: function (data) {
  549. if (data) {
  550. this.get('currentRequestIds').push(data.Requests.id);
  551. var tasksCount = arguments[2].taskNum || 1;
  552. if (tasksCount === this.get('currentRequestIds').length) {
  553. this.setRequestIds(this.get('currentTaskId'), this.get('currentRequestIds'));
  554. this.doPolling();
  555. }
  556. } else {
  557. this.onTaskCompleted();
  558. }
  559. },
  560. doPolling: function () {
  561. this.setTaskStatus(this.get('currentTaskId'), 'IN_PROGRESS');
  562. var requestIds = this.get('currentRequestIds');
  563. this.set('logs', []);
  564. for (var i = 0; i < requestIds.length; i++) {
  565. App.ajax.send({
  566. name: 'background_operations.get_by_request',
  567. sender: this,
  568. data: {
  569. requestId: requestIds[i]
  570. },
  571. success: 'parseLogs',
  572. error: 'onTaskError'
  573. });
  574. }
  575. },
  576. parseLogs: function (logs) {
  577. this.get('logs').pushObject(logs.tasks);
  578. if (this.get('currentRequestIds').length === this.get('logs').length) {
  579. var tasks = [];
  580. this.get('logs').forEach(function (logs) {
  581. tasks.pushObjects(logs);
  582. }, this);
  583. var self = this;
  584. var currentTaskId = this.get('currentTaskId');
  585. if (!tasks.someProperty('Tasks.status', 'PENDING') && !tasks.someProperty('Tasks.status', 'QUEUED') && !tasks.someProperty('Tasks.status', 'IN_PROGRESS')) {
  586. this.set('currentRequestIds', []);
  587. if (tasks.someProperty('Tasks.status', 'FAILED') || tasks.someProperty('Tasks.status', 'TIMEDOUT') || tasks.someProperty('Tasks.status', 'ABORTED')) {
  588. this.setTaskStatus(currentTaskId, 'FAILED');
  589. } else {
  590. this.setTaskStatus(currentTaskId, 'COMPLETED');
  591. }
  592. } else {
  593. var actionsPerHost = tasks.length;
  594. var completedActions = tasks.filterProperty('Tasks.status', 'COMPLETED').length
  595. + tasks.filterProperty('Tasks.status', 'FAILED').length
  596. + tasks.filterProperty('Tasks.status', 'ABORTED').length
  597. + tasks.filterProperty('Tasks.status', 'TIMEDOUT').length;
  598. var queuedActions = tasks.filterProperty('Tasks.status', 'QUEUED').length;
  599. var inProgressActions = tasks.filterProperty('Tasks.status', 'IN_PROGRESS').length;
  600. var progress = Math.floor(((queuedActions * 0.09) + (inProgressActions * 0.35) + completedActions ) / actionsPerHost * 100);
  601. this.get('tasks').findProperty('id', currentTaskId).set('progress', progress);
  602. window.setTimeout(function () {
  603. self.doPolling();
  604. }, self.POLL_INTERVAL);
  605. }
  606. }
  607. },
  608. showHostProgressPopup: function (event) {
  609. if (!['IN_PROGRESS', 'FAILED', 'COMPLETED'].contains(Em.get(event.context, 'status')) || !event.contexts[0].requestIds.length) {
  610. return;
  611. }
  612. var popupTitle = event.contexts[0].title,
  613. requestIds = event.contexts[0].requestIds,
  614. stageId = event.contexts[0].stageId,
  615. hostProgressPopupController = App.router.get('highAvailabilityProgressPopupController');
  616. hostProgressPopupController.initPopup(popupTitle, requestIds, this, true, stageId);
  617. },
  618. done: function () {
  619. if (!this.get('isSubmitDisabled')) {
  620. this.removeObserver('tasks.@each.status', this, 'onTaskStatusChange');
  621. App.router.send('next');
  622. }
  623. },
  624. back: function () {
  625. if (!this.get('isBackButtonDisabled')) {
  626. this.removeObserver('tasks.@each.status', this, 'onTaskStatusChange');
  627. App.router.send('back');
  628. }
  629. }
  630. });