org.apache.hadoop.yarn.server.resourcemanager.RMHAProtocolService.java Source code

Java tutorial

Introduction

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

import com.google.common.annotations.VisibleForTesting;

import com.google.protobuf.BlockingService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
import org.apache.hadoop.ha.HAServiceProtocol;
import org.apache.hadoop.ha.HAServiceStatus;
import org.apache.hadoop.ha.HealthCheckFailedException;
import org.apache.hadoop.ha.ServiceFailedException;
import org.apache.hadoop.ha.proto.HAServiceProtocolProtos;
import org.apache.hadoop.ha.protocolPB.HAServiceProtocolPB;
import org.apache.hadoop.ha.protocolPB.HAServiceProtocolServerSideTranslatorPB;
import org.apache.hadoop.ipc.ProtobufRpcEngine;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.Server;
import org.apache.hadoop.ipc.WritableRpcEngine;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authorize.AccessControlList;
import org.apache.hadoop.service.AbstractService;
import org.apache.hadoop.yarn.conf.HAUtil;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.server.resourcemanager.security.authorize.RMPolicyProvider;

import java.io.IOException;
import java.net.InetSocketAddress;

/**
 * Internal class to handle HA related aspects of the {@link ResourceManager}.
 *
 * TODO (YARN-1318): Some/ all of this functionality should be merged with
 * {@link AdminService}. Currently, marking this as Private and Unstable for
 * those reasons.
 */
@InterfaceAudience.Private
@InterfaceStability.Unstable
public class RMHAProtocolService extends AbstractService implements HAServiceProtocol {
    private static final Log LOG = LogFactory.getLog(RMHAProtocolService.class);

    private Configuration conf;
    private ResourceManager rm;
    @VisibleForTesting
    protected HAServiceState haState = HAServiceState.INITIALIZING;
    private AccessControlList adminAcl;
    private Server haAdminServer;
    private boolean haEnabled;

    public RMHAProtocolService(ResourceManager resourceManager) {
        super("RMHAProtocolService");
        this.rm = resourceManager;
    }

    @Override
    protected synchronized void serviceInit(Configuration conf) throws Exception {
        this.conf = conf;
        haEnabled = HAUtil.isHAEnabled(this.conf);
        if (haEnabled) {
            HAUtil.verifyAndSetConfiguration(conf);
            rm.setConf(this.conf);
            adminAcl = new AccessControlList(
                    conf.get(YarnConfiguration.YARN_ADMIN_ACL, YarnConfiguration.DEFAULT_YARN_ADMIN_ACL));
        }
        rm.createAndInitActiveServices();
        super.serviceInit(this.conf);
    }

    @Override
    protected synchronized void serviceStart() throws Exception {
        if (haEnabled) {
            transitionToStandby(true);
            startHAAdminServer();
        } else {
            transitionToActive();
        }

        super.serviceStart();
    }

    @Override
    protected synchronized void serviceStop() throws Exception {
        if (haEnabled) {
            stopHAAdminServer();
        }
        transitionToStandby(false);
        haState = HAServiceState.STOPPING;
        super.serviceStop();
    }

    protected void startHAAdminServer() throws Exception {
        InetSocketAddress haAdminServiceAddress = conf.getSocketAddr(YarnConfiguration.RM_HA_ADMIN_ADDRESS,
                YarnConfiguration.DEFAULT_RM_HA_ADMIN_ADDRESS, YarnConfiguration.DEFAULT_RM_HA_ADMIN_PORT);

        RPC.setProtocolEngine(conf, HAServiceProtocolPB.class, ProtobufRpcEngine.class);

        HAServiceProtocolServerSideTranslatorPB haServiceProtocolXlator = new HAServiceProtocolServerSideTranslatorPB(
                this);
        BlockingService haPbService = HAServiceProtocolProtos.HAServiceProtocolService
                .newReflectiveBlockingService(haServiceProtocolXlator);

        WritableRpcEngine.ensureInitialized();

        String bindHost = haAdminServiceAddress.getHostName();

        int serviceHandlerCount = conf.getInt(YarnConfiguration.RM_HA_ADMIN_CLIENT_THREAD_COUNT,
                YarnConfiguration.DEFAULT_RM_HA_ADMIN_CLIENT_THREAD_COUNT);

        haAdminServer = new RPC.Builder(conf).setProtocol(HAServiceProtocolPB.class).setInstance(haPbService)
                .setBindAddress(bindHost).setPort(haAdminServiceAddress.getPort())
                .setNumHandlers(serviceHandlerCount).setVerbose(false).build();

        // Enable service authorization?
        if (conf.getBoolean(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHORIZATION, false)) {
            haAdminServer.refreshServiceAcl(conf, new RMPolicyProvider());
        }

        haAdminServer.start();
        conf.updateConnectAddr(YarnConfiguration.RM_HA_ADMIN_ADDRESS, haAdminServer.getListenerAddress());
    }

    private void stopHAAdminServer() throws Exception {
        if (haAdminServer != null) {
            haAdminServer.stop();
            haAdminServer.join();
            haAdminServer = null;
        }
    }

    @Override
    public synchronized void monitorHealth() throws IOException {
        checkAccess("monitorHealth");
        if (haState == HAServiceState.ACTIVE && !rm.areActiveServicesRunning()) {
            throw new HealthCheckFailedException("Active ResourceManager services are not running!");
        }
    }

    private synchronized void transitionToActive() throws Exception {
        if (haState == HAServiceState.ACTIVE) {
            LOG.info("Already in active state");
            return;
        }

        LOG.info("Transitioning to active");
        rm.startActiveServices();
        haState = HAServiceState.ACTIVE;
        LOG.info("Transitioned to active");
    }

    @Override
    public synchronized void transitionToActive(StateChangeRequestInfo reqInfo) throws IOException {
        UserGroupInformation user = checkAccess("transitionToActive");
        // TODO (YARN-1177): When automatic failover is enabled,
        // check if transition should be allowed for this request
        try {
            transitionToActive();
            RMAuditLogger.logSuccess(user.getShortUserName(), "transitionToActive", "RMHAProtocolService");
        } catch (Exception e) {
            RMAuditLogger.logFailure(user.getShortUserName(), "transitionToActive", adminAcl.toString(),
                    "RMHAProtocolService", "Exception transitioning to active");
            throw new ServiceFailedException("Error when transitioning to Active mode", e);
        }
    }

    private synchronized void transitionToStandby(boolean initialize) throws Exception {
        if (haState == HAServiceState.STANDBY) {
            LOG.info("Already in standby state");
            return;
        }

        LOG.info("Transitioning to standby");
        if (haState == HAServiceState.ACTIVE) {
            rm.stopActiveServices();
            if (initialize) {
                rm.createAndInitActiveServices();
            }
        }
        haState = HAServiceState.STANDBY;
        LOG.info("Transitioned to standby");
    }

    @Override
    public synchronized void transitionToStandby(StateChangeRequestInfo reqInfo) throws IOException {
        UserGroupInformation user = checkAccess("transitionToStandby");
        // TODO (YARN-1177): When automatic failover is enabled,
        // check if transition should be allowed for this request
        try {
            transitionToStandby(true);
            RMAuditLogger.logSuccess(user.getShortUserName(), "transitionToStandby", "RMHAProtocolService");
        } catch (Exception e) {
            RMAuditLogger.logFailure(user.getShortUserName(), "transitionToStandby", adminAcl.toString(),
                    "RMHAProtocolService", "Exception transitioning to standby");
            throw new ServiceFailedException("Error when transitioning to Standby mode", e);
        }
    }

    @Override
    public synchronized HAServiceStatus getServiceStatus() throws IOException {
        checkAccess("getServiceState");
        HAServiceStatus ret = new HAServiceStatus(haState);
        if (haState == HAServiceState.ACTIVE || haState == HAServiceState.STANDBY) {
            ret.setReadyToBecomeActive();
        } else {
            ret.setNotReadyToBecomeActive("State is " + haState);
        }
        return ret;
    }

    private UserGroupInformation checkAccess(String method) throws IOException {
        return RMServerUtils.verifyAccess(adminAcl, method, LOG);
    }
}