progress_controller.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. App.HighAvailabilityProgressPageController = App.HighAvailabilityWizardController.extend({
  20. name: 'highAvailabilityProgressPageController',
  21. status: 'IN_PROGRESS',
  22. clusterDeployState: 'HIGH_AVAILABILITY_DEPLOY',
  23. tasks: [],
  24. commands: [],
  25. currentRequestIds: [],
  26. logs: [],
  27. currentTaskId: null,
  28. POLL_INTERVAL: 4000,
  29. isSubmitDisabled: true,
  30. serviceTimestamp: null,
  31. isRollback: false,
  32. loadStep: function () {
  33. this.clearStep();
  34. this.initializeTasks();
  35. this.loadTasks();
  36. this.addObserver('tasks.@each.status', this, 'onTaskStatusChange');
  37. this.onTaskStatusChange();
  38. },
  39. clearStep: function () {
  40. this.set('isSubmitDisabled', true);
  41. this.set('tasks', []);
  42. this.set('logs', []);
  43. this.set('currentRequestIds', []);
  44. },
  45. initializeTasks: function() {
  46. var commands = this.get('commands');
  47. var currentStep = App.router.get('highAvailabilityWizardController.currentStep');
  48. for (var i = 0; i < commands.length; i++) {
  49. this.get('tasks').pushObject(Ember.Object.create({
  50. title: Em.I18n.t('admin.highAvailability.wizard.step' + currentStep + '.task' + i + '.title'),
  51. status: 'PENDING',
  52. id: i,
  53. command: commands[i],
  54. showRetry: false,
  55. showRollback: false,
  56. name: Em.I18n.t('admin.highAvailability.wizard.step' + currentStep + '.task' + i + '.title'),
  57. displayName: Em.I18n.t('admin.highAvailability.wizard.step' + currentStep + '.task' + i + '.title'),
  58. progress: 0,
  59. isRunning: false,
  60. hosts: []
  61. }));
  62. }
  63. },
  64. services: function(){
  65. return this.get('tasks');
  66. }.property('tasks'),
  67. loadTasks: function () {
  68. var loadedStauses = this.get('content.tasksStatuses');
  69. var loadedLogs = this.get('content.logs');
  70. if (loadedStauses && loadedLogs && loadedStauses.length === this.get('tasks').length) {
  71. for (var i = 0; i < loadedStauses.length; i++) {
  72. this.setTaskStatus(i, loadedStauses[i]);
  73. this.restoreTaskLog(i, loadedLogs[i]);
  74. }
  75. if (loadedStauses.contains('IN_PROGRESS')) {
  76. this.set('currentRequestIds', this.get('content.requestIds'));
  77. this.set('currentTaskId', loadedStauses.indexOf('IN_PROGRESS'));
  78. this.doPolling();
  79. }else if (loadedStauses.contains('QUEUED')){
  80. this.set('currentTaskId', loadedStauses.indexOf('QUEUED'));
  81. this.runTask(loadedStauses.indexOf('QUEUED'));
  82. }
  83. }
  84. },
  85. setTaskStatus: function (taskId, status) {
  86. this.get('tasks').findProperty('id', taskId).set('status', status);
  87. },
  88. restoreTaskLog: function (taskId, log) {
  89. this.get('tasks').findProperty('id', taskId).set('hosts', log);
  90. },
  91. setTaskLogs: function (taskId, tasks) {
  92. var hosts = [];
  93. var uniqHosts = tasks.mapProperty('Tasks.host_name').uniq();
  94. uniqHosts.forEach(function (host) {
  95. var curHostTasks = tasks.filterProperty('Tasks.host_name', host);
  96. hosts.push(
  97. {
  98. name: host,
  99. publicName: host,
  100. logTasks: curHostTasks
  101. }
  102. );
  103. });
  104. this.get('tasks').findProperty('id', taskId).set('hosts', hosts);
  105. this.set('serviceTimestamp', new Date().getTime());
  106. },
  107. retryTask: function () {
  108. var task = this.get('tasks').findProperty('status', 'FAILED');
  109. task.set('showRetry', false);
  110. task.set('showRollback', false);
  111. task.set('status', 'PENDING');
  112. },
  113. rollback: function () {
  114. var task = this.get('tasks').findProperty('status', 'FAILED');
  115. App.router.get(this.get('content.controllerName')).saveFailedTask(task);
  116. App.ModalPopup.show({
  117. header: Em.I18n.t('admin.highAvailability.confirmRollbackHeader'),
  118. primary: Em.I18n.t('common.confirm'),
  119. showCloseButton: false,
  120. onPrimary: function () {
  121. App.router.get('highAvailabilityWizardController').clearTasksData();
  122. App.router.transitionTo('main.admin.highAvailabilityRollback');
  123. this.hide();
  124. },
  125. secondary : Em.I18n.t('common.cancel'),
  126. onSecondary: function(){
  127. this.hide();
  128. },
  129. body: Em.I18n.t('admin.highAvailability.confirmRollbackBody')
  130. });
  131. },
  132. onTaskStatusChange: function () {
  133. if (!this.get('tasks').someProperty('status', 'IN_PROGRESS') && !this.get('tasks').someProperty('status', 'QUEUED') && !this.get('tasks').someProperty('status', 'FAILED')) {
  134. var nextTask = this.get('tasks').findProperty('status', 'PENDING');
  135. if (nextTask) {
  136. this.set('status', 'IN_PROGRESS');
  137. this.setTaskStatus(nextTask.get('id'), 'QUEUED');
  138. this.set('currentTaskId', nextTask.get('id'));
  139. this.runTask(nextTask.get('id'));
  140. } else {
  141. this.set('status', 'COMPLETED');
  142. this.set('isSubmitDisabled', false);
  143. }
  144. } else if (this.get('tasks').someProperty('status', 'FAILED')) {
  145. this.set('status', 'FAILED');
  146. this.get('tasks').findProperty('status', 'FAILED').set('showRetry', true);
  147. this.get('tasks').findProperty('status', 'FAILED').set('showRollback', true);
  148. }
  149. var statuses = this.get('tasks').mapProperty('status');
  150. var logs = this.get('tasks').mapProperty('hosts');
  151. var requestIds = this.get('currentRequestIds');
  152. App.router.get(this.get('content.controllerName')).saveTasksStatuses(statuses);
  153. App.router.get(this.get('content.controllerName')).saveRequestIds(requestIds);
  154. App.router.get(this.get('content.controllerName')).saveLogs(logs);
  155. App.clusterStatus.setClusterStatus({
  156. clusterName: this.get('content.cluster.name'),
  157. clusterState: this.get('clusterDeployState'),
  158. wizardControllerName: this.get('content.controllerName'),
  159. localdb: App.db.data
  160. });
  161. },
  162. /*
  163. run command of appropriate task
  164. */
  165. runTask: function (taskId) {
  166. this[this.get('tasks').findProperty('id', taskId).get('command')]();
  167. },
  168. onTaskError: function () {
  169. this.setTaskStatus(this.get('currentTaskId'), 'FAILED');
  170. },
  171. onTaskCompleted: function () {
  172. this.setTaskStatus(this.get('currentTaskId'), 'COMPLETED');
  173. },
  174. createComponent: function (componentName, hostName) {
  175. if (!(hostName instanceof Array)) {
  176. hostName = [hostName];
  177. }
  178. var hostComponents = [];
  179. for (var i = 0; i < hostName.length; i++) {
  180. hostComponents = App.HostComponent.find().filterProperty('componentName', componentName);
  181. if (!hostComponents.length || !hostComponents.mapProperty('host.hostName').contains(hostName[i])) {
  182. App.ajax.send({
  183. name: 'admin.high_availability.create_component',
  184. sender: this,
  185. data: {
  186. hostName: hostName[i],
  187. componentName: componentName,
  188. taskNum: hostName.length
  189. },
  190. success: 'onCreateComponent',
  191. error: 'onTaskError'
  192. });
  193. } else {
  194. var taskNum = hostName.length;
  195. this.installComponent(componentName, hostName[i], taskNum);
  196. }
  197. }
  198. },
  199. onCreateComponent: function () {
  200. var hostName = arguments[2].hostName;
  201. var componentName = arguments[2].componentName;
  202. var taskNum = arguments[2].taskNum;
  203. this.installComponent(componentName, hostName, taskNum);
  204. },
  205. installComponent: function (componentName, hostName, taskNum) {
  206. if (!(hostName instanceof Array)) {
  207. hostName = [hostName];
  208. }
  209. for (var i = 0; i < hostName.length; i++) {
  210. App.ajax.send({
  211. name: 'admin.high_availability.install_component',
  212. sender: this,
  213. data: {
  214. hostName: hostName[i],
  215. componentName: componentName,
  216. displayName: App.format.role(componentName),
  217. taskNum: taskNum || hostName.length
  218. },
  219. success: 'startPolling',
  220. error: 'onTaskError'
  221. });
  222. }
  223. },
  224. startComponent: function (componentName, hostName) {
  225. if (!(hostName instanceof Array)) {
  226. hostName = [hostName];
  227. }
  228. for (var i = 0; i < hostName.length; i++) {
  229. App.ajax.send({
  230. name: 'admin.high_availability.start_component',
  231. sender: this,
  232. data: {
  233. hostName: hostName[i],
  234. componentName: componentName,
  235. displayName: App.format.role(componentName),
  236. taskNum: hostName.length
  237. },
  238. success: 'startPolling',
  239. error: 'onTaskError'
  240. });
  241. }
  242. },
  243. startPolling: function (data) {
  244. if (data) {
  245. this.get('currentRequestIds').push(data.Requests.id);
  246. var tasksCount = arguments[2].taskNum || 1;
  247. if (tasksCount === this.get('currentRequestIds').length) {
  248. this.doPolling();
  249. }
  250. } else {
  251. this.onTaskCompleted();
  252. }
  253. },
  254. doPolling: function () {
  255. this.setTaskStatus(this.get('currentTaskId'), 'IN_PROGRESS');
  256. var requestIds = this.get('currentRequestIds');
  257. for (var i = 0; i < requestIds.length; i++) {
  258. App.ajax.send({
  259. name: 'admin.high_availability.polling',
  260. sender: this,
  261. data: {
  262. requestId: requestIds[i]
  263. },
  264. success: 'parseLogs',
  265. error: 'onTaskError'
  266. });
  267. }
  268. },
  269. parseLogs: function (logs) {
  270. this.get('logs').push(logs.tasks);
  271. if (this.get('currentRequestIds').length === this.get('logs').length) {
  272. var tasks = [];
  273. this.get('logs').forEach(function (logs) {
  274. tasks.pushObjects(logs);
  275. }, this);
  276. var self = this;
  277. var currentTaskId = this.get('currentTaskId');
  278. this.setTaskLogs(currentTaskId, tasks);
  279. if (!tasks.someProperty('Tasks.status', 'PENDING') && !tasks.someProperty('Tasks.status', 'QUEUED') && !tasks.someProperty('Tasks.status', 'IN_PROGRESS')) {
  280. this.set('currentRequestIds', []);
  281. if (tasks.someProperty('Tasks.status', 'FAILED') || tasks.someProperty('status', 'TIMEDOUT') || tasks.someProperty('status', 'ABORTED')) {
  282. this.setTaskStatus(currentTaskId, 'FAILED');
  283. } else {
  284. this.setTaskStatus(currentTaskId, 'COMPLETED');
  285. }
  286. } else {
  287. var actionsPerHost = tasks.length;
  288. var completedActions = tasks.filterProperty('Tasks.status', 'COMPLETED').length
  289. + tasks.filterProperty('Tasks.status', 'FAILED').length
  290. + tasks.filterProperty('Tasks.status', 'ABORTED').length
  291. + tasks.filterProperty('Tasks.status', 'TIMEDOUT').length;
  292. var queuedActions = tasks.filterProperty('Tasks.status', 'QUEUED').length;
  293. var inProgressActions = tasks.filterProperty('Tasks.status', 'IN_PROGRESS').length;
  294. var progress = Math.ceil(((queuedActions * 0.09) + (inProgressActions * 0.35) + completedActions ) / actionsPerHost * 100);
  295. this.get('tasks').findProperty('id', currentTaskId).set('progress', progress);
  296. window.setTimeout(function () {
  297. self.doPolling()
  298. }, self.POLL_INTERVAL);
  299. }
  300. this.set('logs', []);
  301. }
  302. },
  303. done: function () {
  304. if (!this.get('isSubmitDisabled')) {
  305. this.removeObserver('tasks.@each.status', this, 'onTaskStatusChange');
  306. App.router.send('next');
  307. }
  308. }
  309. });