org.apache.ambari.msi.ClusterDefinition.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ambari.msi.ClusterDefinition.java

Source

/**
 * 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.msi;

import org.apache.ambari.scom.ClusterDefinitionProvider;
import org.apache.ambari.scom.HostInfoProvider;
import org.apache.ambari.server.controller.internal.ResourceImpl;
import org.apache.ambari.server.controller.spi.Resource;
import org.apache.commons.lang.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Defines the cluster created by the MSI.
 */
public class ClusterDefinition {

    private static final String COMMENT_TAG = "#";
    private static final String HA_PROPERTY_INDICATOR = "HA";
    private static Boolean HA_ENABLE = Boolean.FALSE;

    private final Set<String> services = new HashSet<String>();
    private final Set<String> hosts = new HashSet<String>();
    private final Map<String, Set<String>> components = new HashMap<String, Set<String>>();
    private final Map<String, Map<String, Set<String>>> hostComponents = new HashMap<String, Map<String, Set<String>>>();
    private final Map<Integer, StateProvider.Process> processes = new HashMap<Integer, StateProvider.Process>();

    private final Set<Resource> requestResources = new HashSet<Resource>();
    private final Set<Resource> taskResources = new HashSet<Resource>();

    private final StateProvider stateProvider;
    private final ClusterDefinitionProvider definitionProvider;
    private final HostInfoProvider hostInfoProvider;
    private String clusterName;
    private String versionId;

    private int nextRequestId = 1;
    private int nextTaskId = 1;

    /**
     * Client only components
     */
    private final Set<String> clientOnlyComponents = new HashSet<String>() {
        {
            add("PIG");
            add("SQOOP");
            add("YARN_CLIENT");
            add("MAPREDUCE2_CLIENT");
        }
    };

    private Boolean isClientOnlyComponent(String componentName) {
        return clientOnlyComponents.contains(componentName);
    }

    /**
     * Client only services
     */
    private final Set<String> clientOnlyServices = new HashSet<String>() {
        {
            add("PIG");
            add("SQOOP");
        }
    };

    private Boolean isClientOnlyService(String serviceName) {
        return clientOnlyServices.contains(serviceName);
    }

    /**
     * Component name mapping to account for differences in what is provided by the MSI
     * and what is expected by the Ambari providers.
     */
    private final Map<String, Set<String>> componentNameMap = new HashMap<String, Set<String>>();

    private void initComponentNameMap() {
        componentNameMap.put("NAMENODE_HOST", Collections.singleton("NAMENODE"));
        componentNameMap.put("SECONDARY_NAMENODE_HOST", Collections.singleton("SECONDARY_NAMENODE"));
        componentNameMap.put("OOZIE_SERVER_HOST", Collections.singleton("OOZIE_SERVER"));
        componentNameMap.put("WEBHCAT_HOST", Collections.singleton("WEBHCAT_SERVER"));
        componentNameMap.put("FLUME_HOSTS", Collections.singleton("FLUME_SERVER"));
        componentNameMap.put("HBASE_MASTER", Collections.singleton("HBASE_MASTER"));
        componentNameMap.put("HBASE_REGIONSERVERS", Collections.singleton("HBASE_REGIONSERVER"));
        componentNameMap.put("ZOOKEEPER_HOSTS", Collections.singleton("ZOOKEEPER_SERVER"));

        Set<String> slaveComponents = new HashSet<String>();
        slaveComponents.add("DATANODE");
        componentNameMap.put("SLAVE_HOSTS", slaveComponents);

        Set<String> hiveComponents = new HashSet<String>();
        hiveComponents.add("HIVE_SERVER");
        hiveComponents.add("HIVE_METASTORE");
        hiveComponents.add("HIVE_CLIENT");
        componentNameMap.put("HIVE_SERVER_HOST", hiveComponents);

        Integer majorStackVersion = getMajorStackVersion();
        Integer minorStackVersion = getMinorStackVersion();
        if (majorStackVersion != null) {
            if (majorStackVersion == 1) {
                Set<String> mapReduceComponents = new HashSet<String>();
                mapReduceComponents.add("JOBTRACKER");
                mapReduceComponents.add("HISTORYSERVER");
                componentNameMap.put("JOBTRACKER_HOST", mapReduceComponents);

                slaveComponents.add("TASKTRACKER");
            }
            if (majorStackVersion == 2) {
                componentNameMap.put("JOURNALNODE_HOST", Collections.singleton("JOURNALNODE"));
                componentNameMap.put(minorStackVersion > 0 ? "NN_HA_JOURNALNODE_HOSTS" : "HA_JOURNALNODE_HOSTS",
                        Collections.singleton("JOURNALNODE"));

                Set<String> haNamenodeComponents = new HashSet<String>();
                haNamenodeComponents.add("NAMENODE");
                haNamenodeComponents.add("ZKFC");
                componentNameMap.put(minorStackVersion > 0 ? "NN_HA_STANDBY_NAMENODE_HOST" : "HA_NAMENODE_HOST",
                        haNamenodeComponents);

                Set<String> mapReduce2Components = new HashSet<String>();
                mapReduce2Components.add("HISTORYSERVER");
                mapReduce2Components.add("RESOURCEMANAGER");
                componentNameMap.put("RESOURCEMANAGER_HOST", mapReduce2Components);

                componentNameMap.put("RM_HA_STANDBY_RESOURCEMANAGER_HOST",
                        Collections.singleton("RESOURCEMANAGER"));

                slaveComponents.add("NODEMANAGER");
                //hiveComponents.add("MYSQL_SERVER");

                Set<String> clientHosts = new HashSet<String>();
                clientHosts.add("PIG");
                clientHosts.add("SQOOP");
                clientHosts.add("YARN_CLIENT");
                clientHosts.add("MAPREDUCE2_CLIENT");
                componentNameMap.put("CLIENT_HOSTS", clientHosts);
            }
        }
    }

    /**
     * Component service mapping .
     */
    private final Map<String, String> componentServiceMap = new HashMap<String, String>();

    private void initComponentServiceMap() {
        componentServiceMap.put("NAMENODE", "HDFS");
        componentServiceMap.put("DATANODE", "HDFS");
        componentServiceMap.put("SECONDARY_NAMENODE", "HDFS");
        componentServiceMap.put("HIVE_SERVER", "HIVE");
        componentServiceMap.put("HIVE_METASTORE", "HIVE");
        componentServiceMap.put("HIVE_CLIENT", "HIVE");
        componentServiceMap.put("OOZIE_SERVER", "OOZIE");
        componentServiceMap.put("WEBHCAT_SERVER", "HIVE");
        componentServiceMap.put("FLUME_SERVER", "FLUME");
        componentServiceMap.put("HBASE_MASTER", "HBASE");
        componentServiceMap.put("HBASE_REGIONSERVER", "HBASE");
        componentServiceMap.put("ZOOKEEPER_SERVER", "ZOOKEEPER");

        Integer majorStackVersion = getMajorStackVersion();
        if (majorStackVersion != null) {
            if (majorStackVersion == 1) {
                componentServiceMap.put("JOBTRACKER", "MAPREDUCE");
                componentServiceMap.put("HISTORYSERVER", "MAPREDUCE");
                componentServiceMap.put("TASKTRACKER", "MAPREDUCE");
            }
            if (majorStackVersion == 2) {
                componentServiceMap.put("PIG", "PIG");
                componentServiceMap.put("SQOOP", "SQOOP");
                componentServiceMap.put("HISTORYSERVER", "MAPREDUCE2");
                componentServiceMap.put("MAPREDUCE2_CLIENT", "MAPREDUCE2");
                componentServiceMap.put("JOURNALNODE", "HDFS");
                componentServiceMap.put("NODEMANAGER", "YARN");
                componentServiceMap.put("RESOURCEMANAGER", "YARN");
                componentServiceMap.put("YARN_CLIENT", "YARN");
                componentServiceMap.put("ZKFC", "HDFS");
                //componentServiceMap.put("MYSQL_SERVER",       "HIVE");
            }
        }
    }

    // ----- Constructors ------------------------------------------------------

    /**
     * Create a cluster definition.
     *
     * @param stateProvider  the state provider
     */
    public ClusterDefinition(StateProvider stateProvider, ClusterDefinitionProvider definitionProvider,
            HostInfoProvider hostInfoProvider) {
        this.stateProvider = stateProvider;
        this.definitionProvider = definitionProvider;
        this.hostInfoProvider = hostInfoProvider;
        this.clusterName = definitionProvider.getClusterName();
        this.versionId = definitionProvider.getVersionId();

        init();

        try {
            readClusterDefinition();
            haEnableSetup();
        } catch (IOException e) {
            String msg = "Caught exception reading cluster definition file.";
            throw new IllegalStateException(msg, e);
        }
    }

    private void haEnableSetup() {
        if (HA_ENABLE) {
            Map<String, Set<String>> serviceHostComponents = hostComponents.get(componentServiceMap.get("ZKFC"));
            if (serviceHostComponents != null) {
                for (String host : serviceHostComponents.keySet()) {
                    Set<String> hostHostComponents = serviceHostComponents.get(host);
                    if (hostHostComponents != null && hostHostComponents.contains("NAMENODE")) {
                        hostHostComponents.add("ZKFC");
                    }
                }
            }
        }
    }

    // ----- ClusterDefinition -------------------------------------------------

    /**
     * Get the major stack version for this cluster.
     *
     * @return the major stack version
     */
    public Integer getMajorStackVersion() {
        if (StringUtils.isNotEmpty(versionId)) {
            String majorVersion = StringUtils.substring(versionId, 4, 5);
            if (StringUtils.isNotEmpty(majorVersion)) {
                return Integer.parseInt(majorVersion);
            }
        }
        return null;
    }

    /**
     * Get the minor stack version for this cluster.
     *
     * @return the minor stack version
     */
    public Integer getMinorStackVersion() {
        if (StringUtils.isNotEmpty(versionId)) {
            String majorVersion = StringUtils.substring(versionId, 6, 7);
            if (StringUtils.isNotEmpty(majorVersion)) {
                return Integer.parseInt(majorVersion);
            }
        }
        return null;
    }

    /**
     * Get the name of the cluster.
     *
     * @return the cluster name
     */
    public String getClusterName() {
        return clusterName;
    }

    /**
     * Get the name of the cluster.
     *
     * @return the cluster name
     */
    public String getVersionId() {
        return versionId;
    }

    /**
     * Get the services for the cluster.
     *
     * @return the set of service names
     */
    public Set<String> getServices() {
        return services;
    }

    /**
     * Get the hosts for the cluster.
     *
     * @return the set of hosts names
     */
    public Set<String> getHosts() {
        return hosts;
    }

    /**
     * Get the host info provider associated with this cluster definition.
     *
     * @return the host info provider
     */
    public HostInfoProvider getHostInfoProvider() {
        return hostInfoProvider;
    }

    /**
     * Get the components for the given service.
     *
     * @param service  the service name
     *
     * @return the set of component names for the given service name
     */
    public Set<String> getComponents(String service) {
        Set<String> componentSet = components.get(service);
        return componentSet == null ? Collections.<String>emptySet() : componentSet;
    }

    /**
     * Get the host components for the given service and host.
     *
     * @param service  the service name
     * @param host     the host name
     *
     * @return the set of host component names for the given service and host names
     */
    public Set<String> getHostComponents(String service, String host) {
        Set<String> resultSet = null;
        Map<String, Set<String>> serviceHostComponents = hostComponents.get(service);
        if (serviceHostComponents != null) {
            resultSet = serviceHostComponents.get(host);
        }
        return resultSet == null ? Collections.<String>emptySet() : resultSet;
    }

    /**
     * Get the host state from the given host name.
     *
     * @param hostName  the host name
     *
     * @return the host state
     */
    public String getHostState(String hostName) {
        for (Map.Entry<String, Map<String, Set<String>>> entry : hostComponents.entrySet()) {
            Map<String, Set<String>> serviceHostComponents = entry.getValue();
            for (Map.Entry<String, Set<String>> hostEntry : serviceHostComponents.entrySet()) {
                if (hostEntry.getKey().equals(hostName)) {
                    Set<String> componentNames = hostEntry.getValue();
                    for (String componentName : componentNames) {
                        if (isClientOnlyComponent(componentName))
                            continue;
                        if (stateProvider.getRunningState(hostName, componentName) != StateProvider.State.Running) {
                            return "UNHEALTHY";
                        }
                    }
                }
            }
        }
        return "HEALTHY";
    }

    /**
     * Get the service state from the given service name.
     *
     * @param serviceName  the service name
     *
     * @return the service state
     */
    public String getServiceState(String serviceName) {
        if (isClientOnlyService(serviceName))
            return "INSTALLED";
        Map<String, Set<String>> serviceHostComponents = hostComponents.get(serviceName);
        if (serviceHostComponents != null) {

            for (Map.Entry<String, Set<String>> entry : serviceHostComponents.entrySet()) {
                String hostName = entry.getKey();
                Set<String> componentNames = entry.getValue();

                for (String componentName : componentNames) {
                    if (isClientOnlyComponent(componentName))
                        continue;
                    if (stateProvider.getRunningState(hostName, componentName) != StateProvider.State.Running) {
                        return "INSTALLED";
                    }
                }
            }
        }

        return "STARTED";
    }

    /**
     * Set the service state for the given service name.
     *
     * @param serviceName  the service name
     *
     * @return the request id
     */
    public int setServiceState(String serviceName, String state) {
        StateProvider.State s = state.equals("STARTED") ? StateProvider.State.Running
                : state.equals("INSTALLED") ? StateProvider.State.Stopped : StateProvider.State.Unknown;

        int requestId = -1;
        if (!isClientOnlyService(serviceName)) {
            // if the state is already set to the desired state or state is unknown then skip it
            if (s != StateProvider.State.Unknown && !state.equals(getServiceState(serviceName))) {
                Map<String, Set<String>> serviceHostComponents = hostComponents.get(serviceName);
                if (serviceHostComponents != null) {

                    for (Map.Entry<String, Set<String>> entry : serviceHostComponents.entrySet()) {
                        String hostName = entry.getKey();
                        Set<String> componentNames = entry.getValue();

                        for (String componentName : componentNames) {
                            if (isClientOnlyComponent(componentName)
                                    || state.equals(getHostComponentState(hostName, componentName)))
                                continue;
                            requestId = recordProcess(stateProvider.setRunningState(hostName, componentName, s),
                                    requestId, "Set service " + serviceName + " state to " + s);
                        }
                    }
                }
            }
        }
        return requestId;
    }

    /**
     * Get the component state from the give service name and component name.
     *
     * @param serviceName    the service name
     * @param componentName  the component name
     *
     * @return the component state
     */
    public String getComponentState(String serviceName, String componentName) {
        Map<String, Set<String>> serviceHostComponents = hostComponents.get(serviceName);
        if (serviceHostComponents != null) {

            for (Map.Entry<String, Set<String>> entry : serviceHostComponents.entrySet()) {
                String hostName = entry.getKey();
                Set<String> componentNames = entry.getValue();

                for (String name : componentNames) {
                    if (name.equals(componentName)) {
                        if (isClientOnlyComponent(componentName))
                            return "INSTALLED";
                        if (stateProvider.getRunningState(hostName, componentName) != StateProvider.State.Running) {
                            return "INSTALLED";
                        }
                    }
                }
            }
        }

        return "STARTED";
    }

    /**
     * Set the component state for the given service name.
     *
     * @param serviceName    the service name
     * @param componentName  the component name
     * @param state          the state
     *
     * @return the request id
     */
    public int setComponentState(String serviceName, String componentName, String state) {
        StateProvider.State s = state.equals("STARTED") ? StateProvider.State.Running
                : state.equals("INSTALLED") ? StateProvider.State.Stopped : StateProvider.State.Unknown;

        int requestId = -1;
        if (!isClientOnlyComponent(componentName)) {
            if (s != StateProvider.State.Unknown) {
                Map<String, Set<String>> serviceHostComponents = hostComponents.get(serviceName);
                if (serviceHostComponents != null) {

                    for (Map.Entry<String, Set<String>> entry : serviceHostComponents.entrySet()) {
                        String hostName = entry.getKey();
                        Set<String> componentNames = entry.getValue();

                        for (String name : componentNames) {
                            if (name.equals(componentName)) {
                                if (state.equals(getHostComponentState(hostName, componentName)))
                                    continue;
                                requestId = recordProcess(stateProvider.setRunningState(hostName, componentName, s),
                                        requestId, "Set component " + componentName + " state to " + s);
                            }
                        }
                    }
                }
            }
        }
        return requestId;
    }

    /**
      * Get the host component state from the given host name and component name.
      *
      * @param hostName       the host name
      * @param componentName  the component name
      *
      * @return the host component state
      */
    public String getHostComponentState(String hostName, String componentName) {
        Boolean healthy = Boolean.FALSE;
        if (!isClientOnlyComponent(componentName))
            healthy = stateProvider.getRunningState(hostName, componentName) == StateProvider.State.Running;
        return healthy ? "STARTED" : "INSTALLED";
    }

    /**
     * Set the host component state for the given host name and component name.
     *
     * @param hostName       the host name
     * @param componentName  the component name
     *
     * @return the request id
     */
    public int setHostComponentState(String hostName, String componentName, String state) {
        StateProvider.State s = state.equals("STARTED") ? StateProvider.State.Running
                : state.equals("INSTALLED") ? StateProvider.State.Stopped : StateProvider.State.Unknown;

        int requestId = -1;
        if (!isClientOnlyComponent(componentName)) {
            if (s != StateProvider.State.Unknown && !state.equals(getHostComponentState(hostName, componentName))) {
                requestId = recordProcess(stateProvider.setRunningState(hostName, componentName, s), -1,
                        "Set host component " + componentName + " state to " + s);
            }
        }
        return requestId;
    }

    /**
     * Return the process that is associated with the given id.
     *
     * @param id  the id
     *
     * @return the process
     */
    public StateProvider.Process getProcess(Integer id) {
        return processes.get(id);
    }

    /**
     * Get the set of request resources.
     *
     * @return the set of request resources
     */
    public Set<Resource> getRequestResources() {
        return requestResources;
    }

    /**
     * Get the set of task resources
     *
     * @return the set of task resources
     */
    public Set<Resource> getTaskResources() {
        return taskResources;
    }

    // ----- helper methods ----------------------------------------------------

    // initialize
    private void init() {
        initComponentNameMap();
        initComponentServiceMap();
    }

    // record a process and create the corresponding request and task resource
    private synchronized int recordProcess(StateProvider.Process process, int requestId, String context) {

        if (requestId == -1) {
            requestId = nextRequestId++;

            Resource request = new ResourceImpl(Resource.Type.Request);

            request.setProperty(RequestProvider.REQUEST_ID_PROPERTY_ID, requestId);
            request.setProperty(RequestProvider.REQUEST_CLUSTER_NAME_PROPERTY_ID, clusterName);
            request.setProperty(RequestProvider.REQUEST_CONTEXT_ID, context);

            requestResources.add(request);
        }

        Resource task = new ResourceImpl(Resource.Type.Task);
        int taskId = nextTaskId++;

        taskResources.add(task);

        task.setProperty(TaskProvider.TASK_ID_PROPERTY_ID, taskId);
        task.setProperty(TaskProvider.TASK_REQUEST_ID_PROPERTY_ID, requestId);
        task.setProperty(TaskProvider.TASK_CLUSTER_NAME_PROPERTY_ID, clusterName);

        processes.put(taskId, process);
        return requestId;
    }

    /**
     * Read the MSI cluster definition file.
     */
    private void readClusterDefinition() throws IOException {

        InputStream is = definitionProvider.getInputStream();
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String line;
            while ((line = br.readLine()) != null) {
                line = line.trim();

                if (line.startsWith(COMMENT_TAG))
                    continue;

                int i = line.indexOf('=');
                if (i == -1)
                    continue;

                String propertyName = line.substring(0, i);
                String propertyValue = line.substring(i + 1);

                if (propertyName.equalsIgnoreCase(HA_PROPERTY_INDICATOR)) {
                    HA_ENABLE = propertyValue.equalsIgnoreCase("YES") ? Boolean.TRUE : Boolean.FALSE;
                }

                Set<String> componentNames = componentNameMap.get(propertyName);
                if (componentNames != null) {
                    for (String componentName : componentNames) {
                        String serviceName = componentServiceMap.get(componentName);
                        services.add(serviceName);

                        Set<String> serviceComponents = components.get(serviceName);
                        if (serviceComponents == null) {
                            serviceComponents = new HashSet<String>();
                            components.put(serviceName, serviceComponents);
                        }
                        serviceComponents.add(componentName);

                        Map<String, Set<String>> serviceHostComponents = hostComponents.get(serviceName);
                        if (serviceHostComponents == null) {
                            serviceHostComponents = new HashMap<String, Set<String>>();
                            hostComponents.put(serviceName, serviceHostComponents);
                        }

                        String[] hostNames = propertyValue.split(",");
                        for (String hostName : hostNames) {
                            hostName = hostName.trim();
                            Set<String> hostHostComponents = serviceHostComponents.get(hostName);
                            if (hostHostComponents == null) {
                                hostHostComponents = new HashSet<String>();
                                serviceHostComponents.put(hostName, hostHostComponents);
                            }
                            hostHostComponents.add(componentName);

                            hosts.add(hostName);
                        }
                    }
                }
            }
        } finally {
            is.close();
        }
    }
}