/** * 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'); var uiEffects = require('utils/ui_effects'); /** * Mixin for App.HostComponentView * Contains code for processing components with allowed decommission * @type {Em.Mixin} */ App.Decommissionable = Em.Mixin.create({ /** * Should be redeclared in views that use this mixin * @type {String} */ componentForCheckDecommission: '', /** * Is component in decommission process right know * @type {bool} */ isComponentDecommissioning: null, /** * May conponent be decommissioned * @type {bool} */ isComponentDecommissionAvailable: null, /** * May component be recommissioned * @type {bool} */ isComponentRecommissionAvailable: null, /** * Component with stopped masters can't be docommissioned * @type {bool} */ isComponentDecommissionDisable: function() { var masterComponent = this.get('content.service.hostComponents').findProperty('componentName', this.get('componentForCheckDecommission')); if (masterComponent && masterComponent.get('workStatus') != App.HostComponentStatus.started) return true; return this.get('content.service.workStatus') != App.HostComponentStatus.started; }.property('content.service.workStatus', 'content.service.hostComponents.@each.workStatus'), /** * @override App.HostComponentView.isRestartableComponent */ isRestartableComponent: function() { return this.get('isComponentDecommissionAvailable') && App.get('components.restartable').contains(this.get('content.componentName')); }.property('isComponentDecommissionAvailable'), /** * Tooltip message shows if decommission/recommission is disabled * when masters for current component is down */ decommissionTooltipMessage: function() { if (this.get('isComponentDecommissionDisable') && (this.get('isComponentRecommissionAvailable') || this.get('isComponentDecommissionAvailable'))) { var decom = this.get('isComponentRecommissionAvailable') ? Em.I18n.t('common.recommission') : Em.I18n.t('common.decommission'); return Em.I18n.t('hosts.decommission.tooltip.warning').format(decom, App.format.role(this.get('componentForCheckDecommission'))); } }.property('isComponentDecommissionDisable', 'isComponentRecommissionAvailable', 'isComponentDecommissionAvailable', 'componentForCheckDecommission'), /** * Recalculated component status based on decommission * @type {string} */ statusClass: function () { //Class when install failed if (this.get('workStatus') === App.HostComponentStatus.install_failed) { return 'health-status-color-red icon-cog'; } //Class when installing if (this.get('workStatus') === App.HostComponentStatus.installing) { return 'health-status-color-blue icon-cog'; } if (this.get('isComponentRecommissionAvailable') && (this.get('isStart') || this.get('workStatus') == 'INSTALLED')) { return 'health-status-DEAD-ORANGE'; } //For all other cases return 'health-status-' + App.HostComponentStatus.getKeyName(this.get('workStatus')); }.property('workStatus', 'isComponentRecommissionAvailable', 'isComponentDecommissioning'), /** * Return host component text status * @type {String} */ componentTextStatus: function () { var componentTextStatus = this.get('content.componentTextStatus'); var hostComponent = this.get('hostComponent'); if (hostComponent) { componentTextStatus = hostComponent.get('componentTextStatus'); if(this.get('isComponentRecommissionAvailable')){ if(this.get('isComponentDecommissioning')){ componentTextStatus = Em.I18n.t('hosts.host.decommissioning'); } else { componentTextStatus = Em.I18n.t('hosts.host.decommissioned'); } } } return componentTextStatus; }.property('workStatus','isComponentRecommissionAvailable','isComponentDecommissioning'), /** * For Stopping or Starting states, also for decommissioning * @type {bool} */ isInProgress: function () { return (this.get('workStatus') === App.HostComponentStatus.stopping || this.get('workStatus') === App.HostComponentStatus.starting) || this.get('isDecommissioning'); }.property('workStatus', 'isDecommissioning'), /** * load Recommission/Decommission status of component */ loadComponentDecommissionStatus: function () { return this.getDesiredAdminState(); }, /** * Get desired_admin_state status from server */ getDesiredAdminState: function(){ return App.ajax.send({ name: 'host.host_component.slave_desired_admin_state', sender: this, data: { hostName: this.get('content.hostName'), componentName: this.get('content.componentName') }, success: 'getDesiredAdminStateSuccessCallback', error: 'getDesiredAdminStateErrorCallback' }); }, /** * pass received value or null to setDesiredAdminState * @param {Object} response * @returns {String|null} */ getDesiredAdminStateSuccessCallback: function (response) { var status = response.HostRoles.desired_admin_state; if (status != null) { this.setDesiredAdminState(status); return status; } return null; }, /** * error callback of getDesiredAdminState */ getDesiredAdminStateErrorCallback: Em.K, /** * compute decommission state by desiredAdminState * @param {Object} status */ setDesiredAdminState: Em.K, /** * Get component decommission status from server * @returns {$.ajax} */ getDecommissionStatus: function() { return App.ajax.send({ name: 'host.host_component.decommission_status', sender: this, data: { hostName: this.get('content.hostName'), componentName: this.get('componentForCheckDecommission'), serviceName: this.get('content.service.serviceName') }, success: 'getDecommissionStatusSuccessCallback', error: 'getDecommissionStatusErrorCallback' }); }, /** * pass received value or null to setDecommissionStatus * @param {Object} response * @returns {Object|null} */ getDecommissionStatusSuccessCallback: function (response) { var statusObject = response.ServiceComponentInfo; if ( statusObject != null) { statusObject.component_state = response.host_components[0].HostRoles.state; this.setDecommissionStatus(statusObject); return statusObject; } return null; }, /** * Set null to decommissionedStatusObject if server returns error * @returns {null} */ getDecommissionStatusErrorCallback: Em.K, /** * compute decommission state by component info * @param {Object} status */ setDecommissionStatus: Em.K, /** * set decommission and recommission flags according to status * @param status */ setStatusAs: function (status) { switch (status) { case "INSERVICE": this.set('isComponentRecommissionAvailable', false); this.set('isComponentDecommissioning', false); this.set('isComponentDecommissionAvailable', this.get('isStart')); break; case "DECOMMISSIONING": this.set('isComponentRecommissionAvailable', true); this.set('isComponentDecommissioning', true); this.set('isComponentDecommissionAvailable', false); break; case "DECOMMISSIONED": this.set('isComponentRecommissionAvailable', true); this.set('isComponentDecommissioning', false); this.set('isComponentDecommissionAvailable', false); break; case "RS_DECOMMISSIONED": this.set('isComponentRecommissionAvailable', true); this.set('isComponentDecommissioning', this.get('isStart')); this.set('isComponentDecommissionAvailable', false); break; } }, /** * Do blinking for 1 minute */ doBlinking: function () { var workStatus = this.get('workStatus'); var self = this; var pulsate = [App.HostComponentStatus.starting, App.HostComponentStatus.stopping, App.HostComponentStatus.installing].contains(workStatus); if (!pulsate) { var component = this.get('content'); if (component && workStatus != "INSTALLED") { pulsate = this.get('isDecommissioning'); } } if (pulsate && !self.get('isBlinking')) { self.set('isBlinking', true); uiEffects.pulsate(self.$('.components-health'), 1000, function () { self.set('isBlinking', false); self.doBlinking(); }); } }, /** * Start blinking when host component is starting/stopping/decommissioning */ startBlinking: function () { this.$('.components-health').stop(true, true); this.$('.components-health').css({opacity: 1.0}); this.doBlinking(); }.observes('workStatus','isComponentRecommissionAvailable', 'isDecommissioning'), didInsertElement: function() { this._super(); this.loadComponentDecommissionStatus(); }, /** * Update Decommission status only one time when component was changed */ updateDecommissionStatus: function() { Em.run.once(this, 'loadComponentDecommissionStatus'); }.observes('content.workStatus', 'content.passiveState'), decommissionView: Em.View.extend({ templateName: require('templates/main/host/decommission'), text: function() { return this.get('parentView.isComponentDecommissionAvailable') ? Em.I18n.t('common.decommission') : Em.I18n.t('common.recommission'); }.property('parentView.isComponentDecommissionAvailable'), didInsertElement: function() { this._super(); App.tooltip($("[rel='decommissionTooltip']")); }, click: function() { if (!this.get('parentView.isComponentDecommissionDisable')) { if (this.get('parentView.isComponentDecommissionAvailable')) { this.get('controller').decommission(this.get('parentView.content')); } else { this.get('controller').recommission(this.get('parentView.content')); } } } }) });