/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var App = require('app'); App.HighAvailabilityProgressPageController = App.HighAvailabilityWizardController.extend({ name: 'highAvailabilityProgressPageController', status: 'IN_PROGRESS', clusterDeployState: 'HIGH_AVAILABILITY_DEPLOY', tasks: [], commands: [], currentRequestIds: [], logs: [], currentTaskId: null, POLL_INTERVAL: 4000, isSubmitDisabled: true, serviceTimestamp: null, isRollback: false, loadStep: function () { console.warn('func: loadStep'); this.clearStep(); this.initializeTasks(); this.loadTasks(); this.addObserver('tasks.@each.status', this, 'onTaskStatusChange'); this.onTaskStatusChange(); }, clearStep: function () { console.warn('func: clearStep'); this.set('isSubmitDisabled', true); this.set('tasks', []); this.set('logs', []); this.set('currentRequestIds', []); }, initializeTasks: function() { console.warn('func: initializeTasks'); var commands = this.get('commands'); var currentStep = App.router.get('highAvailabilityWizardController.currentStep'); for (var i = 0; i < commands.length; i++) { this.get('tasks').pushObject(Ember.Object.create({ title: Em.I18n.t('admin.highAvailability.wizard.step' + currentStep + '.task' + i + '.title'), status: 'PENDING', id: i, command: commands[i], showRetry: false, showRollback: false, name: Em.I18n.t('admin.highAvailability.wizard.step' + currentStep + '.task' + i + '.title'), displayName: Em.I18n.t('admin.highAvailability.wizard.step' + currentStep + '.task' + i + '.title'), progress: 0, isRunning: false, hosts: [] })); } }, services: function(){ return this.get('tasks'); }.property('tasks'), loadTasks: function () { console.warn('func: loadTasks'); var self = this; var loadedStauses = this.get('content.tasksStatuses'); var loadedLogs = this.get('content.logs'); if (loadedStauses && loadedLogs && loadedStauses.length === this.get('tasks').length) { this.get('tasks').forEach(function(task,i){ self.setTaskStatus(task.get('id'), loadedStauses[i]); self.restoreTaskLog(task.get('id'), loadedLogs[i]); }); if (loadedStauses.contains('IN_PROGRESS')) { var curTaskId = this.get('tasks')[loadedStauses.indexOf('IN_PROGRESS')].get('id'); this.set('currentRequestIds', this.get('content.requestIds')); this.set('currentTaskId', curTaskId); this.doPolling(); }else if (loadedStauses.contains('QUEUED')){ var curTaskId = this.get('tasks')[loadedStauses.indexOf('QUEUED')].get('id'); this.set('currentTaskId', curTaskId); this.runTask(curTaskId); } } }, setTaskStatus: function (taskId, status) { console.warn('func: setTaskStatus'); this.get('tasks').findProperty('id', taskId).set('status', status); }, restoreTaskLog: function (taskId, log) { console.warn('func: restoreTaskLog'); this.get('tasks').findProperty('id', taskId).set('hosts', log); }, setTaskLogs: function (taskId, tasks) { console.warn('func: setTaskLogs'); var hosts = []; var uniqHosts = tasks.mapProperty('Tasks.host_name').uniq(); uniqHosts.forEach(function (host) { var curHostTasks = tasks.filterProperty('Tasks.host_name', host); hosts.push( { name: host, publicName: host, logTasks: curHostTasks } ); }); this.get('tasks').findProperty('id', taskId).set('hosts', hosts); this.set('serviceTimestamp', new Date().getTime()); }, retryTask: function () { console.warn('func: retryTask'); var task = this.get('tasks').findProperty('status', 'FAILED'); task.set('showRetry', false); task.set('showRollback', false); task.set('status', 'PENDING'); }, manualRollback: function () { console.warn('func: manualRollback'); App.ModalPopup.show({ header: Em.I18n.t('admin.highAvailability.confirmRollbackHeader'), primary: Em.I18n.t('yes'), showCloseButton: false, onPrimary: function () { var controller = App.router.get('highAvailabilityWizardController'); controller.clearTasksData(); controller.clearStorageData(); controller.setCurrentStep('1'); App.router.get('updateController').set('isWorking', true); App.clusterStatus.setClusterStatus({ clusterName: App.router.get('content.cluster.name'), clusterState: 'DEFAULT', wizardControllerName: App.router.get('highAvailabilityRollbackController.name'), localdb: App.db.data }); this.hide(); App.router.transitionTo('main.admin.index'); location.reload(); }, secondary : Em.I18n.t('no'), onSecondary: function(){ this.hide(); }, bodyClass: Ember.View.extend({ template: Ember.Handlebars.compile( Em.I18n.t('admin.highAvailability.confirmManualRollbackBody')) }) }); }, rollback: function () { console.warn('func: rollback'); var task = this.get('tasks').findProperty('status', 'FAILED'); App.router.get(this.get('content.controllerName')).saveFailedTask(task); App.ModalPopup.show({ header: Em.I18n.t('admin.highAvailability.confirmRollbackHeader'), primary: Em.I18n.t('common.confirm'), showCloseButton: false, onPrimary: function () { App.router.get('highAvailabilityWizardController').clearTasksData(); App.router.transitionTo('main.admin.highAvailabilityRollback'); this.hide(); }, secondary : Em.I18n.t('common.cancel'), onSecondary: function(){ this.hide(); }, body: Em.I18n.t('admin.highAvailability.confirmRollbackBody') }); }, onTaskStatusChange: function () { console.warn('func: onTaskStatusChange1'); if (!this.get('tasks').someProperty('status', 'IN_PROGRESS') && !this.get('tasks').someProperty('status', 'QUEUED') && !this.get('tasks').someProperty('status', 'FAILED')) { var nextTask = this.get('tasks').findProperty('status', 'PENDING'); if (nextTask) { console.warn('func: onTaskStatusChange2'); this.set('status', 'IN_PROGRESS'); this.setTaskStatus(nextTask.get('id'), 'QUEUED'); this.set('currentTaskId', nextTask.get('id')); this.runTask(nextTask.get('id')); } else { console.warn('func: onTaskStatusChange3'); this.set('status', 'COMPLETED'); this.set('isSubmitDisabled', false); } } else if (this.get('tasks').someProperty('status', 'FAILED')) { console.warn('func: onTaskStatusChange4'); this.set('status', 'FAILED'); this.get('tasks').findProperty('status', 'FAILED').set('showRetry', true); if(App.supports.autoRollbackHA){ this.get('tasks').findProperty('status', 'FAILED').set('showRollback', true); } } this.get('tasks').filterProperty('status','COMPLETED').setEach('showRetry', false); this.get('tasks').filterProperty('status','COMPLETED').setEach('showRollback', false); var statuses = this.get('tasks').mapProperty('status'); var logs = this.get('tasks').mapProperty('hosts'); var requestIds = this.get('currentRequestIds'); console.warn('func: onTaskStatusChange5',statuses, logs, requestIds); App.router.get(this.get('content.controllerName')).saveTasksStatuses(statuses); App.router.get(this.get('content.controllerName')).saveRequestIds(requestIds); App.router.get(this.get('content.controllerName')).saveLogs(logs); App.clusterStatus.setClusterStatus({ clusterName: this.get('content.cluster.name'), clusterState: this.get('clusterDeployState'), wizardControllerName: this.get('content.controllerName'), localdb: App.db.data }); }, /* run command of appropriate task */ runTask: function (taskId) { console.warn('func: runTask',taskId); this[this.get('tasks').findProperty('id', taskId).get('command')](); }, onTaskError: function () { console.warn('func: onTaskError'); this.setTaskStatus(this.get('currentTaskId'), 'FAILED'); }, onTaskCompleted: function () { console.warn('func: onTaskCompleted'); this.setTaskStatus(this.get('currentTaskId'), 'COMPLETED'); }, createComponent: function (componentName, hostName) { console.warn('func: createComponent'); if (!(hostName instanceof Array)) { hostName = [hostName]; } var hostComponents = []; for (var i = 0; i < hostName.length; i++) { hostComponents = App.HostComponent.find().filterProperty('componentName', componentName); if (!hostComponents.length || !hostComponents.mapProperty('host.hostName').contains(hostName[i])) { App.ajax.send({ name: 'admin.high_availability.create_component', sender: this, data: { hostName: hostName[i], componentName: componentName, taskNum: hostName.length }, success: 'onCreateComponent', error: 'onTaskError' }); } else { var taskNum = hostName.length; this.installComponent(componentName, hostName[i], taskNum); } } }, onCreateComponent: function () { console.warn('func: onCreateComponent'); var hostName = arguments[2].hostName; var componentName = arguments[2].componentName; var taskNum = arguments[2].taskNum; this.installComponent(componentName, hostName, taskNum); }, installComponent: function (componentName, hostName, taskNum) { console.warn('func: installComponent'); if (!(hostName instanceof Array)) { hostName = [hostName]; } for (var i = 0; i < hostName.length; i++) { App.ajax.send({ name: 'admin.high_availability.install_component', sender: this, data: { hostName: hostName[i], componentName: componentName, displayName: App.format.role(componentName), taskNum: taskNum || hostName.length }, success: 'startPolling', error: 'onTaskError' }); } }, startComponent: function (componentName, hostName) { console.warn('func: startComponent'); if (!(hostName instanceof Array)) { hostName = [hostName]; } for (var i = 0; i < hostName.length; i++) { App.ajax.send({ name: 'admin.high_availability.start_component', sender: this, data: { hostName: hostName[i], componentName: componentName, displayName: App.format.role(componentName), taskNum: hostName.length }, success: 'startPolling', error: 'onTaskError' }); } }, stopComponent: function (componentName, hostName) { console.warn('func: stopComponent'); if (!(hostName instanceof Array)) { hostName = [hostName]; } for (var i = 0; i < hostName.length; i++) { App.ajax.send({ name: 'admin.high_availability.stop_component', sender: this, data: { hostName: hostName[i], componentName: componentName, displayName: App.format.role(componentName), taskNum: hostName.length }, success: 'startPolling', error: 'onTaskError' }); } }, startPolling: function (data) { if (data) { console.warn('func: startPolling1'); this.get('currentRequestIds').push(data.Requests.id); var tasksCount = arguments[2].taskNum || 1; if (tasksCount === this.get('currentRequestIds').length) { console.warn('func: startPolling2'); this.doPolling(); } } else { console.warn('func: startPolling3'); this.onTaskCompleted(); } }, doPolling: function () { console.warn('func: doPolling'); this.setTaskStatus(this.get('currentTaskId'), 'IN_PROGRESS'); var requestIds = this.get('currentRequestIds'); for (var i = 0; i < requestIds.length; i++) { App.ajax.send({ name: 'admin.high_availability.polling', sender: this, data: { requestId: requestIds[i] }, success: 'parseLogs', error: 'onTaskError' }); } }, parseLogs: function (logs) { console.warn('func: parseLogs'); this.get('logs').push(logs.tasks); if (this.get('currentRequestIds').length === this.get('logs').length) { var tasks = []; this.get('logs').forEach(function (logs) { tasks.pushObjects(logs); }, this); var self = this; var currentTaskId = this.get('currentTaskId'); this.setTaskLogs(currentTaskId, tasks); if (!tasks.someProperty('Tasks.status', 'PENDING') && !tasks.someProperty('Tasks.status', 'QUEUED') && !tasks.someProperty('Tasks.status', 'IN_PROGRESS')) { this.set('currentRequestIds', []); if (tasks.someProperty('Tasks.status', 'FAILED') || tasks.someProperty('Tasks.status', 'TIMEDOUT') || tasks.someProperty('Tasks.status', 'ABORTED')) { this.setTaskStatus(currentTaskId, 'FAILED'); } else { this.setTaskStatus(currentTaskId, 'COMPLETED'); } } else { var actionsPerHost = tasks.length; var completedActions = tasks.filterProperty('Tasks.status', 'COMPLETED').length + tasks.filterProperty('Tasks.status', 'FAILED').length + tasks.filterProperty('Tasks.status', 'ABORTED').length + tasks.filterProperty('Tasks.status', 'TIMEDOUT').length; var queuedActions = tasks.filterProperty('Tasks.status', 'QUEUED').length; var inProgressActions = tasks.filterProperty('Tasks.status', 'IN_PROGRESS').length; var progress = Math.ceil(((queuedActions * 0.09) + (inProgressActions * 0.35) + completedActions ) / actionsPerHost * 100); this.get('tasks').findProperty('id', currentTaskId).set('progress', progress); window.setTimeout(function () { self.doPolling() }, self.POLL_INTERVAL); } this.set('logs', []); } }, done: function () { if (!this.get('isSubmitDisabled')) { this.removeObserver('tasks.@each.status', this, 'onTaskStatusChange'); App.router.send('next'); } } });