/** * 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. */ package org.apache.ambari.server.controller.utilities.state; import java.util.Collections; import java.util.Set; import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.ObjectNotFoundException; import org.apache.ambari.server.StaticallyInject; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.controller.AmbariManagementController; import org.apache.ambari.server.controller.ServiceComponentHostRequest; import org.apache.ambari.server.controller.ServiceComponentHostResponse; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Clusters; import org.apache.ambari.server.state.ComponentInfo; import org.apache.ambari.server.state.MaintenanceState; import org.apache.ambari.server.state.StackId; import org.apache.ambari.server.state.State; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.Inject; import com.google.inject.Provider; /** * Default calculator of service state. * The following rules should apply : * For services that have all components DISABLED, the service state should be DISABLED. * For services that have any master components, the service state should * be STARTED if all master components are STARTED. * For services that have all client components, the service state should * be INSTALLED if all of the components are INSTALLED. * For all other cases the state of the service should match the highest state of all * of its component states or UNKNOWN if the component states can not be determined. */ @StaticallyInject public class DefaultServiceCalculatedState implements ServiceCalculatedState { protected final static Logger LOG = LoggerFactory.getLogger(DefaultServiceCalculatedState.class); @Inject protected static Provider<Clusters> clustersProvider = null; @Inject protected static Provider<AmbariManagementController> managementControllerProvider = null; // Get the State of a host component protected State getHostComponentState(ServiceComponentHostResponse hostComponent) { return State.valueOf(hostComponent.getLiveState()); } protected Cluster getCluster(String clusterName) throws AmbariException { if (clustersProvider != null && clusterName != null && clusterName.length() > 0) { Clusters clusters = clustersProvider.get(); if (clusters != null){ return clusters.getCluster(clusterName); } } return null; } public State getState(String clusterName, String serviceName) { try { Cluster cluster = getCluster(clusterName); if (cluster != null && managementControllerProvider != null) { AmbariMetaInfo ambariMetaInfo = managementControllerProvider.get().getAmbariMetaInfo(); StackId stackId = cluster.getDesiredStackVersion(); ServiceComponentHostRequest request = new ServiceComponentHostRequest(clusterName, serviceName, null, null, null); Set<ServiceComponentHostResponse> hostComponentResponses = managementControllerProvider.get().getHostComponents(Collections.singleton(request)); State masterState = null; State clientState = null; State otherState = null; State maxMMState = null; // The worst state among components in MM boolean hasDisabled = false; boolean hasMaster = false; boolean hasOther = false; boolean hasClient = false; boolean hasMM = false; for (ServiceComponentHostResponse hostComponentResponse : hostComponentResponses ) { try { ComponentInfo componentInfo = ambariMetaInfo.getComponent(stackId.getStackName(), stackId.getStackVersion(), hostComponentResponse.getServiceName(), hostComponentResponse.getComponentName()); State state = getHostComponentState(hostComponentResponse); // Components in MM should not affect service status, // so we tend to ignore them boolean isInMaintenance = ! MaintenanceState.OFF.toString(). equals(hostComponentResponse.getMaintenanceState()); if (state.equals(State.DISABLED)) { hasDisabled = true; } if (isInMaintenance & !componentInfo.isClient()) { hasMM = true; if ( maxMMState == null || state.ordinal() > maxMMState.ordinal()) { maxMMState = state; } } if (componentInfo.isMaster()) { if (state.equals(State.STARTED) || ! isInMaintenance) { // We rely on master's state to determine service state hasMaster = true; } if (! state.equals(State.STARTED) && ! isInMaintenance && // Ignore status of MM component ( masterState == null || state.ordinal() > masterState.ordinal())) { masterState = state; } } else if (componentInfo.isClient()) { hasClient = true; if (!state.equals(State.INSTALLED) && (clientState == null || state.ordinal() > clientState.ordinal())) { clientState = state; } } else { if (state.equals(State.STARTED) || ! isInMaintenance) { // We rely on slaves's state to determine service state hasOther = true; } if (! state.equals(State.STARTED) && ! isInMaintenance && // Ignore status of MM component ( otherState == null || state.ordinal() > otherState.ordinal())) { otherState = state; } } } catch (ObjectNotFoundException e) { // component doesn't exist, nothing to do } } return hasMaster ? masterState == null ? State.STARTED : masterState : hasOther ? otherState == null ? State.STARTED : otherState : hasClient ? clientState == null ? State.INSTALLED : clientState : hasDisabled ? State.DISABLED : hasMM ? maxMMState : State.UNKNOWN; } } catch (AmbariException e) { LOG.error("Can't determine service state.", e); } return State.UNKNOWN; } }