/* * Copyright 2013 the original author or authors. * * Licensed 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.springframework.yarn.rpc; import java.io.IOException; import java.net.InetSocketAddress; import java.security.PrivilegedAction; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.ipc.RPC; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.yarn.exceptions.YarnRuntimeException; import org.apache.hadoop.yarn.ipc.YarnRPC; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataAccessException; import org.springframework.util.Assert; import org.springframework.yarn.support.YarnUtils; /** * Base implementation for accessing yarn components over * protocol buffer rpc system. * * @author Janne Valkealahti * * @param <P> Type of the protocol buffer implementation */ public abstract class YarnRpcAccessor<P> implements InitializingBean, DisposableBean { /** Protocol class used to create rpc connection */ private Class<P> protocolClazz; /** Yarn configuration */ private Configuration configuration; /** Address for rpc end point */ private InetSocketAddress address; /** Created proxy */ private P proxy; /** * Instantiates a new yarn rpc accessor with a protocol class * and Yarn configuration. * * @param protocolClazz the protocol clazz * @param config the yarn configuration */ public YarnRpcAccessor(Class<P> protocolClazz, Configuration config) { this.protocolClazz = protocolClazz; this.configuration = config; } @Override public void afterPropertiesSet() throws Exception { Assert.notNull(configuration, "Yarn configuration must be set"); Assert.notNull(protocolClazz, "Rpc protocol class must be set"); if (UserGroupInformation.isSecurityEnabled()) { UserGroupInformation.setConfiguration(configuration); } address = getRpcAddress(configuration); proxy = createProxy(); } @Override public void destroy() { RPC.stopProxy(proxy); } /** * Gets the proxy handled by this accessor. * * @return the proxy */ public P getProxy() { return proxy; } /** * Execute given action callback on the rpc proxy. * * @param <T> the return type * @param <S> the proxy type * @param action the action * @return the result from a callback execution * @throws DataAccessException the data access exception */ public <T, S extends P> T execute(YarnRpcCallback<T, S> action) throws DataAccessException { @SuppressWarnings("unchecked") S proxy = (S) getProxy(); try { T result = action.doInYarn(proxy); return result; } catch (YarnException e) { throw YarnUtils.convertYarnAccessException(e); } catch (YarnRuntimeException e) { throw YarnUtils.convertYarnAccessException(e); } catch (IOException e) { throw YarnUtils.convertYarnAccessException(e); } catch (RuntimeException e) { throw e; } } /** * Gets the Yarn configuration. * * @return the Yarn configuration */ public Configuration getConfiguration() { return configuration; } /** * Creates the proxy. If {@link #getUser()} returns * a non null {@link UserGroupInformation user}, that * will be used to request the proxy with * a {@link PrivilegedAction}. * * @return the proxy * @throws IOException if creation fails */ @SuppressWarnings("unchecked") protected P createProxy() throws IOException { return getUser().doAs(new PrivilegedAction<P>() { @Override public P run() { return (P) YarnRPC.create(configuration).getProxy(protocolClazz, address, configuration); } }); } /** * Gets the {@link UserGroupInformation user} used to * create the proxy. Default implementation delegates into * {@link UserGroupInformation#getCurrentUser()}. * * @return the user * @throws IOException if login fails * @see #createProxy() */ protected UserGroupInformation getUser() throws IOException { return UserGroupInformation.getCurrentUser(); } /** * Gets the {@link InetSocketAddress} where this accessor should connect. * * @param configuration the yarn configuration * @return address of rpc endpoint */ protected abstract InetSocketAddress getRpcAddress(Configuration configuration); }