org.apache.accumulo.server.ServerContext.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.accumulo.server.ServerContext.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.accumulo.server;

import static com.google.common.base.Preconditions.checkArgument;

import java.io.IOException;
import java.util.Objects;
import java.util.Properties;

import org.apache.accumulo.core.Constants;
import org.apache.accumulo.core.clientImpl.ClientContext;
import org.apache.accumulo.core.clientImpl.ClientInfo;
import org.apache.accumulo.core.conf.AccumuloConfiguration;
import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.conf.SiteConfiguration;
import org.apache.accumulo.core.crypto.CryptoServiceFactory;
import org.apache.accumulo.core.crypto.CryptoServiceFactory.ClassloaderType;
import org.apache.accumulo.core.rpc.SslConnectionParams;
import org.apache.accumulo.core.spi.crypto.CryptoService;
import org.apache.accumulo.core.trace.TraceUtil;
import org.apache.accumulo.fate.zookeeper.ZooReaderWriter;
import org.apache.accumulo.server.conf.ServerConfigurationFactory;
import org.apache.accumulo.server.fs.VolumeManager;
import org.apache.accumulo.server.metrics.MetricsSystemHelper;
import org.apache.accumulo.server.rpc.SaslServerConnectionParams;
import org.apache.accumulo.server.rpc.ThriftServerType;
import org.apache.accumulo.server.security.SecurityUtil;
import org.apache.accumulo.server.security.delegation.AuthenticationTokenSecretManager;
import org.apache.accumulo.server.tables.TableManager;
import org.apache.accumulo.server.tablets.UniqueNameAllocator;
import org.apache.hadoop.security.UserGroupInformation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides a server context for Accumulo server components that operate with the system credentials
 * and have access to the system files and configuration.
 */
public class ServerContext extends ClientContext {

    private static final Logger log = LoggerFactory.getLogger(ServerContext.class);

    private final ServerInfo info;
    private TableManager tableManager;
    private UniqueNameAllocator nameAllocator;
    private ZooReaderWriter zooReaderWriter;
    private ServerConfigurationFactory serverConfFactory = null;
    private String applicationName = null;
    private String applicationClassName = null;
    private String hostname = null;
    private AuthenticationTokenSecretManager secretManager;
    private CryptoService cryptoService = null;

    public ServerContext(SiteConfiguration siteConfig) {
        this(new ServerInfo(siteConfig));
    }

    public ServerContext(SiteConfiguration siteConfig, String instanceName, String zooKeepers,
            int zooKeepersSessionTimeOut) {
        this(new ServerInfo(siteConfig, instanceName, zooKeepers, zooKeepersSessionTimeOut));
    }

    public ServerContext(SiteConfiguration siteConfig, Properties clientProps) {
        this(siteConfig, ClientInfo.from(clientProps));
    }

    private ServerContext(SiteConfiguration siteConfig, ClientInfo info) {
        this(new ServerInfo(siteConfig, info.getInstanceName(), info.getZooKeepers(),
                info.getZooKeepersSessionTimeOut()));
    }

    private ServerContext(ServerInfo info) {
        super(info, info.getSiteConfiguration());
        this.info = info;
        zooReaderWriter = new ZooReaderWriter(info.getSiteConfiguration());
    }

    public void setupServer(String appName, String appClassName, String hostname) {
        applicationName = appName;
        applicationClassName = appClassName;
        this.hostname = hostname;
        SecurityUtil.serverLogin(info.getSiteConfiguration());
        log.info("Version " + Constants.VERSION);
        log.info("Instance " + info.getInstanceID());
        ServerUtil.init(this, applicationName);
        MetricsSystemHelper.configure(applicationClassName);
        TraceUtil.enableServerTraces(hostname, applicationName, getServerConfFactory().getSystemConfiguration());
        if (getSaslParams() != null) {
            // Server-side "client" check to make sure we're logged in as a user we expect to be
            enforceKerberosLogin();
        }
    }

    /**
     * Should only be called by the Tablet server
     */
    public synchronized void setupCrypto() throws CryptoService.CryptoException {
        if (cryptoService != null)
            throw new CryptoService.CryptoException("Crypto Service " + cryptoService.getClass().getName()
                    + " already exists and cannot be setup again");

        AccumuloConfiguration acuConf = getConfiguration();
        cryptoService = CryptoServiceFactory.newInstance(acuConf, ClassloaderType.ACCUMULO);
    }

    public void teardownServer() {
        TraceUtil.disable();
    }

    public String getHostname() {
        Objects.requireNonNull(hostname);
        return hostname;
    }

    public synchronized ServerConfigurationFactory getServerConfFactory() {
        if (serverConfFactory == null) {
            serverConfFactory = new ServerConfigurationFactory(this, info.getSiteConfiguration());
        }
        return serverConfFactory;
    }

    @Override
    public AccumuloConfiguration getConfiguration() {
        return getServerConfFactory().getSystemConfiguration();
    }

    /**
     * A "client-side" assertion for servers to validate that they are logged in as the expected user,
     * per the configuration, before performing any RPC
     */
    // Should be private, but package-protected so EasyMock will work
    void enforceKerberosLogin() {
        final AccumuloConfiguration conf = getServerConfFactory().getSiteConfiguration();
        // Unwrap _HOST into the FQDN to make the kerberos principal we'll compare against
        final String kerberosPrincipal = SecurityUtil
                .getServerPrincipal(conf.get(Property.GENERAL_KERBEROS_PRINCIPAL));
        UserGroupInformation loginUser;
        try {
            // The system user should be logged in via keytab when the process is started, not the
            // currentUser() like KerberosToken
            loginUser = UserGroupInformation.getLoginUser();
        } catch (IOException e) {
            throw new RuntimeException("Could not get login user", e);
        }

        checkArgument(loginUser.hasKerberosCredentials(), "Server does not have Kerberos credentials");
        checkArgument(kerberosPrincipal.equals(loginUser.getUserName()),
                "Expected login user to be " + kerberosPrincipal + " but was " + loginUser.getUserName());
    }

    public VolumeManager getVolumeManager() {
        return info.getVolumeManager();
    }

    public ZooReaderWriter getZooReaderWriter() {
        return zooReaderWriter;
    }

    /**
     * Retrieve the SSL/TLS configuration for starting up a listening service
     */
    public SslConnectionParams getServerSslParams() {
        return SslConnectionParams.forServer(getConfiguration());
    }

    @Override
    public SaslServerConnectionParams getSaslParams() {
        AccumuloConfiguration conf = getServerConfFactory().getSiteConfiguration();
        if (!conf.getBoolean(Property.INSTANCE_RPC_SASL_ENABLED)) {
            return null;
        }
        return new SaslServerConnectionParams(conf, getCredentials().getToken(), secretManager);
    }

    /**
     * Determine the type of Thrift server to instantiate given the server's configuration.
     *
     * @return A {@link ThriftServerType} value to denote the type of Thrift server to construct
     */
    public ThriftServerType getThriftServerType() {
        AccumuloConfiguration conf = getConfiguration();
        if (conf.getBoolean(Property.INSTANCE_RPC_SSL_ENABLED)) {
            if (conf.getBoolean(Property.INSTANCE_RPC_SASL_ENABLED)) {
                throw new IllegalStateException("Cannot create a Thrift server capable of both SASL and SSL");
            }

            return ThriftServerType.SSL;
        } else if (conf.getBoolean(Property.INSTANCE_RPC_SASL_ENABLED)) {
            if (conf.getBoolean(Property.INSTANCE_RPC_SSL_ENABLED)) {
                throw new IllegalStateException("Cannot create a Thrift server capable of both SASL and SSL");
            }

            return ThriftServerType.SASL;
        } else {
            // Lets us control the type of Thrift server created, primarily for benchmarking purposes
            String serverTypeName = conf.get(Property.GENERAL_RPC_SERVER_TYPE);
            return ThriftServerType.get(serverTypeName);
        }
    }

    public void setSecretManager(AuthenticationTokenSecretManager secretManager) {
        this.secretManager = secretManager;
    }

    public AuthenticationTokenSecretManager getSecretManager() {
        return secretManager;
    }

    public synchronized TableManager getTableManager() {
        if (tableManager == null) {
            tableManager = new TableManager(this);
        }
        return tableManager;
    }

    public synchronized UniqueNameAllocator getUniqueNameAllocator() {
        if (nameAllocator == null) {
            nameAllocator = new UniqueNameAllocator(this);
        }
        return nameAllocator;
    }

    public CryptoService getCryptoService() {
        if (cryptoService == null) {
            throw new CryptoService.CryptoException("Crypto service not initialized.");
        }
        return cryptoService;
    }
}