You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by sj...@apache.org on 2016/05/12 17:13:49 UTC
hadoop git commit: YARN-4577. Enable aux services to have their own
custom classpath/jar file (Xuan Gong via sale)
Repository: hadoop
Updated Branches:
refs/heads/trunk 3f2816ab5 -> 0bbe01f8d
YARN-4577. Enable aux services to have their own custom classpath/jar file (Xuan Gong via sale)
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/0bbe01f8
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/0bbe01f8
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/0bbe01f8
Branch: refs/heads/trunk
Commit: 0bbe01f8d56191edfba3b50fb9f8859a0b3f826f
Parents: 3f2816a
Author: Sangjin Lee <sj...@apache.org>
Authored: Thu May 12 10:10:01 2016 -0700
Committer: Sangjin Lee <sj...@apache.org>
Committed: Thu May 12 10:11:23 2016 -0700
----------------------------------------------------------------------
.../java/org/apache/hadoop/util/JarFinder.java | 26 ++-
.../java/org/apache/hadoop/util/TestRunJar.java | 29 +--
.../hadoop/yarn/conf/YarnConfiguration.java | 10 +-
.../containermanager/AuxServices.java | 43 ++--
.../AuxiliaryServiceWithCustomClassLoader.java | 201 +++++++++++++++++++
.../containermanager/TestAuxServices.java | 119 ++++++++++-
6 files changed, 385 insertions(+), 43 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hadoop/blob/0bbe01f8/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/JarFinder.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/JarFinder.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/JarFinder.java
index 33aa025..478a29b 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/JarFinder.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/JarFinder.java
@@ -14,7 +14,7 @@
package org.apache.hadoop.util;
import com.google.common.base.Preconditions;
-
+import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -173,4 +173,28 @@ public class JarFinder {
}
return null;
}
+
+ public static File makeClassLoaderTestJar(Class<?> target, File rootDir,
+ String jarName, int buffSize, String... clsNames) throws IOException {
+ File jarFile = new File(rootDir, jarName);
+ JarOutputStream jstream =
+ new JarOutputStream(new FileOutputStream(jarFile));
+ for (String clsName: clsNames) {
+ String name = clsName.replace('.', '/') + ".class";
+ InputStream entryInputStream = target.getResourceAsStream(
+ "/" + name);
+ ZipEntry entry = new ZipEntry(name);
+ jstream.putNextEntry(entry);
+ BufferedInputStream bufInputStream = new BufferedInputStream(
+ entryInputStream, buffSize);
+ int count;
+ byte[] data = new byte[buffSize];
+ while ((count = bufInputStream.read(data, 0, buffSize)) != -1) {
+ jstream.write(data, 0, count);
+ }
+ jstream.closeEntry();
+ }
+ jstream.close();
+ return jarFile;
+ }
}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/0bbe01f8/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestRunJar.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestRunJar.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestRunJar.java
index 6622389..7b61b32 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestRunJar.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestRunJar.java
@@ -23,11 +23,9 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.util.jar.JarOutputStream;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
@@ -156,7 +154,8 @@ public class TestRunJar {
when(runJar.getSystemClasses()).thenReturn(systemClasses);
// create the test jar
- File testJar = makeClassLoaderTestJar(mainCls, thirdCls);
+ File testJar = JarFinder.makeClassLoaderTestJar(this.getClass(),
+ TEST_ROOT_DIR, TEST_JAR_2_NAME, BUFF_SIZE, mainCls, thirdCls);
// form the args
String[] args = new String[3];
args[0] = testJar.getAbsolutePath();
@@ -166,28 +165,4 @@ public class TestRunJar {
runJar.run(args);
// it should not throw an exception
}
-
- private File makeClassLoaderTestJar(String... clsNames) throws IOException {
- File jarFile = new File(TEST_ROOT_DIR, TEST_JAR_2_NAME);
- JarOutputStream jstream =
- new JarOutputStream(new FileOutputStream(jarFile));
- for (String clsName: clsNames) {
- String name = clsName.replace('.', '/') + ".class";
- InputStream entryInputStream = this.getClass().getResourceAsStream(
- "/" + name);
- ZipEntry entry = new ZipEntry(name);
- jstream.putNextEntry(entry);
- BufferedInputStream bufInputStream = new BufferedInputStream(
- entryInputStream, BUFF_SIZE);
- int count;
- byte[] data = new byte[BUFF_SIZE];
- while ((count = bufInputStream.read(data, 0, BUFF_SIZE)) != -1) {
- jstream.write(data, 0, count);
- }
- jstream.closeEntry();
- }
- jstream.close();
-
- return jarFile;
- }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hadoop/blob/0bbe01f8/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
index 965b6c5..e9c8ea9 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java
@@ -1451,10 +1451,16 @@ public class YarnConfiguration extends Configuration {
NM_PREFIX + "principal";
public static final String NM_AUX_SERVICES =
- NM_PREFIX + "aux-services";
+ NM_PREFIX + "aux-services";
public static final String NM_AUX_SERVICE_FMT =
- NM_PREFIX + "aux-services.%s.class";
+ NM_PREFIX + "aux-services.%s.class";
+
+ public static final String NM_AUX_SERVICES_CLASSPATH =
+ NM_AUX_SERVICES + ".%s.classpath";
+
+ public static final String NM_AUX_SERVICES_SYSTEM_CLASSES =
+ NM_AUX_SERVICES + ".%s.system-classes";
public static final String NM_USER_HOME_DIR =
NM_PREFIX + "user-home-dir";
http://git-wip-us.apache.org/repos/asf/hadoop/blob/0bbe01f8/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/AuxServices.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/AuxServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/AuxServices.java
index cd5ed88..171b20d 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/AuxServices.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/AuxServices.java
@@ -118,21 +118,40 @@ public class AuxServices extends AbstractService
YarnConfiguration.NM_AUX_SERVICES +" is invalid." +
"The valid service name should only contain a-zA-Z0-9_ " +
"and can not start with numbers");
- Class<? extends AuxiliaryService> sClass = conf.getClass(
- String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, sName), null,
- AuxiliaryService.class);
- if (null == sClass) {
- throw new RuntimeException("No class defined for " + sName);
+ String classKey = String.format(
+ YarnConfiguration.NM_AUX_SERVICE_FMT, sName);
+ String className = conf.get(classKey);
+ final String appClassPath = conf.get(String.format(
+ YarnConfiguration.NM_AUX_SERVICES_CLASSPATH, sName));
+ AuxiliaryService s = null;
+ boolean useCustomerClassLoader = appClassPath != null
+ && !appClassPath.isEmpty() && className != null
+ && !className.isEmpty();
+ if (useCustomerClassLoader) {
+ s = AuxiliaryServiceWithCustomClassLoader.getInstance(
+ conf, className, appClassPath);
+ LOG.info("The aux service:" + sName
+ + " are using the custom classloader");
+ } else {
+ Class<? extends AuxiliaryService> sClass = conf.getClass(
+ classKey, null, AuxiliaryService.class);
+
+ if (sClass == null) {
+ throw new RuntimeException("No class defined for " + sName);
+ }
+ s = ReflectionUtils.newInstance(sClass, conf);
+ }
+ if (s == null) {
+ throw new RuntimeException("No object created for " + sName);
}
- AuxiliaryService s = ReflectionUtils.newInstance(sClass, conf);
// TODO better use s.getName()?
if(!sName.equals(s.getName())) {
LOG.warn("The Auxilurary Service named '"+sName+"' in the "
- +"configuration is for "+sClass+" which has "
- +"a name of '"+s.getName()+"'. Because these are "
- +"not the same tools trying to send ServiceData and read "
- +"Service Meta Data may have issues unless the refer to "
- +"the name in the config.");
+ +"configuration is for "+s.getClass()+" which has "
+ +"a name of '"+s.getName()+"'. Because these are "
+ +"not the same tools trying to send ServiceData and read "
+ +"Service Meta Data may have issues unless the refer to "
+ +"the name in the config.");
}
addService(sName, s);
if (recoveryEnabled) {
@@ -264,4 +283,4 @@ public class AuxServices extends AbstractService
: "The auxService name is " + service.getName())
+ " and it got an error at event: " + eventType, th);
}
-}
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hadoop/blob/0bbe01f8/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/AuxiliaryServiceWithCustomClassLoader.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/AuxiliaryServiceWithCustomClassLoader.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/AuxiliaryServiceWithCustomClassLoader.java
new file mode 100644
index 0000000..c764fbd
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/AuxiliaryServiceWithCustomClassLoader.java
@@ -0,0 +1,201 @@
+/**
+* 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.nodemanager.containermanager;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Arrays;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.util.ApplicationClassLoader;
+import org.apache.hadoop.util.ReflectionUtils;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
+import org.apache.hadoop.yarn.server.api.ApplicationInitializationContext;
+import org.apache.hadoop.yarn.server.api.ApplicationTerminationContext;
+import org.apache.hadoop.yarn.server.api.AuxiliaryService;
+import org.apache.hadoop.yarn.server.api.ContainerInitializationContext;
+import org.apache.hadoop.yarn.server.api.ContainerTerminationContext;
+
+final class AuxiliaryServiceWithCustomClassLoader extends AuxiliaryService {
+
+ private final AuxiliaryService wrapped;
+ private final ClassLoader customClassLoader;
+
+ private AuxiliaryServiceWithCustomClassLoader(String name,
+ AuxiliaryService wrapped, ClassLoader customClassLoader) {
+ super(name);
+ this.wrapped = wrapped;
+ this.customClassLoader = customClassLoader;
+ }
+
+ @Override
+ protected void serviceInit(Configuration conf) throws Exception {
+ // We pass a shared configuration as part of serviceInit call.
+ // To avoid the scenario that we could get a ClassNotFoundException
+ // when we use customClassLoader to load the class, we create a copy
+ // of the configuration.
+ Configuration config = new Configuration(conf);
+ // reset the service configuration
+ setConfig(config);
+ config.setClassLoader(customClassLoader);
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(customClassLoader);
+ try {
+ wrapped.init(config);
+ } finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ }
+
+ @Override
+ protected void serviceStart() throws Exception {
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(customClassLoader);
+ try {
+ wrapped.start();
+ } finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ }
+
+ @Override
+ protected void serviceStop() throws Exception {
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(customClassLoader);
+ try {
+ wrapped.stop();
+ } finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ }
+
+ @Override
+ public void initializeApplication(
+ ApplicationInitializationContext initAppContext) {
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(customClassLoader);
+ try {
+ wrapped.initializeApplication(initAppContext);
+ } finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ }
+
+ @Override
+ public void stopApplication(ApplicationTerminationContext stopAppContext) {
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(customClassLoader);
+ try {
+ wrapped.stopApplication(stopAppContext);
+ } finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ }
+
+ @Override
+ public ByteBuffer getMetaData() {
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(customClassLoader);
+ try {
+ return wrapped.getMetaData();
+ } finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ }
+
+ @Override
+ public void initializeContainer(ContainerInitializationContext
+ initContainerContext) {
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(customClassLoader);
+ try {
+ wrapped.initializeContainer(initContainerContext);
+ } finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ }
+
+ @Override
+ public void stopContainer(ContainerTerminationContext stopContainerContext) {
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(customClassLoader);
+ try {
+ wrapped.stopContainer(stopContainerContext);
+ } finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ }
+
+ @Override
+ public void setRecoveryPath(Path recoveryPath) {
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(customClassLoader);
+ try {
+ wrapped.setRecoveryPath(recoveryPath);
+ } finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ }
+
+ public static AuxiliaryServiceWithCustomClassLoader getInstance(
+ Configuration conf, String className, String appClassPath)
+ throws IOException, ClassNotFoundException {
+ String[] systemClasses = conf.getTrimmedStrings(String.format(
+ YarnConfiguration.NM_AUX_SERVICES_SYSTEM_CLASSES,
+ className));
+ ClassLoader customClassLoader = createAuxServiceClassLoader(
+ appClassPath, systemClasses);
+ Class<?> clazz = Class.forName(className, true,
+ customClassLoader);
+ Class<? extends AuxiliaryService> sClass = clazz.asSubclass(
+ AuxiliaryService.class);
+ AuxiliaryService wrapped = ReflectionUtils.newInstance(sClass, conf);
+ return new AuxiliaryServiceWithCustomClassLoader(
+ className + " with custom class loader", wrapped,
+ customClassLoader);
+ }
+
+ private static ClassLoader createAuxServiceClassLoader(
+ final String appClasspath, final String[] systemClasses)
+ throws IOException {
+ try {
+ return AccessController.doPrivileged(
+ new PrivilegedExceptionAction<ClassLoader>() {
+ @Override
+ public ClassLoader run() throws MalformedURLException {
+ return new ApplicationClassLoader(appClasspath,
+ AuxServices.class.getClassLoader(),
+ Arrays.asList(systemClasses));
+ }
+ }
+ );
+ } catch (PrivilegedActionException e) {
+ Throwable t = e.getCause();
+ if (t instanceof MalformedURLException) {
+ throw (MalformedURLException) t;
+ }
+ throw new IOException(e);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hadoop/blob/0bbe01f8/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/TestAuxServices.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/TestAuxServices.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/TestAuxServices.java
index 9d0d0c0..26a1003 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/TestAuxServices.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/TestAuxServices.java
@@ -27,13 +27,21 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
+import com.google.common.base.Charsets;
+import com.google.common.collect.Sets;
import java.io.File;
import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
-
+import java.util.Map.Entry;
+import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
@@ -42,6 +50,10 @@ import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.service.Service;
+import org.apache.hadoop.test.GenericTestUtils;
+import org.apache.hadoop.util.ApplicationClassLoader;
+import org.apache.hadoop.util.JarFinder;
+import org.apache.hadoop.util.StringUtils;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ContainerId;
@@ -150,6 +162,111 @@ public class TestAuxServices {
}
}
+ // Override getMetaData() method to return current
+ // class path. This class would be used for
+ // testCustomizedAuxServiceClassPath.
+ static class ServiceC extends LightService {
+ public ServiceC() {
+ super("C", 'C', 66, ByteBuffer.wrap("C".getBytes()));
+ }
+
+ @Override
+ public ByteBuffer getMetaData() {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ URL[] urls = ((URLClassLoader)loader).getURLs();
+ List<String> urlString = new ArrayList<String>();
+ for (URL url : urls) {
+ urlString.add(url.toString());
+ }
+ String joinedString = StringUtils.join(",", urlString);
+ return ByteBuffer.wrap(joinedString.getBytes());
+ }
+ }
+
+ // To verify whether we could load class from customized class path.
+ // We would use ServiceC in this test. Also create a separate jar file
+ // including ServiceC class, and add this jar to customized directory.
+ // By setting some proper configurations, we should load ServiceC class
+ // from customized class path.
+ @Test (timeout = 15000)
+ public void testCustomizedAuxServiceClassPath() throws Exception {
+ // verify that we can load AuxService Class from default Class path
+ Configuration conf = new YarnConfiguration();
+ conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
+ new String[] {"ServiceC"});
+ conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT,
+ "ServiceC"), ServiceC.class, Service.class);
+ @SuppressWarnings("resource")
+ AuxServices aux = new AuxServices();
+ aux.init(conf);
+ aux.start();
+ Map<String, ByteBuffer> meta = aux.getMetaData();
+ String auxName = "";
+ Set<String> defaultAuxClassPath = null;
+ Assert.assertTrue(meta.size() == 1);
+ for(Entry<String, ByteBuffer> i : meta.entrySet()) {
+ auxName = i.getKey();
+ String auxClassPath = Charsets.UTF_8.decode(i.getValue()).toString();
+ defaultAuxClassPath = new HashSet<String>(Arrays.asList(StringUtils
+ .getTrimmedStrings(auxClassPath)));
+ }
+ Assert.assertTrue(auxName.equals("ServiceC"));
+ aux.serviceStop();
+
+ // create a new jar file, and configure it as customized class path
+ // for this AuxService, and make sure that we could load the class
+ // from this configured customized class path
+ File rootDir = GenericTestUtils.getTestDir(getClass()
+ .getSimpleName());
+ if (!rootDir.exists()) {
+ rootDir.mkdirs();
+ }
+ File testJar = null;
+ try {
+ testJar = JarFinder.makeClassLoaderTestJar(this.getClass(), rootDir,
+ "test-runjar.jar", 2048, ServiceC.class.getName());
+ conf = new YarnConfiguration();
+ conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
+ new String[] {"ServiceC"});
+ conf.set(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT, "ServiceC"),
+ ServiceC.class.getName());
+ conf.set(String.format(
+ YarnConfiguration.NM_AUX_SERVICES_CLASSPATH, "ServiceC"),
+ testJar.getAbsolutePath());
+ // remove "-org.apache.hadoop." from system classes
+ String systemClasses = "-org.apache.hadoop." + "," +
+ ApplicationClassLoader.SYSTEM_CLASSES_DEFAULT;
+ conf.set(String.format(
+ YarnConfiguration.NM_AUX_SERVICES_SYSTEM_CLASSES,
+ "ServiceC"), systemClasses);
+ aux = new AuxServices();
+ aux.init(conf);
+ aux.start();
+ meta = aux.getMetaData();
+ Assert.assertTrue(meta.size() == 1);
+ Set<String> customizedAuxClassPath = null;
+ for(Entry<String, ByteBuffer> i : meta.entrySet()) {
+ Assert.assertTrue(auxName.equals(i.getKey()));
+ String classPath = Charsets.UTF_8.decode(i.getValue()).toString();
+ customizedAuxClassPath = new HashSet<String>(Arrays.asList(StringUtils
+ .getTrimmedStrings(classPath)));
+ Assert.assertTrue(classPath.contains(testJar.getName()));
+ }
+ aux.stop();
+
+ // Verify that we do not have any overlap between customized class path
+ // and the default class path.
+ Set<String> mutalClassPath = Sets.intersection(defaultAuxClassPath,
+ customizedAuxClassPath);
+ Assert.assertTrue(mutalClassPath.isEmpty());
+ } finally {
+ if (testJar != null) {
+ testJar.delete();
+ rootDir.delete();
+ }
+ }
+ }
+
@Test
public void testAuxEventDispatch() {
Configuration conf = new Configuration();
---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org