org.apache.hadoop.yarn.conf.HAUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.yarn.conf.HAUtil.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.hadoop.yarn.conf;

import java.net.InetSocketAddress;
import java.util.Collection;

import org.apache.hadoop.HadoopIllegalArgumentException;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;

import com.google.common.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@InterfaceAudience.Private
public class HAUtil {
    private static Logger LOG = LoggerFactory.getLogger(HAUtil.class);

    @VisibleForTesting
    public static final String BAD_CONFIG_MESSAGE_PREFIX = "Invalid configuration! ";

    private HAUtil() {
        /* Hidden constructor */ }

    private static void throwBadConfigurationException(String msg) {
        throw new YarnRuntimeException(BAD_CONFIG_MESSAGE_PREFIX + msg);
    }

    /**
     * Returns true if Federation is configured.
     *
     * @param conf Configuration
     * @return true if federation is configured in the configuration; else false.
     */
    public static boolean isFederationEnabled(Configuration conf) {
        return conf.getBoolean(YarnConfiguration.FEDERATION_ENABLED, YarnConfiguration.DEFAULT_FEDERATION_ENABLED);
    }

    /**
     * Returns true if RM failover is enabled in a Federation setting.
     *
     * @param conf Configuration
     * @return if RM failover is enabled in conjunction with Federation in the
     *         configuration; else false.
     */
    public static boolean isFederationFailoverEnabled(Configuration conf) {
        return conf.getBoolean(YarnConfiguration.FEDERATION_FAILOVER_ENABLED,
                YarnConfiguration.DEFAULT_FEDERATION_FAILOVER_ENABLED);
    }

    /**
     * Returns true if Resource Manager HA is configured.
     *
     * @param conf Configuration
     * @return true if HA is configured in the configuration; else false.
     */
    public static boolean isHAEnabled(Configuration conf) {
        return conf.getBoolean(YarnConfiguration.RM_HA_ENABLED, YarnConfiguration.DEFAULT_RM_HA_ENABLED);
    }

    public static boolean isAutomaticFailoverEnabled(Configuration conf) {
        return conf.getBoolean(YarnConfiguration.AUTO_FAILOVER_ENABLED,
                YarnConfiguration.DEFAULT_AUTO_FAILOVER_ENABLED);
    }

    public static boolean isAutomaticFailoverEnabledAndEmbedded(Configuration conf) {
        return isAutomaticFailoverEnabled(conf) && isAutomaticFailoverEmbedded(conf);
    }

    public static boolean isAutomaticFailoverEmbedded(Configuration conf) {
        return conf.getBoolean(YarnConfiguration.AUTO_FAILOVER_EMBEDDED,
                YarnConfiguration.DEFAULT_AUTO_FAILOVER_EMBEDDED);
    }

    /**
     * Verify configuration for Resource Manager HA.
     * @param conf Configuration
     * @throws YarnRuntimeException
     */
    public static void verifyAndSetConfiguration(Configuration conf) throws YarnRuntimeException {
        verifyAndSetRMHAIdsList(conf);
        verifyAndSetCurrentRMHAId(conf);
        verifyLeaderElection(conf);
        verifyAndSetAllServiceAddresses(conf);
    }

    /**
     * Verify configuration that there are at least two RM-ids
     * and RPC addresses are specified for each RM-id.
     * Then set the RM-ids.
     */
    private static void verifyAndSetRMHAIdsList(Configuration conf) {
        Collection<String> ids = conf.getTrimmedStringCollection(YarnConfiguration.RM_HA_IDS);
        if (ids.size() < 2) {
            throwBadConfigurationException(getInvalidValueMessage(YarnConfiguration.RM_HA_IDS,
                    conf.get(YarnConfiguration.RM_HA_IDS) + "\nHA mode requires atleast two RMs"));
        }

        StringBuilder setValue = new StringBuilder();
        for (String id : ids) {
            // verify the RM service addresses configurations for every RMIds
            for (String prefix : YarnConfiguration.getServiceAddressConfKeys(conf)) {
                checkAndSetRMRPCAddress(prefix, id, conf);
            }
            setValue.append(id);
            setValue.append(",");
        }
        conf.set(YarnConfiguration.RM_HA_IDS, setValue.substring(0, setValue.length() - 1));
    }

    private static void verifyAndSetCurrentRMHAId(Configuration conf) {
        String rmId = getRMHAId(conf);
        if (rmId == null) {
            StringBuilder msg = new StringBuilder();
            msg.append("Can not find valid RM_HA_ID. None of ");
            for (String id : conf.getTrimmedStringCollection(YarnConfiguration.RM_HA_IDS)) {
                msg.append(addSuffix(YarnConfiguration.RM_ADDRESS, id)).append(" ");
            }
            msg.append(" are matching" + " the local address OR " + YarnConfiguration.RM_HA_ID + " is not"
                    + " specified in HA Configuration");
            throwBadConfigurationException(msg.toString());
        } else {
            Collection<String> ids = getRMHAIds(conf);
            if (!ids.contains(rmId)) {
                throwBadConfigurationException(getRMHAIdNeedToBeIncludedMessage(ids.toString(), rmId));
            }
        }
        conf.set(YarnConfiguration.RM_HA_ID, rmId);
    }

    /**
     * This method validates that some leader election service is enabled. YARN
     * allows leadership election to be disabled in the configuration, which
     * breaks automatic failover. If leadership election is disabled, this
     * method will throw an exception via
     * {@link #throwBadConfigurationException(java.lang.String)}.
     *
     * @param conf the {@link Configuration} to validate
     */
    private static void verifyLeaderElection(Configuration conf) {
        if (isAutomaticFailoverEnabled(conf)
                && !conf.getBoolean(YarnConfiguration.CURATOR_LEADER_ELECTOR,
                        YarnConfiguration.DEFAULT_CURATOR_LEADER_ELECTOR_ENABLED)
                && !isAutomaticFailoverEmbedded(conf)) {
            throwBadConfigurationException(NO_LEADER_ELECTION_MESSAGE);
        }
    }

    @VisibleForTesting
    static final String NO_LEADER_ELECTION_MESSAGE = "The yarn.resourcemanager.ha.automatic-failover.embedded "
            + "and yarn.resourcemanager.ha.curator-leader-elector.enabled "
            + "properties are both false. One of these two properties must "
            + "be true when yarn.resourcemanager.ha.automatic-failover.enabled " + "is true";

    private static void verifyAndSetConfValue(String prefix, Configuration conf) {
        String confKey = null;
        String confValue = null;
        try {
            confKey = getConfKeyForRMInstance(prefix, conf);
            confValue = getConfValueForRMInstance(prefix, conf);
            conf.set(prefix, confValue);
        } catch (YarnRuntimeException yre) {
            // Error at getRMHAId()
            throw yre;
        } catch (IllegalArgumentException iae) {
            String errmsg;
            if (confKey == null) {
                // Error at addSuffix
                errmsg = getInvalidValueMessage(YarnConfiguration.RM_HA_ID, getRMHAId(conf));
            } else {
                // Error at Configuration#set.
                errmsg = getNeedToSetValueMessage(confKey);
            }
            throwBadConfigurationException(errmsg);
        }
    }

    public static void verifyAndSetAllServiceAddresses(Configuration conf) {
        for (String confKey : YarnConfiguration.getServiceAddressConfKeys(conf)) {
            verifyAndSetConfValue(confKey, conf);
        }
    }

    /**
     * @param conf Configuration. Please use getRMHAIds to check.
     * @return RM Ids on success
     */
    public static Collection<String> getRMHAIds(Configuration conf) {
        return conf.getStringCollection(YarnConfiguration.RM_HA_IDS);
    }

    /**
     * @param conf Configuration. Please use verifyAndSetRMHAId to check.
     * @return RM Id on success
     */
    public static String getRMHAId(Configuration conf) {
        int found = 0;
        String currentRMId = conf.getTrimmed(YarnConfiguration.RM_HA_ID);
        if (currentRMId == null) {
            for (String rmId : getRMHAIds(conf)) {
                String key = addSuffix(YarnConfiguration.RM_ADDRESS, rmId);
                String addr = conf.get(key);
                if (addr == null) {
                    continue;
                }
                InetSocketAddress s;
                try {
                    s = NetUtils.createSocketAddr(addr);
                } catch (Exception e) {
                    LOG.warn("Exception in creating socket address " + addr, e);
                    continue;
                }
                if (!s.isUnresolved() && NetUtils.isLocalAddress(s.getAddress())) {
                    currentRMId = rmId.trim();
                    found++;
                }
            }
        }
        if (found > 1) { // Only one address must match the local address
            String msg = "The HA Configuration has multiple addresses that match " + "local node's address.";
            throw new HadoopIllegalArgumentException(msg);
        }
        return currentRMId;
    }

    @VisibleForTesting
    static String getNeedToSetValueMessage(String confKey) {
        return confKey + " needs to be set in an HA configuration.";
    }

    @VisibleForTesting
    static String getInvalidValueMessage(String confKey, String invalidValue) {
        return "Invalid value of " + confKey + ". " + "Current value is " + invalidValue;
    }

    @VisibleForTesting
    static String getRMHAIdNeedToBeIncludedMessage(String ids, String rmId) {
        return YarnConfiguration.RM_HA_IDS + "(" + ids + ") need to contain " + YarnConfiguration.RM_HA_ID + "("
                + rmId + ") in an HA configuration.";
    }

    @VisibleForTesting
    static String getRMHAIdsWarningMessage(String ids) {
        return "Resource Manager HA is enabled, but " + YarnConfiguration.RM_HA_IDS + " has only one id("
                + ids.toString() + ")";
    }

    @InterfaceAudience.Private
    @VisibleForTesting
    static String getConfKeyForRMInstance(String prefix, Configuration conf) {
        if (!YarnConfiguration.getServiceAddressConfKeys(conf).contains(prefix)) {
            return prefix;
        } else {
            String RMId = getRMHAId(conf);
            checkAndSetRMRPCAddress(prefix, RMId, conf);
            return addSuffix(prefix, RMId);
        }
    }

    public static String getConfValueForRMInstance(String prefix, Configuration conf) {
        String confKey = getConfKeyForRMInstance(prefix, conf);
        String retVal = conf.getTrimmed(confKey);
        if (LOG.isTraceEnabled()) {
            LOG.trace("getConfValueForRMInstance: prefix = {};" + " confKey being looked up = {};"
                    + " value being set to = {}", prefix, confKey, retVal);
        }
        return retVal;
    }

    public static String getConfValueForRMInstance(String prefix, String defaultValue, Configuration conf) {
        String value = getConfValueForRMInstance(prefix, conf);
        return (value == null) ? defaultValue : value;
    }

    /**
     * Add non empty and non null suffix to a key.
     * @return the suffixed key
     */
    public static String addSuffix(String key, String suffix) {
        if (suffix == null || suffix.isEmpty()) {
            return key;
        }
        if (suffix.startsWith(".")) {
            throw new IllegalArgumentException(
                    "suffix '" + suffix + "' should not " + "already have '.' prepended.");
        }
        return key + "." + suffix;
    }

    private static void checkAndSetRMRPCAddress(String prefix, String RMId, Configuration conf) {
        String rpcAddressConfKey = null;
        try {
            rpcAddressConfKey = addSuffix(prefix, RMId);
            if (conf.getTrimmed(rpcAddressConfKey) == null) {
                String hostNameConfKey = addSuffix(YarnConfiguration.RM_HOSTNAME, RMId);
                String confVal = conf.getTrimmed(hostNameConfKey);
                if (confVal == null) {
                    throwBadConfigurationException(
                            getNeedToSetValueMessage(hostNameConfKey + " or " + addSuffix(prefix, RMId)));
                } else {
                    conf.set(addSuffix(prefix, RMId),
                            confVal + ":" + YarnConfiguration.getRMDefaultPortNumber(prefix, conf));
                }
            }
        } catch (IllegalArgumentException iae) {
            String errmsg = iae.getMessage();
            if (rpcAddressConfKey == null) {
                // Error at addSuffix
                errmsg = getInvalidValueMessage(YarnConfiguration.RM_HA_ID, RMId);
            }
            throwBadConfigurationException(errmsg);
        }
    }
}