diff --git a/hadoop-mapreduce-project/CHANGES.txt b/hadoop-mapreduce-project/CHANGES.txt
index 95b401bd47f..926161a9b2d 100644
--- a/hadoop-mapreduce-project/CHANGES.txt
+++ b/hadoop-mapreduce-project/CHANGES.txt
@@ -172,6 +172,9 @@ Release 0.23.1 - Unreleased
MAPREDUCE-3391. Making a trivial change to correct a log message in
DistributedShell app's AM. (Subroto Sanyal via vinodkv)
+ MAPREDUCE-3547. Added a bunch of unit tests for the the RM/NM webservices.
+ (Thomas Graves via acmurthy)
+
OPTIMIZATIONS
MAPREDUCE-3567. Extraneous JobConf objects in AM heap. (Vinod Kumar
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/webapp/WebServicesTestUtils.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/webapp/WebServicesTestUtils.java
new file mode 100644
index 00000000000..2cb67724b99
--- /dev/null
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/webapp/WebServicesTestUtils.java
@@ -0,0 +1,79 @@
+/**
+ * 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.webapp;
+
+import static org.junit.Assert.assertTrue;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class WebServicesTestUtils {
+
+ public static long getXmlLong(Element element, String name) {
+ String val = getXmlString(element, name);
+ return Long.parseLong(val);
+ }
+
+ public static int getXmlInt(Element element, String name) {
+ String val = getXmlString(element, name);
+ return Integer.parseInt(val);
+ }
+
+ public static Boolean getXmlBoolean(Element element, String name) {
+ String val = getXmlString(element, name);
+ return Boolean.parseBoolean(val);
+ }
+
+ public static float getXmlFloat(Element element, String name) {
+ String val = getXmlString(element, name);
+ return Float.parseFloat(val);
+ }
+
+ public static String getXmlString(Element element, String name) {
+ NodeList id = element.getElementsByTagName(name);
+ Element line = (Element) id.item(0);
+ Node first = line.getFirstChild();
+ // handle empty
+ if (first == null) {
+ return "";
+ }
+ String val = first.getNodeValue();
+ if (val == null) {
+ return "";
+ }
+ return val;
+ }
+
+ public static String getXmlAttrString(Element element, String name) {
+ Attr at = element.getAttributeNode(name);
+ if (at != null) {
+ return at.getValue();
+ }
+ return null;
+ }
+
+ public static void checkStringMatch(String print, String expected, String got) {
+ assertTrue(
+ print + " doesn't match, got: " + got + " expected: " + expected,
+ got.matches(expected));
+ }
+
+}
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java
index 9f7b90189a7..909679606de 100644
--- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/NMWebServices.java
@@ -42,6 +42,7 @@ import org.apache.hadoop.yarn.server.nodemanager.webapp.dao.ContainerInfo;
import org.apache.hadoop.yarn.server.nodemanager.webapp.dao.ContainersInfo;
import org.apache.hadoop.yarn.server.nodemanager.webapp.dao.NodeInfo;
import org.apache.hadoop.yarn.util.ConverterUtils;
+import org.apache.hadoop.yarn.webapp.BadRequestException;
import org.apache.hadoop.yarn.webapp.NotFoundException;
import org.apache.hadoop.yarn.webapp.WebApp;
@@ -92,12 +93,16 @@ public class NMWebServices {
AppInfo appInfo = new AppInfo(entry.getValue());
if (stateQuery != null && !stateQuery.isEmpty()) {
- ApplicationState state = ApplicationState.valueOf(stateQuery);
+ ApplicationState.valueOf(stateQuery);
if (!appInfo.getState().equalsIgnoreCase(stateQuery)) {
continue;
}
}
- if (userQuery != null && !userQuery.isEmpty()) {
+ if (userQuery != null) {
+ if (userQuery.isEmpty()) {
+ String msg = "Error: You must specify a non-empty string for the user";
+ throw new BadRequestException(msg);
+ }
if (!appInfo.getUser().toString().equals(userQuery)) {
continue;
}
@@ -146,11 +151,12 @@ public class NMWebServices {
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public ContainerInfo getNodeContainer(@PathParam("containerid") String id) {
ContainerId containerId = null;
- containerId = ConverterUtils.toContainerId(id);
- if (containerId == null) {
- throw new NotFoundException("container with id, " + id
- + ", is empty or null");
+ try {
+ containerId = ConverterUtils.toContainerId(id);
+ } catch (Exception e) {
+ throw new BadRequestException("invalid container id, " + id);
}
+
Container container = nmContext.getContainers().get(containerId);
if (container == null) {
throw new NotFoundException("container with id, " + id + ", not found");
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/dao/ContainerInfo.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/dao/ContainerInfo.java
index 5c79a7b52c1..41c649eea2c 100644
--- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/dao/ContainerInfo.java
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/webapp/dao/ContainerInfo.java
@@ -27,6 +27,7 @@ import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import org.apache.hadoop.yarn.api.records.ContainerStatus;
+import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.server.nodemanager.Context;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
@@ -56,7 +57,7 @@ public class ContainerInfo {
}
public ContainerInfo(final Context nmContext, final Container container,
- final String requestUri, final String pathPrefix) {
+ String requestUri, String pathPrefix) {
this.id = container.getContainerID().toString();
this.nodeId = nmContext.getNodeId().toString();
@@ -71,10 +72,19 @@ public class ContainerInfo {
}
this.user = container.getUser();
- this.totalMemoryNeededMB = container.getLaunchContext().getResource()
- .getMemory();
+ Resource res = container.getLaunchContext().getResource();
+ if (res != null) {
+ this.totalMemoryNeededMB = res.getMemory();
+ }
this.containerLogsShortLink = ujoin("containerlogs", this.id,
container.getUser());
+
+ if (requestUri == null) {
+ requestUri = "";
+ }
+ if (pathPrefix == null) {
+ pathPrefix = "";
+ }
this.containerLogsLink = join(requestUri, pathPrefix,
this.containerLogsShortLink);
}
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/MockApp.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/MockApp.java
new file mode 100644
index 00000000000..7a9dac69483
--- /dev/null
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/MockApp.java
@@ -0,0 +1,83 @@
+/**
+ * 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;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.yarn.api.records.ApplicationId;
+import org.apache.hadoop.yarn.api.records.ContainerId;
+import org.apache.hadoop.yarn.factories.RecordFactory;
+import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.Application;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.ApplicationEvent;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.ApplicationState;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
+import org.apache.hadoop.yarn.util.BuilderUtils;
+
+public class MockApp implements Application {
+
+ final String user;
+ final ApplicationId appId;
+ Map containers = new HashMap();
+ ApplicationState appState;
+ Application app;
+
+ public MockApp(int uniqId) {
+ this("mockUser", 1234, uniqId);
+ }
+
+ public MockApp(String user, long clusterTimeStamp, int uniqId) {
+ super();
+ this.user = user;
+ // Add an application and the corresponding containers
+ RecordFactory recordFactory = RecordFactoryProvider
+ .getRecordFactory(new Configuration());
+ this.appId = BuilderUtils.newApplicationId(recordFactory, clusterTimeStamp,
+ uniqId);
+ appState = ApplicationState.NEW;
+ }
+
+ public void setState(ApplicationState state) {
+ this.appState = state;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public Map getContainers() {
+ return containers;
+ }
+
+ public ApplicationId getAppId() {
+ return appId;
+ }
+
+ public ApplicationState getApplicationState() {
+ return appState;
+ }
+
+ public void handle(ApplicationEvent event) {}
+
+}
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/MockContainer.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/MockContainer.java
new file mode 100644
index 00000000000..eacdb1c4241
--- /dev/null
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/MockContainer.java
@@ -0,0 +1,120 @@
+/**
+ * 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;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.Credentials;
+import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
+import org.apache.hadoop.yarn.api.records.ApplicationId;
+import org.apache.hadoop.yarn.api.records.ContainerId;
+import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
+import org.apache.hadoop.yarn.api.records.ContainerStatus;
+import org.apache.hadoop.yarn.event.Dispatcher;
+import org.apache.hadoop.yarn.factories.RecordFactory;
+import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.ContainerEvent;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.ContainerState;
+import org.apache.hadoop.yarn.util.BuilderUtils;
+
+public class MockContainer implements Container {
+
+ private ContainerId id;
+ private ContainerState state;
+ private String user;
+ private ContainerLaunchContext launchContext;
+ private final Map resource = new HashMap();
+ private RecordFactory recordFactory;
+
+ public MockContainer(ApplicationAttemptId appAttemptId,
+ Dispatcher dispatcher, Configuration conf, String user,
+ ApplicationId appId, int uniqId) {
+
+ this.user = user;
+ this.recordFactory = RecordFactoryProvider.getRecordFactory(conf);
+ this.id = BuilderUtils.newContainerId(recordFactory, appId, appAttemptId,
+ uniqId);
+ this.launchContext = recordFactory
+ .newRecordInstance(ContainerLaunchContext.class);
+ launchContext.setContainerId(id);
+ launchContext.setUser(user);
+ this.state = ContainerState.NEW;
+
+ }
+
+ public void setState(ContainerState state) {
+ this.state = state;
+ }
+
+ @Override
+ public ContainerId getContainerID() {
+ return id;
+ }
+
+ @Override
+ public String getUser() {
+ return user;
+ }
+
+ @Override
+ public ContainerState getContainerState() {
+ return state;
+ }
+
+ @Override
+ public ContainerLaunchContext getLaunchContext() {
+ return launchContext;
+ }
+
+ @Override
+ public Credentials getCredentials() {
+ return null;
+ }
+
+ @Override
+ public Map getLocalizedResources() {
+ return resource;
+ }
+
+ @Override
+ public ContainerStatus cloneAndGetContainerStatus() {
+ ContainerStatus containerStatus = recordFactory
+ .newRecordInstance(ContainerStatus.class);
+ containerStatus
+ .setState(org.apache.hadoop.yarn.api.records.ContainerState.RUNNING);
+ containerStatus.setContainerId(this.launchContext.getContainerId());
+ containerStatus.setDiagnostics("testing");
+ containerStatus.setExitStatus(0);
+ return containerStatus;
+ }
+
+ @Override
+ public String toString() {
+ return "";
+ }
+
+ @Override
+ public void handle(ContainerEvent event) {
+ }
+
+}
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/TestNMWebServices.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/TestNMWebServices.java
new file mode 100644
index 00000000000..3b1d2cf81c7
--- /dev/null
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/TestNMWebServices.java
@@ -0,0 +1,361 @@
+/**
+ * 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.webapp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.StringReader;
+
+import javax.ws.rs.core.MediaType;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileUtil;
+import org.apache.hadoop.util.VersionInfo;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
+import org.apache.hadoop.yarn.server.nodemanager.Context;
+import org.apache.hadoop.yarn.server.nodemanager.LocalDirsHandlerService;
+import org.apache.hadoop.yarn.server.nodemanager.NodeHealthCheckerService;
+import org.apache.hadoop.yarn.server.nodemanager.NodeManager;
+import org.apache.hadoop.yarn.server.nodemanager.ResourceView;
+import org.apache.hadoop.yarn.server.nodemanager.webapp.WebServer.NMWebApp;
+import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
+import org.apache.hadoop.yarn.util.YarnVersionInfo;
+import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
+import org.apache.hadoop.yarn.webapp.WebApp;
+import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.servlet.GuiceServletContextListener;
+import com.google.inject.servlet.ServletModule;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.ClientResponse.Status;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+
+/**
+ * Test the nodemanager node info web services api's
+ */
+public class TestNMWebServices extends JerseyTest {
+
+ private static Context nmContext;
+ private static ResourceView resourceView;
+ private static ApplicationACLsManager aclsManager;
+ private static LocalDirsHandlerService dirsHandler;
+ private static WebApp nmWebApp;
+
+ private static final File testRootDir = new File("target",
+ TestNMWebServices.class.getSimpleName());
+ private static File testLogDir = new File("target",
+ TestNMWebServices.class.getSimpleName() + "LogDir");
+
+ private Injector injector = Guice.createInjector(new ServletModule() {
+ @Override
+ protected void configureServlets() {
+ nmContext = new NodeManager.NMContext();
+ nmContext.getNodeId().setHost("testhost.foo.com");
+ nmContext.getNodeId().setPort(9999);
+ resourceView = new ResourceView() {
+ @Override
+ public long getVmemAllocatedForContainers() {
+ // 15.5G in bytes
+ return new Long("16642998272");
+ }
+
+ @Override
+ public long getPmemAllocatedForContainers() {
+ // 16G in bytes
+ return new Long("17179869184");
+ }
+ };
+ Configuration conf = new Configuration();
+ conf.set(YarnConfiguration.NM_LOCAL_DIRS, testRootDir.getAbsolutePath());
+ conf.set(YarnConfiguration.NM_LOG_DIRS, testLogDir.getAbsolutePath());
+ NodeHealthCheckerService healthChecker = new NodeHealthCheckerService();
+ healthChecker.init(conf);
+ dirsHandler = healthChecker.getDiskHandler();
+ aclsManager = new ApplicationACLsManager(conf);
+ nmWebApp = new NMWebApp(resourceView, aclsManager, dirsHandler);
+ bind(JAXBContextResolver.class);
+ bind(NMWebServices.class);
+ bind(GenericExceptionHandler.class);
+ bind(Context.class).toInstance(nmContext);
+ bind(WebApp.class).toInstance(nmWebApp);
+ bind(ResourceView.class).toInstance(resourceView);
+ bind(ApplicationACLsManager.class).toInstance(aclsManager);
+ bind(LocalDirsHandlerService.class).toInstance(dirsHandler);
+
+ serve("/*").with(GuiceContainer.class);
+ }
+ });
+
+ public class GuiceServletConfig extends GuiceServletContextListener {
+
+ @Override
+ protected Injector getInjector() {
+ return injector;
+ }
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ testRootDir.mkdirs();
+ testLogDir.mkdir();
+ }
+
+ @AfterClass
+ static public void stop() {
+ FileUtil.fullyDelete(testRootDir);
+ FileUtil.fullyDelete(testLogDir);
+ }
+
+ public TestNMWebServices() {
+ super(new WebAppDescriptor.Builder(
+ "org.apache.hadoop.yarn.server.nodemanager.webapp")
+ .contextListenerClass(GuiceServletConfig.class)
+ .filterClass(com.google.inject.servlet.GuiceFilter.class)
+ .contextPath("jersey-guice-filter").servletPath("/").build());
+ }
+
+ @Test
+ public void testInvalidUri() throws JSONException, Exception {
+ WebResource r = resource();
+ String responseStr = "";
+ try {
+ responseStr = r.path("ws").path("v1").path("node").path("bogus")
+ .accept(MediaType.APPLICATION_JSON).get(String.class);
+ fail("should have thrown exception on invalid uri");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.NOT_FOUND, response.getClientResponseStatus());
+ WebServicesTestUtils.checkStringMatch(
+ "error string exists and shouldn't", "", responseStr);
+ }
+ }
+
+ @Test
+ public void testInvalidAccept() throws JSONException, Exception {
+ WebResource r = resource();
+ String responseStr = "";
+ try {
+ responseStr = r.path("ws").path("v1").path("node")
+ .accept(MediaType.TEXT_PLAIN).get(String.class);
+ fail("should have thrown exception on invalid uri");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.INTERNAL_SERVER_ERROR,
+ response.getClientResponseStatus());
+ WebServicesTestUtils.checkStringMatch(
+ "error string exists and shouldn't", "", responseStr);
+ }
+ }
+
+ @Test
+ public void testInvalidUri2() throws JSONException, Exception {
+ WebResource r = resource();
+ String responseStr = "";
+ try {
+ responseStr = r.accept(MediaType.APPLICATION_JSON).get(String.class);
+ fail("should have thrown exception on invalid uri");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.NOT_FOUND, response.getClientResponseStatus());
+ WebServicesTestUtils.checkStringMatch(
+ "error string exists and shouldn't", "", responseStr);
+ }
+ }
+
+ @Test
+ public void testNode() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("node")
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyNodeInfo(json);
+ }
+
+ @Test
+ public void testNodeSlash() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("node/")
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyNodeInfo(json);
+ }
+
+ // make sure default is json output
+ @Test
+ public void testNodeDefault() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("node")
+ .get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyNodeInfo(json);
+ }
+
+ @Test
+ public void testNodeInfo() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("node").path("info")
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyNodeInfo(json);
+ }
+
+ @Test
+ public void testNodeInfoSlash() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("node")
+ .path("info/").accept(MediaType.APPLICATION_JSON)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyNodeInfo(json);
+ }
+
+ // make sure default is json output
+ @Test
+ public void testNodeInfoDefault() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("node").path("info")
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyNodeInfo(json);
+ }
+
+ @Test
+ public void testSingleNodesXML() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("node")
+ .path("info/").accept(MediaType.APPLICATION_XML)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodes = dom.getElementsByTagName("nodeInfo");
+ assertEquals("incorrect number of elements", 1, nodes.getLength());
+ verifyNodesXML(nodes);
+ }
+
+ public void verifyNodesXML(NodeList nodes) throws JSONException, Exception {
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Element element = (Element) nodes.item(i);
+
+ verifyNodeInfoGeneric(WebServicesTestUtils.getXmlString(element, "id"),
+ WebServicesTestUtils.getXmlString(element, "healthReport"),
+ WebServicesTestUtils.getXmlLong(element,
+ "totalVmemAllocatedContainersMB"),
+ WebServicesTestUtils.getXmlLong(element,
+ "totalPmemAllocatedContainersMB"),
+ WebServicesTestUtils.getXmlLong(element, "lastNodeUpdateTime"),
+ WebServicesTestUtils.getXmlBoolean(element, "nodeHealthy"),
+ WebServicesTestUtils.getXmlString(element, "nodeHostName"),
+ WebServicesTestUtils.getXmlString(element, "hadoopVersionBuiltOn"),
+ WebServicesTestUtils.getXmlString(element, "hadoopBuildVersion"),
+ WebServicesTestUtils.getXmlString(element, "hadoopVersion"),
+ WebServicesTestUtils.getXmlString(element,
+ "nodeManagerVersionBuiltOn"), WebServicesTestUtils.getXmlString(
+ element, "nodeManagerBuildVersion"),
+ WebServicesTestUtils.getXmlString(element, "nodeManagerVersion"));
+ }
+ }
+
+ public void verifyNodeInfo(JSONObject json) throws JSONException, Exception {
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject info = json.getJSONObject("nodeInfo");
+ assertEquals("incorrect number of elements", 13, info.length());
+ verifyNodeInfoGeneric(info.getString("id"), info.getString("healthReport"),
+ info.getLong("totalVmemAllocatedContainersMB"),
+ info.getLong("totalPmemAllocatedContainersMB"),
+ info.getLong("lastNodeUpdateTime"), info.getBoolean("nodeHealthy"),
+ info.getString("nodeHostName"), info.getString("hadoopVersionBuiltOn"),
+ info.getString("hadoopBuildVersion"), info.getString("hadoopVersion"),
+ info.getString("nodeManagerVersionBuiltOn"),
+ info.getString("nodeManagerBuildVersion"),
+ info.getString("nodeManagerVersion"));
+
+ }
+
+ public void verifyNodeInfoGeneric(String id, String healthReport,
+ long totalVmemAllocatedContainersMB, long totalPmemAllocatedContainersMB,
+ long lastNodeUpdateTime, Boolean nodeHealthy, String nodeHostName,
+ String hadoopVersionBuiltOn, String hadoopBuildVersion,
+ String hadoopVersion, String resourceManagerVersionBuiltOn,
+ String resourceManagerBuildVersion, String resourceManagerVersion) {
+
+ WebServicesTestUtils.checkStringMatch("id", "testhost.foo.com:9999", id);
+ WebServicesTestUtils.checkStringMatch("healthReport", "Healthy",
+ healthReport);
+ assertEquals("totalVmemAllocatedContainersMB incorrect", 15872,
+ totalVmemAllocatedContainersMB);
+ assertEquals("totalPmemAllocatedContainersMB incorrect", 16384,
+ totalPmemAllocatedContainersMB);
+ assertTrue("lastNodeUpdateTime incorrect", lastNodeUpdateTime == nmContext
+ .getNodeHealthStatus().getLastHealthReportTime());
+ assertTrue("nodeHealthy isn't true", nodeHealthy);
+ WebServicesTestUtils.checkStringMatch("nodeHostName", "testhost.foo.com",
+ nodeHostName);
+
+ WebServicesTestUtils.checkStringMatch("hadoopVersionBuiltOn",
+ VersionInfo.getDate(), hadoopVersionBuiltOn);
+ WebServicesTestUtils.checkStringMatch("hadoopBuildVersion",
+ VersionInfo.getBuildVersion(), hadoopBuildVersion);
+ WebServicesTestUtils.checkStringMatch("hadoopVersion",
+ VersionInfo.getVersion(), hadoopVersion);
+
+ WebServicesTestUtils.checkStringMatch("resourceManagerVersionBuiltOn",
+ YarnVersionInfo.getDate(), resourceManagerVersionBuiltOn);
+ WebServicesTestUtils.checkStringMatch("resourceManagerBuildVersion",
+ YarnVersionInfo.getBuildVersion(), resourceManagerBuildVersion);
+ WebServicesTestUtils.checkStringMatch("resourceManagerVersion",
+ YarnVersionInfo.getVersion(), resourceManagerVersion);
+ }
+
+}
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/TestNMWebServicesApps.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/TestNMWebServicesApps.java
new file mode 100644
index 00000000000..f61fdbd4761
--- /dev/null
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/TestNMWebServicesApps.java
@@ -0,0 +1,607 @@
+/**
+ * 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.webapp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.StringReader;
+import java.util.HashMap;
+
+import javax.ws.rs.core.MediaType;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileUtil;
+import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
+import org.apache.hadoop.yarn.event.AsyncDispatcher;
+import org.apache.hadoop.yarn.event.Dispatcher;
+import org.apache.hadoop.yarn.server.nodemanager.Context;
+import org.apache.hadoop.yarn.server.nodemanager.LocalDirsHandlerService;
+import org.apache.hadoop.yarn.server.nodemanager.MockApp;
+import org.apache.hadoop.yarn.server.nodemanager.MockContainer;
+import org.apache.hadoop.yarn.server.nodemanager.NodeHealthCheckerService;
+import org.apache.hadoop.yarn.server.nodemanager.NodeManager;
+import org.apache.hadoop.yarn.server.nodemanager.ResourceView;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.Application;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.ApplicationState;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
+import org.apache.hadoop.yarn.server.nodemanager.webapp.WebServer.NMWebApp;
+import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
+import org.apache.hadoop.yarn.util.BuilderUtils;
+import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
+import org.apache.hadoop.yarn.webapp.WebApp;
+import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.servlet.GuiceServletContextListener;
+import com.google.inject.servlet.ServletModule;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.ClientResponse.Status;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+
+public class TestNMWebServicesApps extends JerseyTest {
+
+ private static Context nmContext;
+ private static ResourceView resourceView;
+ private static ApplicationACLsManager aclsManager;
+ private static LocalDirsHandlerService dirsHandler;
+ private static WebApp nmWebApp;
+ private static Configuration conf = new Configuration();
+
+ private static final File testRootDir = new File("target",
+ TestNMWebServicesApps.class.getSimpleName());
+ private static File testLogDir = new File("target",
+ TestNMWebServicesApps.class.getSimpleName() + "LogDir");
+
+ private Injector injector = Guice.createInjector(new ServletModule() {
+ @Override
+ protected void configureServlets() {
+ nmContext = new NodeManager.NMContext();
+ nmContext.getNodeId().setHost("testhost.foo.com");
+ nmContext.getNodeId().setPort(9999);
+ resourceView = new ResourceView() {
+ @Override
+ public long getVmemAllocatedForContainers() {
+ // 15.5G in bytes
+ return new Long("16642998272");
+ }
+
+ @Override
+ public long getPmemAllocatedForContainers() {
+ // 16G in bytes
+ return new Long("17179869184");
+ }
+ };
+ conf.set(YarnConfiguration.NM_LOCAL_DIRS, testRootDir.getAbsolutePath());
+ conf.set(YarnConfiguration.NM_LOG_DIRS, testLogDir.getAbsolutePath());
+ NodeHealthCheckerService healthChecker = new NodeHealthCheckerService();
+ healthChecker.init(conf);
+ dirsHandler = healthChecker.getDiskHandler();
+ aclsManager = new ApplicationACLsManager(conf);
+ nmWebApp = new NMWebApp(resourceView, aclsManager, dirsHandler);
+ bind(JAXBContextResolver.class);
+ bind(NMWebServices.class);
+ bind(GenericExceptionHandler.class);
+ bind(Context.class).toInstance(nmContext);
+ bind(WebApp.class).toInstance(nmWebApp);
+ bind(ResourceView.class).toInstance(resourceView);
+ bind(ApplicationACLsManager.class).toInstance(aclsManager);
+ bind(LocalDirsHandlerService.class).toInstance(dirsHandler);
+
+ serve("/*").with(GuiceContainer.class);
+ }
+ });
+
+ public class GuiceServletConfig extends GuiceServletContextListener {
+
+ @Override
+ protected Injector getInjector() {
+ return injector;
+ }
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ testRootDir.mkdirs();
+ testLogDir.mkdir();
+ }
+
+ @AfterClass
+ static public void cleanup() {
+ FileUtil.fullyDelete(testRootDir);
+ FileUtil.fullyDelete(testLogDir);
+ }
+
+ public TestNMWebServicesApps() {
+ super(new WebAppDescriptor.Builder(
+ "org.apache.hadoop.yarn.server.nodemanager.webapp")
+ .contextListenerClass(GuiceServletConfig.class)
+ .filterClass(com.google.inject.servlet.GuiceFilter.class)
+ .contextPath("jersey-guice-filter").servletPath("/").build());
+ }
+
+ @Test
+ public void testNodeAppsNone() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("node").path("apps")
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("apps isn't NULL", JSONObject.NULL, json.get("apps"));
+ }
+
+ private HashMap addAppContainers(Application app) {
+ Dispatcher dispatcher = new AsyncDispatcher();
+ ApplicationAttemptId appAttemptId = BuilderUtils.newApplicationAttemptId(
+ app.getAppId(), 1);
+ Container container1 = new MockContainer(appAttemptId, dispatcher, conf,
+ app.getUser(), app.getAppId(), 1);
+ Container container2 = new MockContainer(appAttemptId, dispatcher, conf,
+ app.getUser(), app.getAppId(), 2);
+ nmContext.getContainers().put(container1.getContainerID(), container1);
+ nmContext.getContainers().put(container2.getContainerID(), container2);
+
+ app.getContainers().put(container1.getContainerID(), container1);
+ app.getContainers().put(container2.getContainerID(), container2);
+ HashMap hash = new HashMap();
+ hash.put(container1.getContainerID().toString(), container1
+ .getContainerID().toString());
+ hash.put(container2.getContainerID().toString(), container2
+ .getContainerID().toString());
+ return hash;
+ }
+
+ @Test
+ public void testNodeApps() throws JSONException, Exception {
+ testNodeHelper("apps", MediaType.APPLICATION_JSON);
+ }
+
+ @Test
+ public void testNodeAppsSlash() throws JSONException, Exception {
+ testNodeHelper("apps/", MediaType.APPLICATION_JSON);
+ }
+
+ // make sure default is json output
+ @Test
+ public void testNodeAppsDefault() throws JSONException, Exception {
+ testNodeHelper("apps/", "");
+
+ }
+
+ public void testNodeHelper(String path, String media) throws JSONException,
+ Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ HashMap hash = addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ HashMap hash2 = addAppContainers(app2);
+
+ ClientResponse response = r.path("ws").path("v1").path("node").path(path)
+ .accept(media).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ JSONObject info = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, info.length());
+ JSONArray appInfo = info.getJSONArray("app");
+ assertEquals("incorrect number of elements", 2, appInfo.length());
+ String id = appInfo.getJSONObject(0).getString("id");
+ if (id.matches(app.getAppId().toString())) {
+ verifyNodeAppInfo(appInfo.getJSONObject(0), app, hash);
+ verifyNodeAppInfo(appInfo.getJSONObject(1), app2, hash2);
+ } else {
+ verifyNodeAppInfo(appInfo.getJSONObject(0), app2, hash2);
+ verifyNodeAppInfo(appInfo.getJSONObject(1), app, hash);
+ }
+ }
+
+ @Test
+ public void testNodeAppsUser() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ HashMap hash = addAppContainers(app);
+ Application app2 = new MockApp("foo", 1234, 2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ ClientResponse response = r.path("ws").path("v1").path("node").path("apps")
+ .queryParam("user", "mockUser").accept(MediaType.APPLICATION_JSON)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+
+ JSONObject info = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, info.length());
+ JSONArray appInfo = info.getJSONArray("app");
+ assertEquals("incorrect number of elements", 1, appInfo.length());
+ verifyNodeAppInfo(appInfo.getJSONObject(0), app, hash);
+ }
+
+ @Test
+ public void testNodeAppsUserNone() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ Application app2 = new MockApp("foo", 1234, 2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ ClientResponse response = r.path("ws").path("v1").path("node").path("apps")
+ .queryParam("user", "george").accept(MediaType.APPLICATION_JSON)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("apps is not null", JSONObject.NULL, json.get("apps"));
+ }
+
+ @Test
+ public void testNodeAppsUserEmpty() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ Application app2 = new MockApp("foo", 1234, 2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ try {
+ r.path("ws").path("v1").path("node").path("apps").queryParam("user", "")
+ .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
+ fail("should have thrown exception on invalid user query");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+
+ assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils
+ .checkStringMatch(
+ "exception message",
+ "java.lang.Exception: Error: You must specify a non-empty string for the user",
+ message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "BadRequestException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "org.apache.hadoop.yarn.webapp.BadRequestException", classname);
+ }
+ }
+
+ @Test
+ public void testNodeAppsState() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ MockApp app2 = new MockApp("foo", 1234, 2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ HashMap hash2 = addAppContainers(app2);
+ app2.setState(ApplicationState.RUNNING);
+
+ ClientResponse response = r.path("ws").path("v1").path("node").path("apps")
+ .queryParam("state", ApplicationState.RUNNING.toString())
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+
+ JSONObject info = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, info.length());
+ JSONArray appInfo = info.getJSONArray("app");
+ assertEquals("incorrect number of elements", 1, appInfo.length());
+ verifyNodeAppInfo(appInfo.getJSONObject(0), app2, hash2);
+
+ }
+
+ @Test
+ public void testNodeAppsStateNone() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ Application app2 = new MockApp("foo", 1234, 2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ ClientResponse response = r.path("ws").path("v1").path("node").path("apps")
+ .queryParam("state", ApplicationState.INITING.toString())
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+
+ assertEquals("apps is not null", JSONObject.NULL, json.get("apps"));
+ }
+
+ @Test
+ public void testNodeAppsStateInvalid() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ Application app2 = new MockApp("foo", 1234, 2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ try {
+ r.path("ws").path("v1").path("node").path("apps")
+ .queryParam("state", "FOO_STATE").accept(MediaType.APPLICATION_JSON)
+ .get(JSONObject.class);
+ fail("should have thrown exception on invalid user query");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+
+ assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils
+ .checkStringMatch(
+ "exception message",
+ "No enum const class org.apache.hadoop.yarn.server.nodemanager.containermanager.application.ApplicationState.FOO_STATE",
+ message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "IllegalArgumentException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "java.lang.IllegalArgumentException", classname);
+ }
+ }
+
+ @Test
+ public void testNodeSingleApps() throws JSONException, Exception {
+ testNodeSingleAppHelper(MediaType.APPLICATION_JSON);
+ }
+
+ // make sure default is json output
+ @Test
+ public void testNodeSingleAppsDefault() throws JSONException, Exception {
+ testNodeSingleAppHelper("");
+ }
+
+ public void testNodeSingleAppHelper(String media) throws JSONException,
+ Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ HashMap hash = addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ ClientResponse response = r.path("ws").path("v1").path("node").path("apps")
+ .path(app.getAppId().toString()).accept(media)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyNodeAppInfo(json.getJSONObject("app"), app, hash);
+ }
+
+ @Test
+ public void testNodeSingleAppsSlash() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ HashMap hash = addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+ ClientResponse response = r.path("ws").path("v1").path("node").path("apps")
+ .path(app.getAppId().toString() + "/")
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyNodeAppInfo(json.getJSONObject("app"), app, hash);
+ }
+
+ @Test
+ public void testNodeSingleAppsInvalid() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ try {
+ r.path("ws").path("v1").path("node").path("apps").path("app_foo_0000")
+ .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
+ fail("should have thrown exception on invalid user query");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils.checkStringMatch("exception message",
+ "For input string: \"foo\"", message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "NumberFormatException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "java.lang.NumberFormatException", classname);
+ }
+ }
+
+ @Test
+ public void testNodeSingleAppsMissing() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ try {
+ r.path("ws").path("v1").path("node").path("apps")
+ .path("application_1234_0009").accept(MediaType.APPLICATION_JSON)
+ .get(JSONObject.class);
+ fail("should have thrown exception on invalid user query");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.NOT_FOUND, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils.checkStringMatch("exception message",
+ "java.lang.Exception: app with id application_1234_0009 not found",
+ message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "NotFoundException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
+ }
+ }
+
+ @Test
+ public void testNodeAppsXML() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ ClientResponse response = r.path("ws").path("v1").path("node").path("apps")
+ .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodes = dom.getElementsByTagName("app");
+ assertEquals("incorrect number of elements", 2, nodes.getLength());
+ }
+
+ @Test
+ public void testNodeSingleAppsXML() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ HashMap hash = addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ ClientResponse response = r.path("ws").path("v1").path("node").path("apps")
+ .path(app.getAppId().toString() + "/")
+ .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodes = dom.getElementsByTagName("app");
+ assertEquals("incorrect number of elements", 1, nodes.getLength());
+ verifyNodeAppInfoXML(nodes, app, hash);
+ }
+
+ public void verifyNodeAppInfoXML(NodeList nodes, Application app,
+ HashMap hash) throws JSONException, Exception {
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Element element = (Element) nodes.item(i);
+
+ verifyNodeAppInfoGeneric(app,
+ WebServicesTestUtils.getXmlString(element, "id"),
+ WebServicesTestUtils.getXmlString(element, "state"),
+ WebServicesTestUtils.getXmlString(element, "user"));
+
+ NodeList ids = element.getElementsByTagName("containerids");
+ for (int j = 0; j < ids.getLength(); j++) {
+ Element line = (Element) ids.item(j);
+ Node first = line.getFirstChild();
+ String val = first.getNodeValue();
+ assertEquals("extra containerid: " + val, val, hash.remove(val));
+ }
+ assertTrue("missing containerids", hash.isEmpty());
+ }
+ }
+
+ public void verifyNodeAppInfo(JSONObject info, Application app,
+ HashMap hash) throws JSONException, Exception {
+ assertEquals("incorrect number of elements", 4, info.length());
+
+ verifyNodeAppInfoGeneric(app, info.getString("id"),
+ info.getString("state"), info.getString("user"));
+
+ JSONArray containerids = info.getJSONArray("containerids");
+ for (int i = 0; i < containerids.length(); i++) {
+ String id = containerids.getString(i);
+ assertEquals("extra containerid: " + id, id, hash.remove(id));
+ }
+ assertTrue("missing containerids", hash.isEmpty());
+ }
+
+ public void verifyNodeAppInfoGeneric(Application app, String id,
+ String state, String user) throws JSONException, Exception {
+ WebServicesTestUtils.checkStringMatch("id", app.getAppId().toString(), id);
+ WebServicesTestUtils.checkStringMatch("state", app.getApplicationState()
+ .toString(), state);
+ WebServicesTestUtils.checkStringMatch("user", app.getUser().toString(),
+ user);
+ }
+
+}
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/TestNMWebServicesContainers.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/TestNMWebServicesContainers.java
new file mode 100644
index 00000000000..11ec3401015
--- /dev/null
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/webapp/TestNMWebServicesContainers.java
@@ -0,0 +1,481 @@
+/**
+ * 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.webapp;
+
+import static org.apache.hadoop.yarn.util.StringHelper.ujoin;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.StringReader;
+import java.util.HashMap;
+
+import javax.ws.rs.core.MediaType;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileUtil;
+import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
+import org.apache.hadoop.yarn.event.AsyncDispatcher;
+import org.apache.hadoop.yarn.event.Dispatcher;
+import org.apache.hadoop.yarn.server.nodemanager.Context;
+import org.apache.hadoop.yarn.server.nodemanager.LocalDirsHandlerService;
+import org.apache.hadoop.yarn.server.nodemanager.MockApp;
+import org.apache.hadoop.yarn.server.nodemanager.MockContainer;
+import org.apache.hadoop.yarn.server.nodemanager.NodeHealthCheckerService;
+import org.apache.hadoop.yarn.server.nodemanager.NodeManager;
+import org.apache.hadoop.yarn.server.nodemanager.ResourceView;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.Application;
+import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
+import org.apache.hadoop.yarn.server.nodemanager.webapp.WebServer.NMWebApp;
+import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
+import org.apache.hadoop.yarn.util.BuilderUtils;
+import org.apache.hadoop.yarn.util.ConverterUtils;
+import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
+import org.apache.hadoop.yarn.webapp.WebApp;
+import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.servlet.GuiceServletContextListener;
+import com.google.inject.servlet.ServletModule;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.ClientResponse.Status;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+
+public class TestNMWebServicesContainers extends JerseyTest {
+
+ private static Context nmContext;
+ private static ResourceView resourceView;
+ private static ApplicationACLsManager aclsManager;
+ private static LocalDirsHandlerService dirsHandler;
+ private static WebApp nmWebApp;
+ private static Configuration conf = new Configuration();
+
+ private static final File testRootDir = new File("target",
+ TestNMWebServicesContainers.class.getSimpleName());
+ private static File testLogDir = new File("target",
+ TestNMWebServicesContainers.class.getSimpleName() + "LogDir");
+
+ private Injector injector = Guice.createInjector(new ServletModule() {
+ @Override
+ protected void configureServlets() {
+ nmContext = new NodeManager.NMContext();
+ nmContext.getNodeId().setHost("testhost.foo.com");
+ nmContext.getNodeId().setPort(9999);
+ resourceView = new ResourceView() {
+ @Override
+ public long getVmemAllocatedForContainers() {
+ // 15.5G in bytes
+ return new Long("16642998272");
+ }
+
+ @Override
+ public long getPmemAllocatedForContainers() {
+ // 16G in bytes
+ return new Long("17179869184");
+ }
+ };
+ conf.set(YarnConfiguration.NM_LOCAL_DIRS, testRootDir.getAbsolutePath());
+ conf.set(YarnConfiguration.NM_LOG_DIRS, testLogDir.getAbsolutePath());
+ NodeHealthCheckerService healthChecker = new NodeHealthCheckerService();
+ healthChecker.init(conf);
+ dirsHandler = healthChecker.getDiskHandler();
+ aclsManager = new ApplicationACLsManager(conf);
+ nmWebApp = new NMWebApp(resourceView, aclsManager, dirsHandler);
+ bind(JAXBContextResolver.class);
+ bind(NMWebServices.class);
+ bind(GenericExceptionHandler.class);
+ bind(Context.class).toInstance(nmContext);
+ bind(WebApp.class).toInstance(nmWebApp);
+ bind(ResourceView.class).toInstance(resourceView);
+ bind(ApplicationACLsManager.class).toInstance(aclsManager);
+ bind(LocalDirsHandlerService.class).toInstance(dirsHandler);
+
+ serve("/*").with(GuiceContainer.class);
+ }
+ });
+
+ public class GuiceServletConfig extends GuiceServletContextListener {
+
+ @Override
+ protected Injector getInjector() {
+ return injector;
+ }
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ testRootDir.mkdirs();
+ testLogDir.mkdir();
+ }
+
+ @AfterClass
+ static public void cleanup() {
+ FileUtil.fullyDelete(testRootDir);
+ FileUtil.fullyDelete(testLogDir);
+ }
+
+ public TestNMWebServicesContainers() {
+ super(new WebAppDescriptor.Builder(
+ "org.apache.hadoop.yarn.server.nodemanager.webapp")
+ .contextListenerClass(GuiceServletConfig.class)
+ .filterClass(com.google.inject.servlet.GuiceFilter.class)
+ .contextPath("jersey-guice-filter").servletPath("/").build());
+ }
+
+ @Test
+ public void testNodeContainersNone() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("node")
+ .path("containers").accept(MediaType.APPLICATION_JSON)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("apps isn't NULL", JSONObject.NULL, json.get("containers"));
+ }
+
+ private HashMap addAppContainers(Application app) {
+ Dispatcher dispatcher = new AsyncDispatcher();
+ ApplicationAttemptId appAttemptId = BuilderUtils.newApplicationAttemptId(
+ app.getAppId(), 1);
+ Container container1 = new MockContainer(appAttemptId, dispatcher, conf,
+ app.getUser(), app.getAppId(), 1);
+ Container container2 = new MockContainer(appAttemptId, dispatcher, conf,
+ app.getUser(), app.getAppId(), 2);
+ nmContext.getContainers().put(container1.getContainerID(), container1);
+ nmContext.getContainers().put(container2.getContainerID(), container2);
+
+ app.getContainers().put(container1.getContainerID(), container1);
+ app.getContainers().put(container2.getContainerID(), container2);
+ HashMap hash = new HashMap();
+ hash.put(container1.getContainerID().toString(), container1
+ .getContainerID().toString());
+ hash.put(container2.getContainerID().toString(), container2
+ .getContainerID().toString());
+ return hash;
+ }
+
+ @Test
+ public void testNodeContainers() throws JSONException, Exception {
+ testNodeHelper("containers", MediaType.APPLICATION_JSON);
+ }
+
+ @Test
+ public void testNodeContainersSlash() throws JSONException, Exception {
+ testNodeHelper("containers/", MediaType.APPLICATION_JSON);
+ }
+
+ // make sure default is json output
+ @Test
+ public void testNodeContainersDefault() throws JSONException, Exception {
+ testNodeHelper("containers/", "");
+
+ }
+
+ public void testNodeHelper(String path, String media) throws JSONException,
+ Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ ClientResponse response = r.path("ws").path("v1").path("node").path(path)
+ .accept(media).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ JSONObject info = json.getJSONObject("containers");
+ assertEquals("incorrect number of elements", 1, info.length());
+ JSONArray conInfo = info.getJSONArray("container");
+ assertEquals("incorrect number of elements", 4, conInfo.length());
+
+ for (int i = 0; i < conInfo.length(); i++) {
+ verifyNodeContainerInfo(
+ conInfo.getJSONObject(i),
+ nmContext.getContainers().get(
+ ConverterUtils.toContainerId(conInfo.getJSONObject(i).getString(
+ "id"))));
+ }
+ }
+
+ @Test
+ public void testNodeSingleContainers() throws JSONException, Exception {
+ testNodeSingleContainersHelper(MediaType.APPLICATION_JSON);
+ }
+
+ @Test
+ public void testNodeSingleContainersSlash() throws JSONException, Exception {
+ testNodeSingleContainersHelper(MediaType.APPLICATION_JSON);
+ }
+
+ @Test
+ public void testNodeSingleContainersDefault() throws JSONException, Exception {
+ testNodeSingleContainersHelper("");
+ }
+
+ public void testNodeSingleContainersHelper(String media)
+ throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ HashMap hash = addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ for (String id : hash.keySet()) {
+ ClientResponse response = r.path("ws").path("v1").path("node")
+ .path("containers").path(id).accept(media).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyNodeContainerInfo(json.getJSONObject("container"), nmContext
+ .getContainers().get(ConverterUtils.toContainerId(id)));
+ }
+ }
+
+ @Test
+ public void testSingleContainerInvalid() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+ try {
+ r.path("ws").path("v1").path("node").path("containers")
+ .path("container_foo_1234").accept(MediaType.APPLICATION_JSON)
+ .get(JSONObject.class);
+ fail("should have thrown exception on invalid user query");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils.checkStringMatch("exception message",
+ "java.lang.Exception: invalid container id, container_foo_1234",
+ message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "BadRequestException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "org.apache.hadoop.yarn.webapp.BadRequestException", classname);
+ }
+ }
+
+ @Test
+ public void testSingleContainerInvalid2() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+ try {
+ r.path("ws").path("v1").path("node").path("containers")
+ .path("container_1234_0001").accept(MediaType.APPLICATION_JSON)
+ .get(JSONObject.class);
+ fail("should have thrown exception on invalid user query");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils.checkStringMatch("exception message",
+ "java.lang.Exception: invalid container id, container_1234_0001",
+ message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "BadRequestException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "org.apache.hadoop.yarn.webapp.BadRequestException", classname);
+ }
+ }
+
+ @Test
+ public void testSingleContainerWrong() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+ try {
+ r.path("ws").path("v1").path("node").path("containers")
+ .path("container_1234_0001_01_000005")
+ .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
+ fail("should have thrown exception on invalid user query");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.NOT_FOUND, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils
+ .checkStringMatch(
+ "exception message",
+ "java.lang.Exception: container with id, container_1234_0001_01_000005, not found",
+ message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "NotFoundException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
+ }
+ }
+
+ @Test
+ public void testNodeSingleContainerXML() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ HashMap hash = addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ for (String id : hash.keySet()) {
+ ClientResponse response = r.path("ws").path("v1").path("node")
+ .path("containers").path(id).accept(MediaType.APPLICATION_XML)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodes = dom.getElementsByTagName("container");
+ assertEquals("incorrect number of elements", 1, nodes.getLength());
+ verifyContainersInfoXML(nodes,
+ nmContext.getContainers().get(ConverterUtils.toContainerId(id)));
+
+ }
+ }
+
+ @Test
+ public void testNodeContainerXML() throws JSONException, Exception {
+ WebResource r = resource();
+ Application app = new MockApp(1);
+ nmContext.getApplications().put(app.getAppId(), app);
+ addAppContainers(app);
+ Application app2 = new MockApp(2);
+ nmContext.getApplications().put(app2.getAppId(), app2);
+ addAppContainers(app2);
+
+ ClientResponse response = r.path("ws").path("v1").path("node")
+ .path("containers").accept(MediaType.APPLICATION_XML)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodes = dom.getElementsByTagName("container");
+ assertEquals("incorrect number of elements", 4, nodes.getLength());
+ }
+
+ public void verifyContainersInfoXML(NodeList nodes, Container cont)
+ throws JSONException, Exception {
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Element element = (Element) nodes.item(i);
+
+ verifyNodeContainerInfoGeneric(cont,
+ WebServicesTestUtils.getXmlString(element, "id"),
+ WebServicesTestUtils.getXmlString(element, "state"),
+ WebServicesTestUtils.getXmlString(element, "user"),
+ WebServicesTestUtils.getXmlInt(element, "exitCode"),
+ WebServicesTestUtils.getXmlString(element, "diagnostics"),
+ WebServicesTestUtils.getXmlString(element, "nodeId"),
+ WebServicesTestUtils.getXmlInt(element, "totalMemoryNeededMB"),
+ WebServicesTestUtils.getXmlString(element, "containerLogsLink"));
+ }
+ }
+
+ public void verifyNodeContainerInfo(JSONObject info, Container cont)
+ throws JSONException, Exception {
+ assertEquals("incorrect number of elements", 8, info.length());
+
+ verifyNodeContainerInfoGeneric(cont, info.getString("id"),
+ info.getString("state"), info.getString("user"),
+ info.getInt("exitCode"), info.getString("diagnostics"),
+ info.getString("nodeId"), info.getInt("totalMemoryNeededMB"),
+ info.getString("containerLogsLink"));
+ }
+
+ public void verifyNodeContainerInfoGeneric(Container cont, String id,
+ String state, String user, int exitCode, String diagnostics,
+ String nodeId, int totalMemoryNeededMB, String logsLink)
+ throws JSONException, Exception {
+ WebServicesTestUtils.checkStringMatch("id", cont.getContainerID()
+ .toString(), id);
+ WebServicesTestUtils.checkStringMatch("state", cont.getContainerState()
+ .toString(), state);
+ WebServicesTestUtils.checkStringMatch("user", cont.getUser().toString(),
+ user);
+ assertEquals("exitCode wrong", 0, exitCode);
+ WebServicesTestUtils
+ .checkStringMatch("diagnostics", "testing", diagnostics);
+
+ WebServicesTestUtils.checkStringMatch("nodeId", nmContext.getNodeId()
+ .toString(), nodeId);
+ assertEquals("totalMemoryNeededMB wrong", 0, totalMemoryNeededMB);
+ String shortLink = ujoin("containerlogs", cont.getContainerID().toString(),
+ cont.getUser());
+ assertTrue("containerLogsLink wrong", logsLink.contains(shortLink));
+ }
+
+}
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/CapacitySchedulerInfo.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/CapacitySchedulerInfo.java
index c66fa938873..921b5ea9e18 100644
--- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/CapacitySchedulerInfo.java
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/CapacitySchedulerInfo.java
@@ -26,6 +26,7 @@ import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
+import org.apache.hadoop.yarn.api.records.QueueState;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CSQueue;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.ParentQueue;
@@ -90,7 +91,7 @@ public class CapacitySchedulerInfo extends SchedulerInfo {
if (max < EPSILON || max > 1f)
max = 1f;
float maxCapacity = max * 100;
- String state = queue.getState().toString();
+ QueueState state = queue.getState();
CapacitySchedulerQueueInfo info = new CapacitySchedulerQueueInfo(
capacity, usedCapacity, maxCapacity, queueName, state, queuePath);
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/CapacitySchedulerQueueInfo.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/CapacitySchedulerQueueInfo.java
index f346fb0c87a..14cffd8e5eb 100644
--- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/CapacitySchedulerQueueInfo.java
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/CapacitySchedulerQueueInfo.java
@@ -24,6 +24,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
+import org.apache.hadoop.yarn.api.records.QueueState;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CSQueue;
@XmlRootElement
@@ -43,14 +44,14 @@ public class CapacitySchedulerQueueInfo {
protected float usedCapacity;
protected float maxCapacity;
protected String queueName;
- protected String state;
+ protected QueueState state;
protected ArrayList subQueues;
CapacitySchedulerQueueInfo() {
};
CapacitySchedulerQueueInfo(float cap, float used, float max, String name,
- String state, String path) {
+ QueueState state, String path) {
this.capacity = cap;
this.usedCapacity = used;
this.maxCapacity = max;
@@ -84,7 +85,7 @@ public class CapacitySchedulerQueueInfo {
}
public String getQueueState() {
- return this.state;
+ return this.state.toString();
}
public String getQueuePath() {
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/ClusterInfo.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/ClusterInfo.java
index b4511bc1767..a68fe0a7d1f 100644
--- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/ClusterInfo.java
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/ClusterInfo.java
@@ -23,6 +23,7 @@ import javax.xml.bind.annotation.XmlRootElement;
import org.apache.hadoop.util.VersionInfo;
import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
+import org.apache.hadoop.yarn.service.Service.STATE;
import org.apache.hadoop.yarn.util.YarnVersionInfo;
@XmlRootElement
@@ -31,7 +32,7 @@ public class ClusterInfo {
protected long id;
protected long startedOn;
- protected String state;
+ protected STATE state;
protected String resourceManagerVersion;
protected String resourceManagerBuildVersion;
protected String resourceManagerVersionBuiltOn;
@@ -46,7 +47,7 @@ public class ClusterInfo {
long ts = ResourceManager.clusterTimeStamp;
this.id = ts;
- this.state = rm.getServiceState().toString();
+ this.state = rm.getServiceState();
this.startedOn = ts;
this.resourceManagerVersion = YarnVersionInfo.getVersion();
this.resourceManagerBuildVersion = YarnVersionInfo.getBuildVersion();
@@ -57,7 +58,7 @@ public class ClusterInfo {
}
public String getState() {
- return this.state;
+ return this.state.toString();
}
public String getRMVersion() {
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/MockRM.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/MockRM.java
index e80e629aa54..cdcfd2590ec 100644
--- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/MockRM.java
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/MockRM.java
@@ -87,8 +87,12 @@ public class MockRM extends ResourceManager {
.newRecord(GetNewApplicationRequest.class));
}
- // client
public RMApp submitApp(int masterMemory) throws Exception {
+ return submitApp(masterMemory, "", "");
+ }
+
+ // client
+ public RMApp submitApp(int masterMemory, String name, String user) throws Exception {
ClientRMProtocol client = getClientRMService();
GetNewApplicationResponse resp = client.getNewApplication(Records
.newRecord(GetNewApplicationRequest.class));
@@ -99,8 +103,8 @@ public class MockRM extends ResourceManager {
ApplicationSubmissionContext sub = Records
.newRecord(ApplicationSubmissionContext.class);
sub.setApplicationId(appId);
- sub.setApplicationName("");
- sub.setUser("");
+ sub.setApplicationName(name);
+ sub.setUser(user);
ContainerLaunchContext clc = Records
.newRecord(ContainerLaunchContext.class);
Resource capability = Records.newRecord(Resource.class);
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java
index b19e7b54e5e..51d2fa7d0dd 100644
--- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServices.java
@@ -22,34 +22,34 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import java.util.ArrayList;
+import java.io.StringReader;
import javax.ws.rs.core.MediaType;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.hadoop.yarn.api.records.ContainerStatus;
-import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
-import org.apache.hadoop.yarn.api.records.NodeHealthStatus;
+import org.apache.hadoop.util.VersionInfo;
import org.apache.hadoop.yarn.api.records.QueueState;
-import org.apache.hadoop.yarn.server.resourcemanager.MockAM;
-import org.apache.hadoop.yarn.server.resourcemanager.MockNM;
+import org.apache.hadoop.yarn.server.resourcemanager.ClusterMetrics;
import org.apache.hadoop.yarn.server.resourcemanager.MockRM;
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
-import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
-import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState;
-import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode;
-import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeImpl;
-import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeState;
-import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeStatusEvent;
+import org.apache.hadoop.yarn.server.resourcemanager.scheduler.QueueMetrics;
+import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
+import org.apache.hadoop.yarn.service.Service.STATE;
+import org.apache.hadoop.yarn.util.YarnVersionInfo;
import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
-import org.codehaus.jettison.json.JSONArray;
+import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
import com.google.inject.Guice;
import com.google.inject.Injector;
@@ -104,11 +104,73 @@ public class TestRMWebServices extends JerseyTest {
.contextPath("jersey-guice-filter").servletPath("/").build());
}
+ @Test
+ public void testInfoXML() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("info").accept("application/xml").get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+ verifyClusterInfoXML(xml);
+ }
+
+ @Test
+ public void testInvalidUri() throws JSONException, Exception {
+ WebResource r = resource();
+ String responseStr = "";
+ try {
+ responseStr = r.path("ws").path("v1").path("cluster").path("bogus")
+ .accept(MediaType.APPLICATION_JSON).get(String.class);
+ fail("should have thrown exception on invalid uri");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.NOT_FOUND, response.getClientResponseStatus());
+
+ WebServicesTestUtils.checkStringMatch(
+ "error string exists and shouldn't", "", responseStr);
+ }
+ }
+
+ @Test
+ public void testInvalidUri2() throws JSONException, Exception {
+ WebResource r = resource();
+ String responseStr = "";
+ try {
+ responseStr = r.accept(MediaType.APPLICATION_JSON).get(String.class);
+ fail("should have thrown exception on invalid uri");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.NOT_FOUND, response.getClientResponseStatus());
+ WebServicesTestUtils.checkStringMatch(
+ "error string exists and shouldn't", "", responseStr);
+ }
+ }
+
+ @Test
+ public void testInvalidAccept() throws JSONException, Exception {
+ WebResource r = resource();
+ String responseStr = "";
+ try {
+ responseStr = r.path("ws").path("v1").path("cluster")
+ .accept(MediaType.TEXT_PLAIN).get(String.class);
+ fail("should have thrown exception on invalid uri");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.INTERNAL_SERVER_ERROR,
+ response.getClientResponseStatus());
+ WebServicesTestUtils.checkStringMatch(
+ "error string exists and shouldn't", "", responseStr);
+ }
+ }
+
@Test
public void testCluster() throws JSONException, Exception {
WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster")
- .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
verifyClusterInfo(json);
}
@@ -116,986 +178,366 @@ public class TestRMWebServices extends JerseyTest {
public void testClusterSlash() throws JSONException, Exception {
WebResource r = resource();
// test with trailing "/" to make sure acts same as without slash
- JSONObject json = r.path("ws").path("v1").path("cluster/")
- .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
+ ClientResponse response = r.path("ws").path("v1").path("cluster/")
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyClusterInfo(json);
+ }
+
+ @Test
+ public void testClusterDefault() throws JSONException, Exception {
+ WebResource r = resource();
+ // test with trailing "/" to make sure acts same as without slash
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
verifyClusterInfo(json);
}
@Test
public void testInfo() throws JSONException, Exception {
WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("info")
- .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("info").accept(MediaType.APPLICATION_JSON)
+ .get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
verifyClusterInfo(json);
}
@Test
public void testInfoSlash() throws JSONException, Exception {
- WebResource r = resource();
// test with trailing "/" to make sure acts same as without slash
- JSONObject json = r.path("ws").path("v1").path("cluster").path("info/")
- .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("info/").accept(MediaType.APPLICATION_JSON)
+ .get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
verifyClusterInfo(json);
}
+ @Test
+ public void testInfoDefault() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("info").get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyClusterInfo(json);
+ }
+
+ public void verifyClusterInfoXML(String xml) throws JSONException, Exception {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodes = dom.getElementsByTagName("clusterInfo");
+ assertEquals("incorrect number of elements", 1, nodes.getLength());
+
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Element element = (Element) nodes.item(i);
+
+ verifyClusterGeneric(WebServicesTestUtils.getXmlLong(element, "id"),
+ WebServicesTestUtils.getXmlLong(element, "startedOn"),
+ WebServicesTestUtils.getXmlString(element, "state"),
+ WebServicesTestUtils.getXmlString(element, "hadoopVersionBuiltOn"),
+ WebServicesTestUtils.getXmlString(element, "hadoopBuildVersion"),
+ WebServicesTestUtils.getXmlString(element, "hadoopVersion"),
+ WebServicesTestUtils.getXmlString(element,
+ "resourceManagerVersionBuiltOn"),
+ WebServicesTestUtils.getXmlString(element,
+ "resourceManagerBuildVersion"),
+ WebServicesTestUtils.getXmlString(element, "resourceManagerVersion"));
+ }
+ }
+
public void verifyClusterInfo(JSONObject json) throws JSONException,
Exception {
- assertEquals("correct number of elements", 1, json.length());
- JSONObject clusterinfo = json.getJSONObject("clusterInfo");
- assertEquals("correct number of elements", 9, clusterinfo.length());
- String clusterid = clusterinfo.get("id").toString();
- assertTrue("clusterId doesn't match: " + clusterid, clusterid.toString()
- .matches("^\\d+"));
- String startedon = clusterinfo.get("startedOn").toString();
- assertTrue("startedOn doesn't match: " + startedon,
- startedon.matches("^\\d+"));
- String state = clusterinfo.get("state").toString();
- assertTrue("stated doesn't match: " + state, state.matches("INITED"));
- String rmVersion = clusterinfo.get("resourceManagerVersion").toString();
- assertTrue("rm version doesn't match: " + rmVersion,
- rmVersion.matches(".*"));
- String rmBuildVersion = clusterinfo.get("resourceManagerBuildVersion")
- .toString();
- assertTrue("rm Build version doesn't match: " + rmBuildVersion,
- rmBuildVersion.matches(".*"));
- String rmVersionBuiltOn = clusterinfo.get("resourceManagerVersionBuiltOn")
- .toString();
- assertTrue(
- "rm version built on doesn't match: " + rmVersionBuiltOn,
- rmVersionBuiltOn
- .matches("^\\w+\\s+\\w+\\s+\\d+\\s+\\d\\d:\\d\\d:\\d\\d\\s+\\w+\\s+\\d\\d\\d\\d"));
- String hadoopVersion = clusterinfo.get("hadoopVersion").toString();
- assertTrue("hadoop version doesn't match: " + hadoopVersion,
- hadoopVersion.matches(".*"));
- String hadoopBuildVersion = clusterinfo.get("hadoopBuildVersion")
- .toString();
- assertTrue("hadoop Build version doesn't match: " + hadoopBuildVersion,
- hadoopBuildVersion.matches(".*"));
- String hadoopVersionBuiltOn = clusterinfo.get("hadoopVersionBuiltOn")
- .toString();
- assertTrue(
- "hadoop version built on doesn't match: " + hadoopVersionBuiltOn,
- hadoopVersionBuiltOn
- .matches("^\\w+\\s+\\w+\\s+\\d+\\s+\\d\\d:\\d\\d:\\d\\d\\s+\\w+\\s+\\d\\d\\d\\d"));
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject info = json.getJSONObject("clusterInfo");
+ assertEquals("incorrect number of elements", 9, info.length());
+ verifyClusterGeneric(info.getLong("id"), info.getLong("startedOn"),
+ info.getString("state"), info.getString("hadoopVersionBuiltOn"),
+ info.getString("hadoopBuildVersion"), info.getString("hadoopVersion"),
+ info.getString("resourceManagerVersionBuiltOn"),
+ info.getString("resourceManagerBuildVersion"),
+ info.getString("resourceManagerVersion"));
+
+ }
+
+ public void verifyClusterGeneric(long clusterid, long startedon,
+ String state, String hadoopVersionBuiltOn, String hadoopBuildVersion,
+ String hadoopVersion, String resourceManagerVersionBuiltOn,
+ String resourceManagerBuildVersion, String resourceManagerVersion) {
+
+ assertEquals("clusterId doesn't match: ", ResourceManager.clusterTimeStamp,
+ clusterid);
+ assertEquals("startedOn doesn't match: ", ResourceManager.clusterTimeStamp,
+ startedon);
+ assertTrue("stated doesn't match: " + state,
+ state.matches(STATE.INITED.toString()));
+
+ WebServicesTestUtils.checkStringMatch("hadoopVersionBuiltOn",
+ VersionInfo.getDate(), hadoopVersionBuiltOn);
+ WebServicesTestUtils.checkStringMatch("hadoopBuildVersion",
+ VersionInfo.getBuildVersion(), hadoopBuildVersion);
+ WebServicesTestUtils.checkStringMatch("hadoopVersion",
+ VersionInfo.getVersion(), hadoopVersion);
+
+ WebServicesTestUtils.checkStringMatch("resourceManagerVersionBuiltOn",
+ YarnVersionInfo.getDate(), resourceManagerVersionBuiltOn);
+ WebServicesTestUtils.checkStringMatch("resourceManagerBuildVersion",
+ YarnVersionInfo.getBuildVersion(), resourceManagerBuildVersion);
+ WebServicesTestUtils.checkStringMatch("resourceManagerVersion",
+ YarnVersionInfo.getVersion(), resourceManagerVersion);
}
@Test
public void testClusterMetrics() throws JSONException, Exception {
WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("metrics")
- .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
- verifyClusterMetrics(json);
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("metrics").accept(MediaType.APPLICATION_JSON)
+ .get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyClusterMetricsJSON(json);
}
@Test
public void testClusterMetricsSlash() throws JSONException, Exception {
WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("metrics/")
- .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
- verifyClusterMetrics(json);
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("metrics/").accept(MediaType.APPLICATION_JSON)
+ .get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyClusterMetricsJSON(json);
}
- public void verifyClusterMetrics(JSONObject json) throws JSONException,
+ @Test
+ public void testClusterMetricsDefault() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("metrics").get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyClusterMetricsJSON(json);
+ }
+
+ @Test
+ public void testClusterMetricsXML() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("metrics").accept("application/xml").get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+ verifyClusterMetricsXML(xml);
+ }
+
+ public void verifyClusterMetricsXML(String xml) throws JSONException,
Exception {
- assertEquals("correct number of elements", 1, json.length());
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodes = dom.getElementsByTagName("clusterMetrics");
+ assertEquals("incorrect number of elements", 1, nodes.getLength());
+
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Element element = (Element) nodes.item(i);
+
+ verifyClusterMetrics(
+ WebServicesTestUtils.getXmlInt(element, "appsSubmitted"),
+ WebServicesTestUtils.getXmlInt(element, "reservedMB"),
+ WebServicesTestUtils.getXmlInt(element, "availableMB"),
+ WebServicesTestUtils.getXmlInt(element, "allocatedMB"),
+ WebServicesTestUtils.getXmlInt(element, "containersAllocated"),
+ WebServicesTestUtils.getXmlInt(element, "totalMB"),
+ WebServicesTestUtils.getXmlInt(element, "totalNodes"),
+ WebServicesTestUtils.getXmlInt(element, "lostNodes"),
+ WebServicesTestUtils.getXmlInt(element, "unhealthyNodes"),
+ WebServicesTestUtils.getXmlInt(element, "decommissionedNodes"),
+ WebServicesTestUtils.getXmlInt(element, "rebootedNodes"));
+ }
+ }
+
+ public void verifyClusterMetricsJSON(JSONObject json) throws JSONException,
+ Exception {
+ assertEquals("incorrect number of elements", 1, json.length());
JSONObject clusterinfo = json.getJSONObject("clusterMetrics");
- assertEquals("correct number of elements", 11, clusterinfo.length());
- assertEquals("appsSubmitted doesn't match", 0,
- clusterinfo.getInt("appsSubmitted"));
- assertEquals("reservedMB doesn't match", 0,
- clusterinfo.getInt("reservedMB"));
- assertEquals("availableMB doesn't match", 0,
- clusterinfo.getInt("availableMB"));
- assertEquals("allocatedMB doesn't match", 0,
- clusterinfo.getInt("allocatedMB"));
- assertEquals("containersAllocated doesn't match", 0,
- clusterinfo.getInt("containersAllocated"));
- assertEquals("totalMB doesn't match", 0, clusterinfo.getInt("totalMB"));
- assertEquals("totalNodes doesn't match", 0,
- clusterinfo.getInt("totalNodes"));
- assertEquals("lostNodes doesn't match", 0, clusterinfo.getInt("lostNodes"));
- assertEquals("unhealthyNodes doesn't match", 0,
- clusterinfo.getInt("unhealthyNodes"));
- assertEquals("decommissionedNodes doesn't match", 0,
- clusterinfo.getInt("decommissionedNodes"));
- assertEquals("rebootedNodes doesn't match", 0,
+ assertEquals("incorrect number of elements", 11, clusterinfo.length());
+ verifyClusterMetrics(clusterinfo.getInt("appsSubmitted"),
+ clusterinfo.getInt("reservedMB"), clusterinfo.getInt("availableMB"),
+ clusterinfo.getInt("allocatedMB"),
+ clusterinfo.getInt("containersAllocated"),
+ clusterinfo.getInt("totalMB"), clusterinfo.getInt("totalNodes"),
+ clusterinfo.getInt("lostNodes"), clusterinfo.getInt("unhealthyNodes"),
+ clusterinfo.getInt("decommissionedNodes"),
clusterinfo.getInt("rebootedNodes"));
}
+ public void verifyClusterMetrics(int sub, int reservedMB, int availableMB,
+ int allocMB, int containersAlloc, int totalMB, int totalNodes,
+ int lostNodes, int unhealthyNodes, int decommissionedNodes,
+ int rebootedNodes) throws JSONException, Exception {
+
+ ResourceScheduler rs = rm.getResourceScheduler();
+ QueueMetrics metrics = rs.getRootQueueMetrics();
+ ClusterMetrics clusterMetrics = ClusterMetrics.getMetrics();
+ final long MB_IN_GB = 1024;
+
+ long totalMBExpect = (metrics.getReservedGB() * MB_IN_GB)
+ + (metrics.getAvailableGB() * MB_IN_GB)
+ + (metrics.getAllocatedGB() * MB_IN_GB);
+
+ assertEquals("appsSubmitted doesn't match", metrics.getAppsSubmitted(), sub);
+ assertEquals("reservedMB doesn't match",
+ metrics.getReservedGB() * MB_IN_GB, reservedMB);
+ assertEquals("availableMB doesn't match", metrics.getAvailableGB()
+ * MB_IN_GB, availableMB);
+ assertEquals("allocatedMB doesn't match", metrics.getAllocatedGB()
+ * MB_IN_GB, allocMB);
+ assertEquals("containersAllocated doesn't match", 0, containersAlloc);
+ assertEquals("totalMB doesn't match", totalMBExpect, totalMB);
+ assertEquals("totalNodes doesn't match", clusterMetrics.getNumNMs(),
+ totalNodes);
+ assertEquals("lostNodes doesn't match", clusterMetrics.getNumLostNMs(),
+ lostNodes);
+ assertEquals("unhealthyNodes doesn't match",
+ clusterMetrics.getUnhealthyNMs(), unhealthyNodes);
+ assertEquals("decommissionedNodes doesn't match",
+ clusterMetrics.getNumDecommisionedNMs(), decommissionedNodes);
+ assertEquals("rebootedNodes doesn't match",
+ clusterMetrics.getNumRebootedNMs(), rebootedNodes);
+ }
+
@Test
public void testClusterSchedulerFifo() throws JSONException, Exception {
WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("scheduler")
- .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("scheduler").accept(MediaType.APPLICATION_JSON)
+ .get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
verifyClusterSchedulerFifo(json);
}
@Test
public void testClusterSchedulerFifoSlash() throws JSONException, Exception {
WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster")
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
.path("scheduler/").accept(MediaType.APPLICATION_JSON)
- .get(JSONObject.class);
+ .get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
verifyClusterSchedulerFifo(json);
}
+ @Test
+ public void testClusterSchedulerFifoDefault() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("scheduler").get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyClusterSchedulerFifo(json);
+ }
+
+ @Test
+ public void testClusterSchedulerFifoXML() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("scheduler").accept(MediaType.APPLICATION_XML)
+ .get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+ verifySchedulerFifoXML(xml);
+ }
+
+ public void verifySchedulerFifoXML(String xml) throws JSONException,
+ Exception {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodesSched = dom.getElementsByTagName("scheduler");
+ assertEquals("incorrect number of elements", 1, nodesSched.getLength());
+ NodeList nodes = dom.getElementsByTagName("schedulerInfo");
+ assertEquals("incorrect number of elements", 1, nodes.getLength());
+
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Element element = (Element) nodes.item(i);
+
+ verifyClusterSchedulerFifoGeneric(
+ WebServicesTestUtils.getXmlAttrString(element, "xsi:type"),
+ WebServicesTestUtils.getXmlString(element, "qstate"),
+ WebServicesTestUtils.getXmlFloat(element, "capacity"),
+ WebServicesTestUtils.getXmlFloat(element, "usedCapacity"),
+ WebServicesTestUtils.getXmlInt(element, "minQueueMemoryCapacity"),
+ WebServicesTestUtils.getXmlInt(element, "maxQueueMemoryCapacity"),
+ WebServicesTestUtils.getXmlInt(element, "numNodes"),
+ WebServicesTestUtils.getXmlInt(element, "usedNodeCapacity"),
+ WebServicesTestUtils.getXmlInt(element, "availNodeCapacity"),
+ WebServicesTestUtils.getXmlInt(element, "totalNodeCapacity"),
+ WebServicesTestUtils.getXmlInt(element, "numContainers"));
+ }
+ }
+
public void verifyClusterSchedulerFifo(JSONObject json) throws JSONException,
Exception {
- assertEquals("correct number of elements", 1, json.length());
+ assertEquals("incorrect number of elements", 1, json.length());
JSONObject info = json.getJSONObject("scheduler");
- assertEquals("correct number of elements", 1, info.length());
+ assertEquals("incorrect number of elements", 1, info.length());
info = info.getJSONObject("schedulerInfo");
- assertEquals("correct number of elements", 11, info.length());
- assertEquals("type doesn't match", "fifoScheduler", info.getString("type"));
- assertEquals("qstate doesn't match", QueueState.RUNNING.toString(),
- info.getString("qstate"));
- assertEquals("capacity doesn't match", 1.0, info.getDouble("capacity"), 0.0);
- assertEquals("usedCapacity doesn't match", Float.NaN,
- info.getDouble("usedCapacity"), 0.0);
- assertEquals("minQueueMemoryCapacity doesn't match", 1024,
- info.getInt("minQueueMemoryCapacity"));
- assertEquals("maxQueueMemoryCapacity doesn't match", 10240,
- info.getInt("maxQueueMemoryCapacity"));
- assertEquals("maxQueueMemoryCapacity doesn't match", 10240,
- info.getInt("maxQueueMemoryCapacity"));
+ assertEquals("incorrect number of elements", 11, info.length());
+
+ verifyClusterSchedulerFifoGeneric(info.getString("type"),
+ info.getString("qstate"), (float) info.getDouble("capacity"),
+ (float) info.getDouble("usedCapacity"),
+ info.getInt("minQueueMemoryCapacity"),
+ info.getInt("maxQueueMemoryCapacity"), info.getInt("numNodes"),
+ info.getInt("usedNodeCapacity"), info.getInt("availNodeCapacity"),
+ info.getInt("totalNodeCapacity"), info.getInt("numContainers"));
}
- @Test
- public void testNodes() throws JSONException, Exception {
- testNodesHelper("nodes");
- }
-
- @Test
- public void testNodesSlash() throws JSONException, Exception {
- testNodesHelper("nodes/");
- }
-
- @Test
- public void testNodesQueryState() throws JSONException, Exception {
- WebResource r = resource();
- MockNM nm1 = rm.registerNode("h1:1234", 5120);
- MockNM nm2 = rm.registerNode("h2:1235", 5121);
- rm.sendNodeStarted(nm1);
- rm.NMwaitForState(nm1.getNodeId(), RMNodeState.RUNNING);
- rm.NMwaitForState(nm2.getNodeId(), RMNodeState.NEW);
-
- JSONObject json = r.path("ws").path("v1").path("cluster").path("nodes")
- .queryParam("state", RMNodeState.RUNNING.toString())
- .accept("application/json").get(JSONObject.class);
-
- assertEquals("correct number of elements", 1, json.length());
- JSONObject nodes = json.getJSONObject("nodes");
- assertEquals("correct number of elements", 1, nodes.length());
- JSONArray nodeArray = nodes.getJSONArray("node");
- assertEquals("correct number of elements", 1, nodeArray.length());
- JSONObject info = nodeArray.getJSONObject(0);
-
- verifyNodeInfo(info, nm1, RMNodeState.RUNNING);
- }
-
- @Test
- public void testNodesQueryStateNone() throws JSONException, Exception {
- WebResource r = resource();
- rm.registerNode("h1:1234", 5120);
- rm.registerNode("h2:1235", 5121);
-
- JSONObject json = r.path("ws").path("v1").path("cluster").path("nodes")
- .queryParam("state", RMNodeState.DECOMMISSIONED.toString())
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- assertEquals("nodes is not null", JSONObject.NULL, json.get("nodes"));
- }
-
- @Test
- public void testNodesQueryStateInvalid() throws JSONException, Exception {
- WebResource r = resource();
- rm.registerNode("h1:1234", 5120);
- rm.registerNode("h2:1235", 5121);
-
- try {
- r.path("ws").path("v1").path("cluster").path("nodes")
- .queryParam("state", "BOGUSSTATE").accept("application/json")
- .get(JSONObject.class);
-
- fail("should have thrown exception querying invalid state");
- } catch (UniformInterfaceException ue) {
- ClientResponse response = ue.getResponse();
-
- assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
- JSONObject msg = response.getEntity(JSONObject.class);
- JSONObject exception = msg.getJSONObject("RemoteException");
- assertEquals("correct number of elements", 3, exception.length());
- String message = exception.getString("message");
- String type = exception.getString("exception");
- String classname = exception.getString("javaClassName");
- checkStringMatch(
- "exception message",
- "No enum const class org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeState.BOGUSSTATE",
- message);
- checkStringMatch("exception type", "IllegalArgumentException", type);
- checkStringMatch("exception classname",
- "java.lang.IllegalArgumentException", classname);
-
- } finally {
- rm.stop();
- }
- }
-
- @Test
- public void testNodesQueryHealthy() throws JSONException, Exception {
- WebResource r = resource();
- MockNM nm1 = rm.registerNode("h1:1234", 5120);
- MockNM nm2 = rm.registerNode("h2:1235", 5121);
- rm.sendNodeStarted(nm1);
- rm.NMwaitForState(nm1.getNodeId(), RMNodeState.RUNNING);
- rm.NMwaitForState(nm2.getNodeId(), RMNodeState.NEW);
- JSONObject json = r.path("ws").path("v1").path("cluster").path("nodes")
- .queryParam("healthy", "true").accept("application/json")
- .get(JSONObject.class);
-
- assertEquals("correct number of elements", 1, json.length());
- JSONObject nodes = json.getJSONObject("nodes");
- assertEquals("correct number of elements", 1, nodes.length());
- JSONArray nodeArray = nodes.getJSONArray("node");
- assertEquals("correct number of elements", 2, nodeArray.length());
- }
-
- @Test
- public void testNodesQueryHealthyCase() throws JSONException, Exception {
- WebResource r = resource();
- MockNM nm1 = rm.registerNode("h1:1234", 5120);
- MockNM nm2 = rm.registerNode("h2:1235", 5121);
- rm.sendNodeStarted(nm1);
- rm.NMwaitForState(nm1.getNodeId(), RMNodeState.RUNNING);
- rm.NMwaitForState(nm2.getNodeId(), RMNodeState.NEW);
- JSONObject json = r.path("ws").path("v1").path("cluster").path("nodes")
- .queryParam("healthy", "TRUe").accept("application/json")
- .get(JSONObject.class);
-
- assertEquals("correct number of elements", 1, json.length());
- JSONObject nodes = json.getJSONObject("nodes");
- assertEquals("correct number of elements", 1, nodes.length());
- JSONArray nodeArray = nodes.getJSONArray("node");
- assertEquals("correct number of elements", 2, nodeArray.length());
-
- }
-
- @Test
- public void testNodesQueryHealthyAndState() throws JSONException, Exception {
- WebResource r = resource();
- MockNM nm1 = rm.registerNode("h1:1234", 5120);
- MockNM nm2 = rm.registerNode("h2:1235", 5121);
- rm.sendNodeStarted(nm1);
- rm.NMwaitForState(nm2.getNodeId(), RMNodeState.NEW);
- rm.NMwaitForState(nm1.getNodeId(), RMNodeState.RUNNING);
- RMNodeImpl node = (RMNodeImpl) rm.getRMContext().getRMNodes()
- .get(nm1.getNodeId());
- NodeHealthStatus nodeHealth = node.getNodeHealthStatus();
- nodeHealth.setHealthReport("test health report");
- nodeHealth.setIsNodeHealthy(false);
- node.handle(new RMNodeStatusEvent(nm1.getNodeId(), nodeHealth,
- new ArrayList(), null, null));
- rm.NMwaitForState(nm1.getNodeId(), RMNodeState.UNHEALTHY);
-
- JSONObject json = r.path("ws").path("v1").path("cluster").path("nodes")
- .queryParam("healthy", "true")
- .queryParam("state", RMNodeState.RUNNING.toString())
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- assertEquals("nodes is not null", JSONObject.NULL, json.get("nodes"));
- }
-
- @Test
- public void testNodesQueryHealthyFalse() throws JSONException, Exception {
- WebResource r = resource();
- MockNM nm1 = rm.registerNode("h1:1234", 5120);
- MockNM nm2 = rm.registerNode("h2:1235", 5121);
- rm.sendNodeStarted(nm1);
- rm.NMwaitForState(nm1.getNodeId(), RMNodeState.RUNNING);
- rm.NMwaitForState(nm2.getNodeId(), RMNodeState.NEW);
- JSONObject json = r.path("ws").path("v1").path("cluster").path("nodes")
- .queryParam("healthy", "false").accept("application/json")
- .get(JSONObject.class);
-
- assertEquals("correct number of elements", 1, json.length());
- assertEquals("nodes is not null", JSONObject.NULL, json.get("nodes"));
- }
-
- @Test
- public void testNodesQueryHealthyInvalid() throws JSONException, Exception {
- WebResource r = resource();
- rm.registerNode("h1:1234", 5120);
- rm.registerNode("h2:1235", 5121);
-
- try {
- r.path("ws").path("v1").path("cluster").path("nodes")
- .queryParam("healthy", "tr").accept("application/json")
- .get(JSONObject.class);
- fail("should have thrown exception querying invalid healthy string");
- } catch (UniformInterfaceException ue) {
- ClientResponse response = ue.getResponse();
- assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
- JSONObject msg = response.getEntity(JSONObject.class);
- JSONObject exception = msg.getJSONObject("RemoteException");
- assertEquals("correct number of elements", 3, exception.length());
- String message = exception.getString("message");
- String type = exception.getString("exception");
- String classname = exception.getString("javaClassName");
- checkStringMatch(
- "exception message",
- "java.lang.Exception: Error: You must specify either true or false to query on health",
- message);
- checkStringMatch("exception type", "BadRequestException", type);
- checkStringMatch("exception classname",
- "org.apache.hadoop.yarn.webapp.BadRequestException", classname);
-
- } finally {
- rm.stop();
- }
- }
-
- public void testNodesHelper(String path) throws JSONException, Exception {
- WebResource r = resource();
- MockNM nm1 = rm.registerNode("h1:1234", 5120);
- MockNM nm2 = rm.registerNode("h2:1235", 5121);
- JSONObject json = r.path("ws").path("v1").path("cluster").path(path)
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject nodes = json.getJSONObject("nodes");
- assertEquals("correct number of elements", 1, nodes.length());
- JSONArray nodeArray = nodes.getJSONArray("node");
- assertEquals("correct number of elements", 2, nodeArray.length());
- JSONObject info = nodeArray.getJSONObject(0);
- String id = info.get("id").toString();
-
- if (id.matches("h1:1234")) {
- verifyNodeInfo(info, nm1, RMNodeState.NEW);
- verifyNodeInfo(nodeArray.getJSONObject(1), nm2, RMNodeState.NEW);
- } else {
- verifyNodeInfo(info, nm2, RMNodeState.NEW);
- verifyNodeInfo(nodeArray.getJSONObject(1), nm1, RMNodeState.NEW);
- }
- }
-
- @Test
- public void testSingleNode() throws JSONException, Exception {
- rm.registerNode("h1:1234", 5120);
- MockNM nm2 = rm.registerNode("h2:1235", 5121);
- testSingleNodeHelper("h2:1235", nm2);
- }
-
- @Test
- public void testSingleNodeSlash() throws JSONException, Exception {
- MockNM nm1 = rm.registerNode("h1:1234", 5120);
- rm.registerNode("h2:1235", 5121);
- testSingleNodeHelper("h1:1234/", nm1);
- }
-
- public void testSingleNodeHelper(String nodeid, MockNM nm)
+ public void verifyClusterSchedulerFifoGeneric(String type, String state,
+ float capacity, float usedCapacity, int minQueueCapacity,
+ int maxQueueCapacity, int numNodes, int usedNodeCapacity,
+ int availNodeCapacity, int totalNodeCapacity, int numContainers)
throws JSONException, Exception {
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("nodes")
- .path(nodeid).accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject info = json.getJSONObject("node");
- verifyNodeInfo(info, nm, RMNodeState.NEW);
- }
- @Test
- public void testNonexistNode() throws JSONException, Exception {
- rm.registerNode("h1:1234", 5120);
- rm.registerNode("h2:1235", 5121);
- WebResource r = resource();
- try {
- r.path("ws").path("v1").path("cluster").path("nodes")
- .path("node_invalid:99").accept("application/json")
- .get(JSONObject.class);
+ assertEquals("type doesn't match", "fifoScheduler", type);
+ assertEquals("qstate doesn't match", QueueState.RUNNING.toString(), state);
+ assertEquals("capacity doesn't match", 1.0, capacity, 0.0);
+ assertEquals("usedCapacity doesn't match", Float.NaN, usedCapacity, 0.0);
+ assertEquals("minQueueMemoryCapacity doesn't match", 1024, minQueueCapacity);
+ assertEquals("maxQueueMemoryCapacity doesn't match", 10240,
+ maxQueueCapacity);
+ assertEquals("numNodes doesn't match", 0, numNodes);
+ assertEquals("usedNodeCapacity doesn't match", 0, usedNodeCapacity);
+ assertEquals("availNodeCapacity doesn't match", 0, availNodeCapacity);
+ assertEquals("totalNodeCapacity doesn't match", 0, totalNodeCapacity);
+ assertEquals("numContainers doesn't match", 0, numContainers);
- fail("should have thrown exception on non-existent nodeid");
- } catch (UniformInterfaceException ue) {
- ClientResponse response = ue.getResponse();
- assertEquals(Status.NOT_FOUND, response.getClientResponseStatus());
-
- JSONObject msg = response.getEntity(JSONObject.class);
- JSONObject exception = msg.getJSONObject("RemoteException");
- assertEquals("correct number of elements", 3, exception.length());
- String message = exception.getString("message");
- String type = exception.getString("exception");
- String classname = exception.getString("javaClassName");
- checkStringMatch("exception message",
- "java.lang.Exception: nodeId, node_invalid:99, is not found", message);
- checkStringMatch("exception type", "NotFoundException", type);
- checkStringMatch("exception classname",
- "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
-
- } finally {
- rm.stop();
- }
- }
-
- @Test
- public void testInvalidNode() throws JSONException, Exception {
- rm.registerNode("h1:1234", 5120);
- rm.registerNode("h2:1235", 5121);
-
- WebResource r = resource();
- try {
- r.path("ws").path("v1").path("cluster").path("nodes")
- .path("node_invalid_foo").accept("application/json")
- .get(JSONObject.class);
-
- fail("should have thrown exception on non-existent nodeid");
- } catch (UniformInterfaceException ue) {
- ClientResponse response = ue.getResponse();
-
- assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
- JSONObject msg = response.getEntity(JSONObject.class);
- JSONObject exception = msg.getJSONObject("RemoteException");
- assertEquals("correct number of elements", 3, exception.length());
- String message = exception.getString("message");
- String type = exception.getString("exception");
- String classname = exception.getString("javaClassName");
- checkStringMatch("exception message",
- "Invalid NodeId \\[node_invalid_foo\\]. Expected host:port", message);
- checkStringMatch("exception type", "IllegalArgumentException", type);
- checkStringMatch("exception classname",
- "java.lang.IllegalArgumentException", classname);
- } finally {
- rm.stop();
- }
- }
-
- public void verifyNodeInfo(JSONObject nodeInfo, MockNM nm,
- RMNodeState expectedState) throws JSONException, Exception {
- assertEquals("correct number of elements", 11, nodeInfo.length());
- String state = nodeInfo.get("state").toString();
- assertTrue("stated doesn't match: " + state,
- state.matches(expectedState.toString()));
- String rack = nodeInfo.get("rack").toString();
- assertTrue("rack doesn't match: " + rack, rack.matches("/default-rack"));
- String healthStatus = nodeInfo.get("healthStatus").toString();
- assertTrue("healthStatus doesn't match: " + healthStatus,
- healthStatus.matches("Healthy"));
- String id = nodeInfo.get("id").toString();
- assertTrue("id doesn't match, got: " + id + " expected: "
- + nm.getNodeId().toString(), id.matches(nm.getNodeId().toString()));
- String nodeHostName = nodeInfo.get("nodeHostName").toString();
- assertTrue("hostname doesn't match, got: " + nodeHostName + " expected: "
- + nm.getNodeId().getHost(),
- nodeHostName.matches(nm.getNodeId().getHost()));
-
- String nodeHTTPAddress = nodeInfo.get("nodeHTTPAddress").toString();
- String expectedHttpAddress = nm.getNodeId().getHost() + ":"
- + nm.getHttpPort();
- assertTrue("nodeHTTPAddress doesn't match, got: " + nodeHTTPAddress
- + " expected: " + expectedHttpAddress,
- nodeHTTPAddress.matches(expectedHttpAddress));
- // could use this for other checks
- RMNode node = rm.getRMContext().getRMNodes().get(nm.getNodeId());
- long lastHealthUpdate = nodeInfo.getLong("lastHealthUpdate");
- long expectedHealthUpdate = node.getNodeHealthStatus()
- .getLastHealthReportTime();
- assertEquals("lastHealthUpdate doesn't match, got: " + lastHealthUpdate
- + " expected: " + expectedHealthUpdate, expectedHealthUpdate,
- lastHealthUpdate);
- String healthReport = nodeInfo.get("healthReport").toString();
- assertTrue("healthReport doesn't match: " + healthReport,
- healthReport.matches("Healthy"));
-
- int numContainers = nodeInfo.getInt("numContainers");
- assertEquals("numContainers doesn't match: " + numContainers, 0,
- numContainers);
-
- long usedMemoryMB = nodeInfo.getLong("usedMemoryMB");
- assertEquals("usedMemoryMB doesn't match: " + usedMemoryMB, 0, usedMemoryMB);
-
- long availMemoryMB = nodeInfo.getLong("availMemoryMB");
- assertEquals("availMemoryMB doesn't match: " + availMemoryMB, 0,
- availMemoryMB);
- }
-
- @Test
- public void testApps() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- RMApp app1 = rm.submitApp(1024);
- amNodeManager.nodeHeartbeat(true);
- testAppsHelper("apps", app1);
- rm.stop();
-
- }
-
- @Test
- public void testAppsSlash() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- RMApp app1 = rm.submitApp(1024);
- amNodeManager.nodeHeartbeat(true);
- testAppsHelper("apps/", app1);
- rm.stop();
-
- }
-
- public void testAppsHelper(String path, RMApp app) throws JSONException,
- Exception {
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path(path)
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject apps = json.getJSONObject("apps");
- assertEquals("correct number of elements", 1, apps.length());
- JSONArray array = apps.getJSONArray("app");
- assertEquals("correct number of elements", 1, array.length());
- verifyAppInfo(array.getJSONObject(0), app);
-
- }
-
- @Test
- public void testAppsQueryState() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- RMApp app1 = rm.submitApp(1024);
- amNodeManager.nodeHeartbeat(true);
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("apps")
- .queryParam("state", RMAppState.ACCEPTED.toString())
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject apps = json.getJSONObject("apps");
- assertEquals("correct number of elements", 1, apps.length());
- JSONArray array = apps.getJSONArray("app");
- assertEquals("correct number of elements", 1, array.length());
- verifyAppInfo(array.getJSONObject(0), app1);
- rm.stop();
- }
-
- @Test
- public void testAppsQueryStateNone() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- rm.submitApp(1024);
- amNodeManager.nodeHeartbeat(true);
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("apps")
- .queryParam("state", RMAppState.RUNNING.toString())
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- assertEquals("apps is not null", JSONObject.NULL, json.get("apps"));
- rm.stop();
- }
-
- @Test
- public void testAppsQueryStateInvalid() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- rm.submitApp(1024);
- amNodeManager.nodeHeartbeat(true);
- WebResource r = resource();
-
- try {
- r.path("ws").path("v1").path("cluster").path("apps")
- .queryParam("state", "INVALID_test").accept("application/json")
- .get(JSONObject.class);
- fail("should have thrown exception on invalid state query");
- } catch (UniformInterfaceException ue) {
- ClientResponse response = ue.getResponse();
-
- assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
- JSONObject msg = response.getEntity(JSONObject.class);
- JSONObject exception = msg.getJSONObject("RemoteException");
- assertEquals("correct number of elements", 3, exception.length());
- String message = exception.getString("message");
- String type = exception.getString("exception");
- String classname = exception.getString("javaClassName");
- checkStringMatch(
- "exception message",
- "No enum const class org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState.INVALID_test",
- message);
- checkStringMatch("exception type", "IllegalArgumentException", type);
- checkStringMatch("exception classname",
- "java.lang.IllegalArgumentException", classname);
-
- } finally {
- rm.stop();
- }
- }
-
- @Test
- public void testAppsQueryUser() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- rm.submitApp(1024);
- rm.submitApp(1024);
-
- amNodeManager.nodeHeartbeat(true);
- WebResource r = resource();
- JSONObject json = r
- .path("ws")
- .path("v1")
- .path("cluster")
- .path("apps")
- .queryParam("user",
- UserGroupInformation.getCurrentUser().getShortUserName())
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject apps = json.getJSONObject("apps");
- assertEquals("correct number of elements", 1, apps.length());
- JSONArray array = apps.getJSONArray("app");
- assertEquals("correct number of elements", 2, array.length());
- rm.stop();
- }
-
- @Test
- public void testAppsQueryQueue() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- rm.submitApp(1024);
- rm.submitApp(1024);
-
- amNodeManager.nodeHeartbeat(true);
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("apps")
- .queryParam("queue", "default").accept("application/json")
- .get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject apps = json.getJSONObject("apps");
- assertEquals("correct number of elements", 1, apps.length());
- JSONArray array = apps.getJSONArray("app");
- assertEquals("correct number of elements", 2, array.length());
- rm.stop();
- }
-
- @Test
- public void testAppsQueryLimit() throws JSONException, Exception {
- rm.start();
- rm.registerNode("amNM:1234", 2048);
- rm.submitApp(1024);
- rm.submitApp(1024);
- rm.submitApp(1024);
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("apps")
- .queryParam("limit", "2").accept("application/json")
- .get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject apps = json.getJSONObject("apps");
- assertEquals("correct number of elements", 1, apps.length());
- JSONArray array = apps.getJSONArray("app");
- assertEquals("correct number of elements", 2, array.length());
- rm.stop();
- }
-
- @Test
- public void testAppsQueryStartBegin() throws JSONException, Exception {
- rm.start();
- long start = System.currentTimeMillis();
- Thread.sleep(1);
- rm.registerNode("amNM:1234", 2048);
- rm.submitApp(1024);
- rm.submitApp(1024);
- rm.submitApp(1024);
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("apps")
- .queryParam("startedTimeBegin", String.valueOf(start))
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject apps = json.getJSONObject("apps");
- assertEquals("correct number of elements", 1, apps.length());
- JSONArray array = apps.getJSONArray("app");
- assertEquals("correct number of elements", 3, array.length());
- rm.stop();
- }
-
- @Test
- public void testAppsQueryStartBeginSome() throws JSONException, Exception {
- rm.start();
- rm.registerNode("amNM:1234", 2048);
- rm.submitApp(1024);
- rm.submitApp(1024);
- long start = System.currentTimeMillis();
- Thread.sleep(1);
- rm.submitApp(1024);
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("apps")
- .queryParam("startedTimeBegin", String.valueOf(start))
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject apps = json.getJSONObject("apps");
- assertEquals("correct number of elements", 1, apps.length());
- JSONArray array = apps.getJSONArray("app");
- assertEquals("correct number of elements", 1, array.length());
- rm.stop();
- }
-
- @Test
- public void testAppsQueryStartEnd() throws JSONException, Exception {
- rm.start();
- rm.registerNode("amNM:1234", 2048);
- long end = System.currentTimeMillis();
- Thread.sleep(1);
- rm.submitApp(1024);
- rm.submitApp(1024);
- rm.submitApp(1024);
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("apps")
- .queryParam("startedTimeEnd", String.valueOf(end))
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- assertEquals("apps is not null", JSONObject.NULL, json.get("apps"));
- rm.stop();
- }
-
- @Test
- public void testAppsQueryStartBeginEnd() throws JSONException, Exception {
- rm.start();
- rm.registerNode("amNM:1234", 2048);
- long start = System.currentTimeMillis();
- Thread.sleep(1);
- rm.submitApp(1024);
- rm.submitApp(1024);
- long end = System.currentTimeMillis();
- Thread.sleep(1);
- rm.submitApp(1024);
-
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("apps")
- .queryParam("startedTimeBegin", String.valueOf(start))
- .queryParam("startedTimeEnd", String.valueOf(end))
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject apps = json.getJSONObject("apps");
- assertEquals("correct number of elements", 1, apps.length());
- JSONArray array = apps.getJSONArray("app");
- assertEquals("correct number of elements", 2, array.length());
- rm.stop();
- }
-
- @Test
- public void testAppsQueryFinishBegin() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- long start = System.currentTimeMillis();
- Thread.sleep(1);
- RMApp app1 = rm.submitApp(1024);
- amNodeManager.nodeHeartbeat(true);
- // finish App
- MockAM am = rm
- .sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId());
- am.registerAppAttempt();
- am.unregisterAppAttempt();
- rm.submitApp(1024);
- rm.submitApp(1024);
-
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("apps")
- .queryParam("finishedTimeBegin", String.valueOf(start))
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject apps = json.getJSONObject("apps");
- assertEquals("correct number of elements", 1, apps.length());
- JSONArray array = apps.getJSONArray("app");
- assertEquals("correct number of elements", 1, array.length());
- rm.stop();
- }
-
- @Test
- public void testAppsQueryFinishEnd() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- RMApp app1 = rm.submitApp(1024);
- amNodeManager.nodeHeartbeat(true);
- // finish App
- MockAM am = rm
- .sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId());
- am.registerAppAttempt();
- am.unregisterAppAttempt();
-
- rm.submitApp(1024);
- rm.submitApp(1024);
- long end = System.currentTimeMillis();
-
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("apps")
- .queryParam("finishedTimeEnd", String.valueOf(end))
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject apps = json.getJSONObject("apps");
- assertEquals("correct number of elements", 1, apps.length());
- JSONArray array = apps.getJSONArray("app");
- assertEquals("correct number of elements", 3, array.length());
- rm.stop();
- }
-
- @Test
- public void testAppsQueryFinishBeginEnd() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- long start = System.currentTimeMillis();
- Thread.sleep(1);
- RMApp app1 = rm.submitApp(1024);
- amNodeManager.nodeHeartbeat(true);
- // finish App
- MockAM am = rm
- .sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId());
- am.registerAppAttempt();
- am.unregisterAppAttempt();
-
- rm.submitApp(1024);
- rm.submitApp(1024);
- long end = System.currentTimeMillis();
-
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("apps")
- .queryParam("finishedTimeBegin", String.valueOf(start))
- .queryParam("finishedTimeEnd", String.valueOf(end))
- .accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- JSONObject apps = json.getJSONObject("apps");
- assertEquals("correct number of elements", 1, apps.length());
- JSONArray array = apps.getJSONArray("app");
- assertEquals("correct number of elements", 1, array.length());
- rm.stop();
- }
-
- @Test
- public void testSingleApp() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- RMApp app1 = rm.submitApp(1024);
- amNodeManager.nodeHeartbeat(true);
- testSingleAppsHelper(app1.getApplicationId().toString(), app1);
- rm.stop();
- }
-
- @Test
- public void testSingleAppsSlash() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- RMApp app1 = rm.submitApp(1024);
- amNodeManager.nodeHeartbeat(true);
- testSingleAppsHelper(app1.getApplicationId().toString() + "/", app1);
- rm.stop();
- }
-
- @Test
- public void testInvalidApp() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- rm.submitApp(1024);
- amNodeManager.nodeHeartbeat(true);
- WebResource r = resource();
-
- try {
- r.path("ws").path("v1").path("cluster").path("apps")
- .path("application_invalid_12").accept("application/json")
- .get(JSONObject.class);
- fail("should have thrown exception on invalid appid");
- } catch (UniformInterfaceException ue) {
- ClientResponse response = ue.getResponse();
-
- assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
- JSONObject msg = response.getEntity(JSONObject.class);
- JSONObject exception = msg.getJSONObject("RemoteException");
- assertEquals("correct number of elements", 3, exception.length());
- String message = exception.getString("message");
- String type = exception.getString("exception");
- String classname = exception.getString("javaClassName");
- checkStringMatch("exception message", "For input string: \"invalid\"",
- message);
- checkStringMatch("exception type", "NumberFormatException", type);
- checkStringMatch("exception classname",
- "java.lang.NumberFormatException", classname);
-
- } finally {
- rm.stop();
- }
- }
-
- @Test
- public void testNonexistApp() throws JSONException, Exception {
- rm.start();
- MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
- rm.submitApp(1024);
- amNodeManager.nodeHeartbeat(true);
- WebResource r = resource();
-
- try {
- r.path("ws").path("v1").path("cluster").path("apps")
- .path("application_00000_0099").accept("application/json")
- .get(JSONObject.class);
- fail("should have thrown exception on invalid appid");
- } catch (UniformInterfaceException ue) {
- ClientResponse response = ue.getResponse();
-
- assertEquals(Status.NOT_FOUND, response.getClientResponseStatus());
- JSONObject msg = response.getEntity(JSONObject.class);
- JSONObject exception = msg.getJSONObject("RemoteException");
- assertEquals("correct number of elements", 3, exception.length());
- String message = exception.getString("message");
- String type = exception.getString("exception");
- String classname = exception.getString("javaClassName");
- checkStringMatch("exception message",
- "java.lang.Exception: app with id: application_00000_0099 not found",
- message);
- checkStringMatch("exception type", "NotFoundException", type);
- checkStringMatch("exception classname",
- "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
- } finally {
- rm.stop();
- }
- }
-
- public void testSingleAppsHelper(String path, RMApp app)
- throws JSONException, Exception {
- WebResource r = resource();
- JSONObject json = r.path("ws").path("v1").path("cluster").path("apps")
- .path(path).accept("application/json").get(JSONObject.class);
- assertEquals("correct number of elements", 1, json.length());
- verifyAppInfo(json.getJSONObject("app"), app);
- }
-
- public void verifyAppInfo(JSONObject info, RMApp app) throws JSONException,
- Exception {
-
- // 15 because trackingUrl not assigned yet
- assertEquals("correct number of elements", 15, info.length());
- String id = info.getString("id");
- String expectedId = app.getApplicationId().toString();
- checkStringMatch("id", expectedId, id);
-
- String user = info.getString("user");
- String expectedUser = app.getUser();
- checkStringMatch("user", expectedUser, user);
-
- checkStringMatch("name", "", info.getString("name"));
- checkStringMatch("queue", "default", info.getString("queue"));
- checkStringMatch("state", RMAppState.ACCEPTED.toString(),
- info.getString("state"));
- checkStringMatch("finalStatus",
- FinalApplicationStatus.UNDEFINED.toString(),
- info.getString("finalStatus"));
- assertEquals("progress doesn't match", 0, info.getDouble("progress"), 0.0);
- checkStringMatch("trackingUI", "UNASSIGNED", info.getString("trackingUI"));
- checkStringMatch("diagnostics", "", info.getString("diagnostics"));
- assertEquals("clusterId doesn't match", ResourceManager.clusterTimeStamp,
- info.getLong("clusterId"));
- assertEquals("startedTime doesn't match", app.getStartTime(),
- info.getLong("startedTime"));
- assertEquals("finishedTime doesn't match", app.getFinishTime(),
- info.getLong("finishedTime"));
- assertTrue("elapsed time not greater than 0",
- info.getLong("elapsedTime") > 0);
- checkStringMatch("amHostHttpAddress", app.getCurrentAppAttempt()
- .getMasterContainer().getNodeHttpAddress(),
- info.getString("amHostHttpAddress"));
- assertTrue("amContainerLogs doesn't match",
- info.getString("amContainerLogs").startsWith("http://"));
- }
-
- private void checkStringMatch(String print, String expected, String got) {
- assertTrue(
- print + " doesn't match, got: " + got + " expected: " + expected,
- got.matches(expected));
}
}
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesApps.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesApps.java
new file mode 100644
index 00000000000..61012aa483f
--- /dev/null
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesApps.java
@@ -0,0 +1,756 @@
+/**
+ * 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.webapp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.StringReader;
+
+import javax.ws.rs.core.MediaType;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.yarn.server.resourcemanager.MockAM;
+import org.apache.hadoop.yarn.server.resourcemanager.MockNM;
+import org.apache.hadoop.yarn.server.resourcemanager.MockRM;
+import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
+import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
+import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
+import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState;
+import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
+import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
+import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.servlet.GuiceServletContextListener;
+import com.google.inject.servlet.ServletModule;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.ClientResponse.Status;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+
+public class TestRMWebServicesApps extends JerseyTest {
+
+ private static MockRM rm;
+
+ private Injector injector = Guice.createInjector(new ServletModule() {
+ @Override
+ protected void configureServlets() {
+ bind(JAXBContextResolver.class);
+ bind(RMWebServices.class);
+ bind(GenericExceptionHandler.class);
+ rm = new MockRM(new Configuration());
+ bind(ResourceManager.class).toInstance(rm);
+ bind(RMContext.class).toInstance(rm.getRMContext());
+ bind(ApplicationACLsManager.class).toInstance(
+ rm.getApplicationACLsManager());
+ serve("/*").with(GuiceContainer.class);
+ }
+ });
+
+ public class GuiceServletConfig extends GuiceServletContextListener {
+
+ @Override
+ protected Injector getInjector() {
+ return injector;
+ }
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public TestRMWebServicesApps() {
+ super(new WebAppDescriptor.Builder(
+ "org.apache.hadoop.yarn.server.resourcemanager.webapp")
+ .contextListenerClass(GuiceServletConfig.class)
+ .filterClass(com.google.inject.servlet.GuiceFilter.class)
+ .contextPath("jersey-guice-filter").servletPath("/").build());
+ }
+
+ @Test
+ public void testApps() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ RMApp app1 = rm.submitApp(1024);
+ amNodeManager.nodeHeartbeat(true);
+ testAppsHelper("apps", app1, MediaType.APPLICATION_JSON);
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsSlash() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ RMApp app1 = rm.submitApp(1024);
+ amNodeManager.nodeHeartbeat(true);
+ testAppsHelper("apps/", app1, MediaType.APPLICATION_JSON);
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsDefault() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ RMApp app1 = rm.submitApp(1024);
+ amNodeManager.nodeHeartbeat(true);
+ testAppsHelper("apps/", app1, "");
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsXML() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ RMApp app1 = rm.submitApp(1024, "testwordcount", "user1");
+ amNodeManager.nodeHeartbeat(true);
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").accept(MediaType.APPLICATION_XML)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodesApps = dom.getElementsByTagName("apps");
+ assertEquals("incorrect number of elements", 1, nodesApps.getLength());
+ NodeList nodes = dom.getElementsByTagName("app");
+ assertEquals("incorrect number of elements", 1, nodes.getLength());
+ verifyAppsXML(nodes, app1);
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsXMLMulti() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ rm.submitApp(1024, "testwordcount", "user1");
+ rm.submitApp(2048, "testwordcount2", "user1");
+
+ amNodeManager.nodeHeartbeat(true);
+ WebResource r = resource();
+
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").accept(MediaType.APPLICATION_XML)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodesApps = dom.getElementsByTagName("apps");
+ assertEquals("incorrect number of elements", 1, nodesApps.getLength());
+ NodeList nodes = dom.getElementsByTagName("app");
+ assertEquals("incorrect number of elements", 2, nodes.getLength());
+ rm.stop();
+ }
+
+ public void testAppsHelper(String path, RMApp app, String media)
+ throws JSONException, Exception {
+ WebResource r = resource();
+
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path(path).accept(media).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject apps = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, apps.length());
+ JSONArray array = apps.getJSONArray("app");
+ assertEquals("incorrect number of elements", 1, array.length());
+ verifyAppInfo(array.getJSONObject(0), app);
+
+ }
+
+ @Test
+ public void testAppsQueryState() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ RMApp app1 = rm.submitApp(1024);
+ amNodeManager.nodeHeartbeat(true);
+ WebResource r = resource();
+
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").queryParam("state", RMAppState.ACCEPTED.toString())
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject apps = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, apps.length());
+ JSONArray array = apps.getJSONArray("app");
+ assertEquals("incorrect number of elements", 1, array.length());
+ verifyAppInfo(array.getJSONObject(0), app1);
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsQueryStateNone() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ rm.submitApp(1024);
+ amNodeManager.nodeHeartbeat(true);
+ WebResource r = resource();
+
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").queryParam("state", RMAppState.RUNNING.toString())
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ assertEquals("apps is not null", JSONObject.NULL, json.get("apps"));
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsQueryStateInvalid() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ rm.submitApp(1024);
+ amNodeManager.nodeHeartbeat(true);
+ WebResource r = resource();
+
+ try {
+ r.path("ws").path("v1").path("cluster").path("apps")
+ .queryParam("state", "INVALID_test")
+ .accept(MediaType.APPLICATION_JSON).get(JSONObject.class);
+ fail("should have thrown exception on invalid state query");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils
+ .checkStringMatch(
+ "exception message",
+ "No enum const class org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState.INVALID_test",
+ message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "IllegalArgumentException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "java.lang.IllegalArgumentException", classname);
+
+ } finally {
+ rm.stop();
+ }
+ }
+
+ @Test
+ public void testAppsQueryUser() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+
+ amNodeManager.nodeHeartbeat(true);
+ WebResource r = resource();
+ ClientResponse response = r
+ .path("ws")
+ .path("v1")
+ .path("cluster")
+ .path("apps")
+ .queryParam("user",
+ UserGroupInformation.getCurrentUser().getShortUserName())
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject apps = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, apps.length());
+ JSONArray array = apps.getJSONArray("app");
+ assertEquals("incorrect number of elements", 2, array.length());
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsQueryQueue() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+
+ amNodeManager.nodeHeartbeat(true);
+ WebResource r = resource();
+
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").queryParam("queue", "default")
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject apps = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, apps.length());
+ JSONArray array = apps.getJSONArray("app");
+ assertEquals("incorrect number of elements", 2, array.length());
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsQueryLimit() throws JSONException, Exception {
+ rm.start();
+ rm.registerNode("amNM:1234", 2048);
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").queryParam("limit", "2")
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject apps = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, apps.length());
+ JSONArray array = apps.getJSONArray("app");
+ assertEquals("incorrect number of elements", 2, array.length());
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsQueryStartBegin() throws JSONException, Exception {
+ rm.start();
+ long start = System.currentTimeMillis();
+ Thread.sleep(1);
+ rm.registerNode("amNM:1234", 2048);
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").queryParam("startedTimeBegin", String.valueOf(start))
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject apps = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, apps.length());
+ JSONArray array = apps.getJSONArray("app");
+ assertEquals("incorrect number of elements", 3, array.length());
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsQueryStartBeginSome() throws JSONException, Exception {
+ rm.start();
+ rm.registerNode("amNM:1234", 2048);
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+ long start = System.currentTimeMillis();
+ Thread.sleep(1);
+ rm.submitApp(1024);
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").queryParam("startedTimeBegin", String.valueOf(start))
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject apps = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, apps.length());
+ JSONArray array = apps.getJSONArray("app");
+ assertEquals("incorrect number of elements", 1, array.length());
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsQueryStartEnd() throws JSONException, Exception {
+ rm.start();
+ rm.registerNode("amNM:1234", 2048);
+ long end = System.currentTimeMillis();
+ Thread.sleep(1);
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").queryParam("startedTimeEnd", String.valueOf(end))
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ assertEquals("apps is not null", JSONObject.NULL, json.get("apps"));
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsQueryStartBeginEnd() throws JSONException, Exception {
+ rm.start();
+ rm.registerNode("amNM:1234", 2048);
+ long start = System.currentTimeMillis();
+ Thread.sleep(1);
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+ long end = System.currentTimeMillis();
+ Thread.sleep(1);
+ rm.submitApp(1024);
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").queryParam("startedTimeBegin", String.valueOf(start))
+ .queryParam("startedTimeEnd", String.valueOf(end))
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject apps = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, apps.length());
+ JSONArray array = apps.getJSONArray("app");
+ assertEquals("incorrect number of elements", 2, array.length());
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsQueryFinishBegin() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ long start = System.currentTimeMillis();
+ Thread.sleep(1);
+ RMApp app1 = rm.submitApp(1024);
+ amNodeManager.nodeHeartbeat(true);
+ // finish App
+ MockAM am = rm
+ .sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId());
+ am.registerAppAttempt();
+ am.unregisterAppAttempt();
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").queryParam("finishedTimeBegin", String.valueOf(start))
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject apps = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, apps.length());
+ JSONArray array = apps.getJSONArray("app");
+ assertEquals("incorrect number of elements", 1, array.length());
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsQueryFinishEnd() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ RMApp app1 = rm.submitApp(1024);
+ amNodeManager.nodeHeartbeat(true);
+ // finish App
+ MockAM am = rm
+ .sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId());
+ am.registerAppAttempt();
+ am.unregisterAppAttempt();
+
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+ long end = System.currentTimeMillis();
+
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").queryParam("finishedTimeEnd", String.valueOf(end))
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject apps = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, apps.length());
+ JSONArray array = apps.getJSONArray("app");
+ assertEquals("incorrect number of elements", 3, array.length());
+ rm.stop();
+ }
+
+ @Test
+ public void testAppsQueryFinishBeginEnd() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ long start = System.currentTimeMillis();
+ Thread.sleep(1);
+ RMApp app1 = rm.submitApp(1024);
+ amNodeManager.nodeHeartbeat(true);
+ // finish App
+ MockAM am = rm
+ .sendAMLaunched(app1.getCurrentAppAttempt().getAppAttemptId());
+ am.registerAppAttempt();
+ am.unregisterAppAttempt();
+
+ rm.submitApp(1024);
+ rm.submitApp(1024);
+ long end = System.currentTimeMillis();
+
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").queryParam("finishedTimeBegin", String.valueOf(start))
+ .queryParam("finishedTimeEnd", String.valueOf(end))
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject apps = json.getJSONObject("apps");
+ assertEquals("incorrect number of elements", 1, apps.length());
+ JSONArray array = apps.getJSONArray("app");
+ assertEquals("incorrect number of elements", 1, array.length());
+ rm.stop();
+ }
+
+ @Test
+ public void testSingleApp() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ RMApp app1 = rm.submitApp(1024, "testwordcount", "user1");
+ amNodeManager.nodeHeartbeat(true);
+ testSingleAppsHelper(app1.getApplicationId().toString(), app1,
+ MediaType.APPLICATION_JSON);
+ rm.stop();
+ }
+
+ @Test
+ public void testSingleAppsSlash() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ RMApp app1 = rm.submitApp(1024);
+ amNodeManager.nodeHeartbeat(true);
+ testSingleAppsHelper(app1.getApplicationId().toString() + "/", app1,
+ MediaType.APPLICATION_JSON);
+ rm.stop();
+ }
+
+ @Test
+ public void testSingleAppsDefault() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ RMApp app1 = rm.submitApp(1024);
+ amNodeManager.nodeHeartbeat(true);
+ testSingleAppsHelper(app1.getApplicationId().toString() + "/", app1, "");
+ rm.stop();
+ }
+
+ @Test
+ public void testInvalidApp() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ rm.submitApp(1024);
+ amNodeManager.nodeHeartbeat(true);
+ WebResource r = resource();
+
+ try {
+ r.path("ws").path("v1").path("cluster").path("apps")
+ .path("application_invalid_12").accept(MediaType.APPLICATION_JSON)
+ .get(JSONObject.class);
+ fail("should have thrown exception on invalid appid");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+
+ assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils.checkStringMatch("exception message",
+ "For input string: \"invalid\"", message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "NumberFormatException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "java.lang.NumberFormatException", classname);
+
+ } finally {
+ rm.stop();
+ }
+ }
+
+ @Test
+ public void testNonexistApp() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ rm.submitApp(1024, "testwordcount", "user1");
+ amNodeManager.nodeHeartbeat(true);
+ WebResource r = resource();
+
+ try {
+ r.path("ws").path("v1").path("cluster").path("apps")
+ .path("application_00000_0099").accept(MediaType.APPLICATION_JSON)
+ .get(JSONObject.class);
+ fail("should have thrown exception on invalid appid");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+
+ assertEquals(Status.NOT_FOUND, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils.checkStringMatch("exception message",
+ "java.lang.Exception: app with id: application_00000_0099 not found",
+ message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "NotFoundException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
+ } finally {
+ rm.stop();
+ }
+ }
+
+ public void testSingleAppsHelper(String path, RMApp app, String media)
+ throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").path(path).accept(media).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+
+ assertEquals("incorrect number of elements", 1, json.length());
+ verifyAppInfo(json.getJSONObject("app"), app);
+ }
+
+ @Test
+ public void testSingleAppsXML() throws JSONException, Exception {
+ rm.start();
+ MockNM amNodeManager = rm.registerNode("amNM:1234", 2048);
+ RMApp app1 = rm.submitApp(1024, "testwordcount", "user1");
+ amNodeManager.nodeHeartbeat(true);
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("apps").path(app1.getApplicationId().toString())
+ .accept(MediaType.APPLICATION_XML).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodes = dom.getElementsByTagName("app");
+ assertEquals("incorrect number of elements", 1, nodes.getLength());
+ verifyAppsXML(nodes, app1);
+ rm.stop();
+ }
+
+ public void verifyAppsXML(NodeList nodes, RMApp app) throws JSONException,
+ Exception {
+
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Element element = (Element) nodes.item(i);
+
+ verifyAppInfoGeneric(app,
+ WebServicesTestUtils.getXmlString(element, "id"),
+ WebServicesTestUtils.getXmlString(element, "user"),
+ WebServicesTestUtils.getXmlString(element, "name"),
+ WebServicesTestUtils.getXmlString(element, "queue"),
+ WebServicesTestUtils.getXmlString(element, "state"),
+ WebServicesTestUtils.getXmlString(element, "finalStatus"),
+ WebServicesTestUtils.getXmlFloat(element, "progress"),
+ WebServicesTestUtils.getXmlString(element, "trackingUI"),
+ WebServicesTestUtils.getXmlString(element, "diagnostics"),
+ WebServicesTestUtils.getXmlLong(element, "clusterId"),
+ WebServicesTestUtils.getXmlLong(element, "startedTime"),
+ WebServicesTestUtils.getXmlLong(element, "finishedTime"),
+ WebServicesTestUtils.getXmlLong(element, "elapsedTime"),
+ WebServicesTestUtils.getXmlString(element, "amHostHttpAddress"),
+ WebServicesTestUtils.getXmlString(element, "amContainerLogs"));
+ }
+ }
+
+ public void verifyAppInfo(JSONObject info, RMApp app) throws JSONException,
+ Exception {
+
+ // 15 because trackingUrl not assigned yet
+ assertEquals("incorrect number of elements", 15, info.length());
+
+ verifyAppInfoGeneric(app, info.getString("id"), info.getString("user"),
+ info.getString("name"), info.getString("queue"),
+ info.getString("state"), info.getString("finalStatus"),
+ (float) info.getDouble("progress"), info.getString("trackingUI"),
+ info.getString("diagnostics"), info.getLong("clusterId"),
+ info.getLong("startedTime"), info.getLong("finishedTime"),
+ info.getLong("elapsedTime"), info.getString("amHostHttpAddress"),
+ info.getString("amContainerLogs"));
+ }
+
+ public void verifyAppInfoGeneric(RMApp app, String id, String user,
+ String name, String queue, String state, String finalStatus,
+ float progress, String trackingUI, String diagnostics, long clusterId,
+ long startedTime, long finishedTime, long elapsedTime,
+ String amHostHttpAddress, String amContainerLogs) throws JSONException,
+ Exception {
+
+ WebServicesTestUtils.checkStringMatch("id", app.getApplicationId()
+ .toString(), id);
+ WebServicesTestUtils.checkStringMatch("user", app.getUser(), user);
+ WebServicesTestUtils.checkStringMatch("name", app.getName(), name);
+ WebServicesTestUtils.checkStringMatch("queue", app.getQueue(), queue);
+ WebServicesTestUtils.checkStringMatch("state", app.getState().toString(),
+ state);
+ WebServicesTestUtils.checkStringMatch("finalStatus", app
+ .getFinalApplicationStatus().toString(), finalStatus);
+ assertEquals("progress doesn't match", 0, progress, 0.0);
+ WebServicesTestUtils.checkStringMatch("trackingUI", "UNASSIGNED",
+ trackingUI);
+ WebServicesTestUtils.checkStringMatch("diagnostics", app.getDiagnostics()
+ .toString(), diagnostics);
+ assertEquals("clusterId doesn't match", ResourceManager.clusterTimeStamp,
+ clusterId);
+ assertEquals("startedTime doesn't match", app.getStartTime(), startedTime);
+ assertEquals("finishedTime doesn't match", app.getFinishTime(),
+ finishedTime);
+ assertTrue("elapsed time not greater than 0", elapsedTime > 0);
+ WebServicesTestUtils.checkStringMatch("amHostHttpAddress", app
+ .getCurrentAppAttempt().getMasterContainer().getNodeHttpAddress(),
+ amHostHttpAddress);
+ assertTrue("amContainerLogs doesn't match",
+ amContainerLogs.startsWith("http://"));
+ }
+
+}
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesCapacitySched.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesCapacitySched.java
new file mode 100644
index 00000000000..0ffe8a98e2f
--- /dev/null
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesCapacitySched.java
@@ -0,0 +1,316 @@
+/**
+ * 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.webapp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.StringReader;
+
+import javax.ws.rs.core.MediaType;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
+import org.apache.hadoop.yarn.server.resourcemanager.MockRM;
+import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
+import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
+import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
+import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler;
+import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration;
+import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
+import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
+import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.servlet.GuiceServletContextListener;
+import com.google.inject.servlet.ServletModule;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+
+public class TestRMWebServicesCapacitySched extends JerseyTest {
+
+ private static MockRM rm;
+ private CapacitySchedulerConfiguration csConf;
+
+ private Injector injector = Guice.createInjector(new ServletModule() {
+ @Override
+ protected void configureServlets() {
+ bind(JAXBContextResolver.class);
+ bind(RMWebServices.class);
+ bind(GenericExceptionHandler.class);
+ csConf = new CapacitySchedulerConfiguration();
+ csConf.setClass(YarnConfiguration.RM_SCHEDULER, CapacityScheduler.class,
+ ResourceScheduler.class);
+ setupQueueConfiguration(csConf);
+ rm = new MockRM(csConf);
+ bind(ResourceManager.class).toInstance(rm);
+ bind(RMContext.class).toInstance(rm.getRMContext());
+ bind(ApplicationACLsManager.class).toInstance(
+ rm.getApplicationACLsManager());
+ serve("/*").with(GuiceContainer.class);
+ }
+ });
+
+ public class GuiceServletConfig extends GuiceServletContextListener {
+
+ @Override
+ protected Injector getInjector() {
+ return injector;
+ }
+ }
+
+ private static void setupQueueConfiguration(
+ CapacitySchedulerConfiguration conf) {
+
+ // Define top-level queues
+ conf.setQueues(CapacityScheduler.ROOT, new String[] { "a", "b" });
+ conf.setCapacity(CapacityScheduler.ROOT, 100);
+
+ final String A = CapacityScheduler.ROOT + ".a";
+ conf.setCapacity(A, 10);
+ conf.setMaximumCapacity(A, 50);
+
+ final String B = CapacityScheduler.ROOT + ".b";
+ conf.setCapacity(B, 90);
+
+ // Define 2nd-level queues
+ final String A1 = A + ".a1";
+ final String A2 = A + ".a2";
+ conf.setQueues(A, new String[] { "a1", "a2" });
+ conf.setCapacity(A1, 30);
+ conf.setMaximumCapacity(A1, 50);
+
+ conf.setUserLimitFactor(A1, 100.0f);
+ conf.setCapacity(A2, 70);
+ conf.setUserLimitFactor(A2, 100.0f);
+
+ final String B1 = B + ".b1";
+ final String B2 = B + ".b2";
+ final String B3 = B + ".b3";
+ conf.setQueues(B, new String[] { "b1", "b2", "b3" });
+ conf.setCapacity(B1, 50);
+ conf.setUserLimitFactor(B1, 100.0f);
+ conf.setCapacity(B2, 30);
+ conf.setUserLimitFactor(B2, 100.0f);
+ conf.setCapacity(B3, 20);
+ conf.setUserLimitFactor(B3, 100.0f);
+
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public TestRMWebServicesCapacitySched() {
+ super(new WebAppDescriptor.Builder(
+ "org.apache.hadoop.yarn.server.resourcemanager.webapp")
+ .contextListenerClass(GuiceServletConfig.class)
+ .filterClass(com.google.inject.servlet.GuiceFilter.class)
+ .contextPath("jersey-guice-filter").servletPath("/").build());
+ }
+
+ @Test
+ public void testClusterScheduler() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("scheduler").accept(MediaType.APPLICATION_JSON)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyClusterScheduler(json);
+ }
+
+ @Test
+ public void testClusterSchedulerSlash() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("scheduler/").accept(MediaType.APPLICATION_JSON)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyClusterScheduler(json);
+ }
+
+ @Test
+ public void testClusterSchedulerDefault() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("scheduler").get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ verifyClusterScheduler(json);
+ }
+
+ @Test
+ public void testClusterSchedulerXML() throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("scheduler/").accept(MediaType.APPLICATION_XML)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList scheduler = dom.getElementsByTagName("scheduler");
+ assertEquals("incorrect number of elements", 1, scheduler.getLength());
+ NodeList schedulerInfo = dom.getElementsByTagName("schedulerInfo");
+ assertEquals("incorrect number of elements", 1, schedulerInfo.getLength());
+ verifyClusterSchedulerXML(schedulerInfo);
+ }
+
+ public void verifyClusterSchedulerXML(NodeList nodes) throws Exception {
+
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Element element = (Element) nodes.item(i);
+
+ verifyClusterSchedulerGeneric(
+ WebServicesTestUtils.getXmlAttrString(element, "xsi:type"),
+ WebServicesTestUtils.getXmlFloat(element, "usedCapacity"),
+ WebServicesTestUtils.getXmlFloat(element, "capacity"),
+ WebServicesTestUtils.getXmlFloat(element, "maxCapacity"),
+ WebServicesTestUtils.getXmlString(element, "queueName"));
+
+ NodeList queues = element.getElementsByTagName("queues");
+ for (int j = 0; j < queues.getLength(); j++) {
+ Element qElem = (Element) queues.item(j);
+ String qName = WebServicesTestUtils.getXmlString(qElem, "queueName");
+ String q = CapacityScheduler.ROOT + "." + qName;
+ verifySubQueueXML(qElem, q);
+ }
+ }
+ }
+
+ public void verifySubQueueXML(Element qElem, String q) throws Exception {
+
+ verifySubQueueGeneric(q,
+ WebServicesTestUtils.getXmlFloat(qElem, "usedCapacity"),
+ WebServicesTestUtils.getXmlFloat(qElem, "capacity"),
+ WebServicesTestUtils.getXmlFloat(qElem, "maxCapacity"),
+ WebServicesTestUtils.getXmlString(qElem, "queueName"),
+ WebServicesTestUtils.getXmlString(qElem, "state"));
+
+ NodeList queues = qElem.getElementsByTagName("subQueues");
+ if (queues != null) {
+ for (int j = 0; j < queues.getLength(); j++) {
+ Element subqElem = (Element) queues.item(j);
+ String qName = WebServicesTestUtils.getXmlString(subqElem, "queueName");
+ String q2 = q + "." + qName;
+ verifySubQueueXML(subqElem, q2);
+ }
+ }
+ }
+
+ private void verifyClusterScheduler(JSONObject json) throws JSONException,
+ Exception {
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject info = json.getJSONObject("scheduler");
+ assertEquals("incorrect number of elements", 1, info.length());
+ info = info.getJSONObject("schedulerInfo");
+ assertEquals("incorrect number of elements", 6, info.length());
+ verifyClusterSchedulerGeneric(info.getString("type"),
+ (float) info.getDouble("usedCapacity"),
+ (float) info.getDouble("capacity"),
+ (float) info.getDouble("maxCapacity"), info.getString("queueName"));
+
+ JSONArray arr = info.getJSONArray("queues");
+ assertEquals("incorrect number of elements", 2, arr.length());
+
+ // test subqueues
+ for (int i = 0; i < arr.length(); i++) {
+ JSONObject obj = arr.getJSONObject(i);
+ String q = CapacityScheduler.ROOT + "." + obj.getString("queueName");
+ verifySubQueue(obj, q);
+ }
+ }
+
+ private void verifyClusterSchedulerGeneric(String type, float usedCapacity,
+ float capacity, float maxCapacity, String queueName) throws Exception {
+
+ assertTrue("type doesn't match", "capacityScheduler".matches(type));
+ assertEquals("usedCapacity doesn't match", 0, usedCapacity, 1e-3f);
+ assertEquals("capacity doesn't match", 100, capacity, 1e-3f);
+ assertEquals("maxCapacity doesn't match", 100, maxCapacity, 1e-3f);
+ assertTrue("queueName doesn't match", "root".matches(queueName));
+ }
+
+ private void verifySubQueue(JSONObject info, String q) throws JSONException,
+ Exception {
+ if (info.has("subQueues")) {
+ assertEquals("incorrect number of elements", 6, info.length());
+ } else {
+ assertEquals("incorrect number of elements", 5, info.length());
+ }
+ verifySubQueueGeneric(q, (float) info.getDouble("usedCapacity"),
+ (float) info.getDouble("capacity"),
+ (float) info.getDouble("maxCapacity"), info.getString("queueName"),
+ info.getString("state"));
+
+ if (info.has("subQueues")) {
+ JSONArray arr = info.getJSONArray("subQueues");
+ // test subqueues
+ for (int i = 0; i < arr.length(); i++) {
+ JSONObject obj = arr.getJSONObject(i);
+ String q2 = q + "." + obj.getString("queueName");
+ verifySubQueue(obj, q2);
+ }
+ }
+ }
+
+ private void verifySubQueueGeneric(String q, float usedCapacity,
+ float capacity, float maxCapacity, String qname, String state)
+ throws Exception {
+ String[] qArr = q.split("\\.");
+ assertTrue("q name invalid: " + q, qArr.length > 1);
+ String qshortName = qArr[qArr.length - 1];
+
+ assertEquals("usedCapacity doesn't match", 0, usedCapacity, 1e-3f);
+ assertEquals("capacity doesn't match", csConf.getCapacity(q), capacity,
+ 1e-3f);
+ float expectCapacity = csConf.getMaximumCapacity(q);
+ if (CapacitySchedulerConfiguration.UNDEFINED == expectCapacity) {
+ expectCapacity = 100;
+ }
+ assertEquals("maxCapacity doesn't match", expectCapacity, maxCapacity,
+ 1e-3f);
+ assertTrue("queueName doesn't match, got: " + qname + " expected: " + q,
+ qshortName.matches(qname));
+ assertTrue("state doesn't match",
+ (csConf.getState(q).toString()).matches(state));
+
+ }
+}
diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesNodes.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesNodes.java
new file mode 100644
index 00000000000..2c2e9fd8cfd
--- /dev/null
+++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesNodes.java
@@ -0,0 +1,601 @@
+/**
+ * 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.webapp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+
+import javax.ws.rs.core.MediaType;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.yarn.api.records.ContainerStatus;
+import org.apache.hadoop.yarn.api.records.NodeHealthStatus;
+import org.apache.hadoop.yarn.server.resourcemanager.MockNM;
+import org.apache.hadoop.yarn.server.resourcemanager.MockRM;
+import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
+import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
+import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNode;
+import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeImpl;
+import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeState;
+import org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeStatusEvent;
+import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
+import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerNodeReport;
+import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
+import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
+import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.servlet.GuiceServletContextListener;
+import com.google.inject.servlet.ServletModule;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.ClientResponse.Status;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+
+public class TestRMWebServicesNodes extends JerseyTest {
+
+ private static MockRM rm;
+
+ private Injector injector = Guice.createInjector(new ServletModule() {
+ @Override
+ protected void configureServlets() {
+ bind(JAXBContextResolver.class);
+ bind(RMWebServices.class);
+ bind(GenericExceptionHandler.class);
+ rm = new MockRM(new Configuration());
+ bind(ResourceManager.class).toInstance(rm);
+ bind(RMContext.class).toInstance(rm.getRMContext());
+ bind(ApplicationACLsManager.class).toInstance(
+ rm.getApplicationACLsManager());
+ serve("/*").with(GuiceContainer.class);
+ }
+ });
+
+ public class GuiceServletConfig extends GuiceServletContextListener {
+
+ @Override
+ protected Injector getInjector() {
+ return injector;
+ }
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public TestRMWebServicesNodes() {
+ super(new WebAppDescriptor.Builder(
+ "org.apache.hadoop.yarn.server.resourcemanager.webapp")
+ .contextListenerClass(GuiceServletConfig.class)
+ .filterClass(com.google.inject.servlet.GuiceFilter.class)
+ .contextPath("jersey-guice-filter").servletPath("/").build());
+ }
+
+ @Test
+ public void testNodes() throws JSONException, Exception {
+ testNodesHelper("nodes", MediaType.APPLICATION_JSON);
+ }
+
+ @Test
+ public void testNodesSlash() throws JSONException, Exception {
+ testNodesHelper("nodes/", MediaType.APPLICATION_JSON);
+ }
+
+ @Test
+ public void testNodesDefault() throws JSONException, Exception {
+ testNodesHelper("nodes/", "");
+ }
+
+ @Test
+ public void testNodesQueryState() throws JSONException, Exception {
+ WebResource r = resource();
+ MockNM nm1 = rm.registerNode("h1:1234", 5120);
+ MockNM nm2 = rm.registerNode("h2:1235", 5121);
+ rm.sendNodeStarted(nm1);
+ rm.NMwaitForState(nm1.getNodeId(), RMNodeState.RUNNING);
+ rm.NMwaitForState(nm2.getNodeId(), RMNodeState.NEW);
+
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("nodes").queryParam("state", RMNodeState.RUNNING.toString())
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject nodes = json.getJSONObject("nodes");
+ assertEquals("incorrect number of elements", 1, nodes.length());
+ JSONArray nodeArray = nodes.getJSONArray("node");
+ assertEquals("incorrect number of elements", 1, nodeArray.length());
+ JSONObject info = nodeArray.getJSONObject(0);
+
+ verifyNodeInfo(info, nm1);
+ }
+
+ @Test
+ public void testNodesQueryStateNone() throws JSONException, Exception {
+ WebResource r = resource();
+ rm.registerNode("h1:1234", 5120);
+ rm.registerNode("h2:1235", 5121);
+
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("nodes")
+ .queryParam("state", RMNodeState.DECOMMISSIONED.toString())
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ assertEquals("nodes is not null", JSONObject.NULL, json.get("nodes"));
+ }
+
+ @Test
+ public void testNodesQueryStateInvalid() throws JSONException, Exception {
+ WebResource r = resource();
+ rm.registerNode("h1:1234", 5120);
+ rm.registerNode("h2:1235", 5121);
+
+ try {
+ r.path("ws").path("v1").path("cluster").path("nodes")
+ .queryParam("state", "BOGUSSTATE").accept(MediaType.APPLICATION_JSON)
+ .get(JSONObject.class);
+
+ fail("should have thrown exception querying invalid state");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+
+ assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils
+ .checkStringMatch(
+ "exception message",
+ "No enum const class org.apache.hadoop.yarn.server.resourcemanager.rmnode.RMNodeState.BOGUSSTATE",
+ message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "IllegalArgumentException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "java.lang.IllegalArgumentException", classname);
+
+ } finally {
+ rm.stop();
+ }
+ }
+
+ @Test
+ public void testNodesQueryHealthy() throws JSONException, Exception {
+ WebResource r = resource();
+ MockNM nm1 = rm.registerNode("h1:1234", 5120);
+ MockNM nm2 = rm.registerNode("h2:1235", 5121);
+ rm.sendNodeStarted(nm1);
+ rm.NMwaitForState(nm1.getNodeId(), RMNodeState.RUNNING);
+ rm.NMwaitForState(nm2.getNodeId(), RMNodeState.NEW);
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("nodes").queryParam("healthy", "true")
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject nodes = json.getJSONObject("nodes");
+ assertEquals("incorrect number of elements", 1, nodes.length());
+ JSONArray nodeArray = nodes.getJSONArray("node");
+ assertEquals("incorrect number of elements", 2, nodeArray.length());
+ }
+
+ @Test
+ public void testNodesQueryHealthyCase() throws JSONException, Exception {
+ WebResource r = resource();
+ MockNM nm1 = rm.registerNode("h1:1234", 5120);
+ MockNM nm2 = rm.registerNode("h2:1235", 5121);
+ rm.sendNodeStarted(nm1);
+ rm.NMwaitForState(nm1.getNodeId(), RMNodeState.RUNNING);
+ rm.NMwaitForState(nm2.getNodeId(), RMNodeState.NEW);
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("nodes").queryParam("healthy", "TRUe")
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject nodes = json.getJSONObject("nodes");
+ assertEquals("incorrect number of elements", 1, nodes.length());
+ JSONArray nodeArray = nodes.getJSONArray("node");
+ assertEquals("incorrect number of elements", 2, nodeArray.length());
+
+ }
+
+ @Test
+ public void testNodesQueryHealthyAndState() throws JSONException, Exception {
+ WebResource r = resource();
+ MockNM nm1 = rm.registerNode("h1:1234", 5120);
+ MockNM nm2 = rm.registerNode("h2:1235", 5121);
+ rm.sendNodeStarted(nm1);
+ rm.NMwaitForState(nm2.getNodeId(), RMNodeState.NEW);
+ rm.NMwaitForState(nm1.getNodeId(), RMNodeState.RUNNING);
+ RMNodeImpl node = (RMNodeImpl) rm.getRMContext().getRMNodes()
+ .get(nm1.getNodeId());
+ NodeHealthStatus nodeHealth = node.getNodeHealthStatus();
+ nodeHealth.setHealthReport("test health report");
+ nodeHealth.setIsNodeHealthy(false);
+ node.handle(new RMNodeStatusEvent(nm1.getNodeId(), nodeHealth,
+ new ArrayList(), null, null));
+ rm.NMwaitForState(nm1.getNodeId(), RMNodeState.UNHEALTHY);
+
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("nodes").queryParam("healthy", "true")
+ .queryParam("state", RMNodeState.RUNNING.toString())
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ assertEquals("nodes is not null", JSONObject.NULL, json.get("nodes"));
+ }
+
+ @Test
+ public void testNodesQueryHealthyFalse() throws JSONException, Exception {
+ WebResource r = resource();
+ MockNM nm1 = rm.registerNode("h1:1234", 5120);
+ MockNM nm2 = rm.registerNode("h2:1235", 5121);
+ rm.sendNodeStarted(nm1);
+ rm.NMwaitForState(nm1.getNodeId(), RMNodeState.RUNNING);
+ rm.NMwaitForState(nm2.getNodeId(), RMNodeState.NEW);
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("nodes").queryParam("healthy", "false")
+ .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ assertEquals("nodes is not null", JSONObject.NULL, json.get("nodes"));
+ }
+
+ @Test
+ public void testNodesQueryHealthyInvalid() throws JSONException, Exception {
+ WebResource r = resource();
+ rm.registerNode("h1:1234", 5120);
+ rm.registerNode("h2:1235", 5121);
+
+ try {
+ r.path("ws").path("v1").path("cluster").path("nodes")
+ .queryParam("healthy", "tr").accept(MediaType.APPLICATION_JSON)
+ .get(JSONObject.class);
+ fail("should have thrown exception querying invalid healthy string");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils
+ .checkStringMatch(
+ "exception message",
+ "java.lang.Exception: Error: You must specify either true or false to query on health",
+ message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "BadRequestException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "org.apache.hadoop.yarn.webapp.BadRequestException", classname);
+
+ } finally {
+ rm.stop();
+ }
+ }
+
+ public void testNodesHelper(String path, String media) throws JSONException,
+ Exception {
+ WebResource r = resource();
+ MockNM nm1 = rm.registerNode("h1:1234", 5120);
+ MockNM nm2 = rm.registerNode("h2:1235", 5121);
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path(path).accept(media).get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject nodes = json.getJSONObject("nodes");
+ assertEquals("incorrect number of elements", 1, nodes.length());
+ JSONArray nodeArray = nodes.getJSONArray("node");
+ assertEquals("incorrect number of elements", 2, nodeArray.length());
+ JSONObject info = nodeArray.getJSONObject(0);
+ String id = info.get("id").toString();
+
+ if (id.matches("h1:1234")) {
+ verifyNodeInfo(info, nm1);
+ verifyNodeInfo(nodeArray.getJSONObject(1), nm2);
+ } else {
+ verifyNodeInfo(info, nm2);
+ verifyNodeInfo(nodeArray.getJSONObject(1), nm1);
+ }
+ }
+
+ @Test
+ public void testSingleNode() throws JSONException, Exception {
+ rm.registerNode("h1:1234", 5120);
+ MockNM nm2 = rm.registerNode("h2:1235", 5121);
+ testSingleNodeHelper("h2:1235", nm2, MediaType.APPLICATION_JSON);
+ }
+
+ @Test
+ public void testSingleNodeSlash() throws JSONException, Exception {
+ MockNM nm1 = rm.registerNode("h1:1234", 5120);
+ rm.registerNode("h2:1235", 5121);
+ testSingleNodeHelper("h1:1234/", nm1, MediaType.APPLICATION_JSON);
+ }
+
+ @Test
+ public void testSingleNodeDefault() throws JSONException, Exception {
+ MockNM nm1 = rm.registerNode("h1:1234", 5120);
+ rm.registerNode("h2:1235", 5121);
+ testSingleNodeHelper("h1:1234/", nm1, "");
+ }
+
+ public void testSingleNodeHelper(String nodeid, MockNM nm, String media)
+ throws JSONException, Exception {
+ WebResource r = resource();
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("nodes").path(nodeid).accept(media).get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject json = response.getEntity(JSONObject.class);
+ assertEquals("incorrect number of elements", 1, json.length());
+ JSONObject info = json.getJSONObject("node");
+ verifyNodeInfo(info, nm);
+ }
+
+ @Test
+ public void testNonexistNode() throws JSONException, Exception {
+ rm.registerNode("h1:1234", 5120);
+ rm.registerNode("h2:1235", 5121);
+ WebResource r = resource();
+ try {
+ r.path("ws").path("v1").path("cluster").path("nodes")
+ .path("node_invalid:99").accept(MediaType.APPLICATION_JSON)
+ .get(JSONObject.class);
+
+ fail("should have thrown exception on non-existent nodeid");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+ assertEquals(Status.NOT_FOUND, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils
+ .checkStringMatch("exception message",
+ "java.lang.Exception: nodeId, node_invalid:99, is not found",
+ message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "NotFoundException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "org.apache.hadoop.yarn.webapp.NotFoundException", classname);
+
+ } finally {
+ rm.stop();
+ }
+ }
+
+ @Test
+ public void testInvalidNode() throws JSONException, Exception {
+ rm.registerNode("h1:1234", 5120);
+ rm.registerNode("h2:1235", 5121);
+
+ WebResource r = resource();
+ try {
+ r.path("ws").path("v1").path("cluster").path("nodes")
+ .path("node_invalid_foo").accept(MediaType.APPLICATION_JSON)
+ .get(JSONObject.class);
+
+ fail("should have thrown exception on non-existent nodeid");
+ } catch (UniformInterfaceException ue) {
+ ClientResponse response = ue.getResponse();
+
+ assertEquals(Status.BAD_REQUEST, response.getClientResponseStatus());
+ assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType());
+ JSONObject msg = response.getEntity(JSONObject.class);
+ JSONObject exception = msg.getJSONObject("RemoteException");
+ assertEquals("incorrect number of elements", 3, exception.length());
+ String message = exception.getString("message");
+ String type = exception.getString("exception");
+ String classname = exception.getString("javaClassName");
+ WebServicesTestUtils.checkStringMatch("exception message",
+ "Invalid NodeId \\[node_invalid_foo\\]. Expected host:port", message);
+ WebServicesTestUtils.checkStringMatch("exception type",
+ "IllegalArgumentException", type);
+ WebServicesTestUtils.checkStringMatch("exception classname",
+ "java.lang.IllegalArgumentException", classname);
+ } finally {
+ rm.stop();
+ }
+ }
+
+ @Test
+ public void testNodesXML() throws JSONException, Exception {
+ rm.start();
+ WebResource r = resource();
+ MockNM nm1 = rm.registerNode("h1:1234", 5120);
+ // MockNM nm2 = rm.registerNode("h2:1235", 5121);
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("nodes").accept(MediaType.APPLICATION_XML)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodesApps = dom.getElementsByTagName("nodes");
+ assertEquals("incorrect number of elements", 1, nodesApps.getLength());
+ NodeList nodes = dom.getElementsByTagName("node");
+ assertEquals("incorrect number of elements", 1, nodes.getLength());
+ verifyNodesXML(nodes, nm1);
+ rm.stop();
+ }
+
+ @Test
+ public void testSingleNodesXML() throws JSONException, Exception {
+ rm.start();
+ WebResource r = resource();
+ MockNM nm1 = rm.registerNode("h1:1234", 5120);
+ // MockNM nm2 = rm.registerNode("h2:1235", 5121);
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("nodes").path("h1:1234").accept(MediaType.APPLICATION_XML)
+ .get(ClientResponse.class);
+
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodes = dom.getElementsByTagName("node");
+ assertEquals("incorrect number of elements", 1, nodes.getLength());
+ verifyNodesXML(nodes, nm1);
+ rm.stop();
+ }
+
+ @Test
+ public void testNodes2XML() throws JSONException, Exception {
+ rm.start();
+ WebResource r = resource();
+ rm.registerNode("h1:1234", 5120);
+ rm.registerNode("h2:1235", 5121);
+ ClientResponse response = r.path("ws").path("v1").path("cluster")
+ .path("nodes").accept(MediaType.APPLICATION_XML)
+ .get(ClientResponse.class);
+ assertEquals(MediaType.APPLICATION_XML_TYPE, response.getType());
+ String xml = response.getEntity(String.class);
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource();
+ is.setCharacterStream(new StringReader(xml));
+ Document dom = db.parse(is);
+ NodeList nodesApps = dom.getElementsByTagName("nodes");
+ assertEquals("incorrect number of elements", 1, nodesApps.getLength());
+ NodeList nodes = dom.getElementsByTagName("node");
+ assertEquals("incorrect number of elements", 2, nodes.getLength());
+ rm.stop();
+ }
+
+ public void verifyNodesXML(NodeList nodes, MockNM nm) throws JSONException,
+ Exception {
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Element element = (Element) nodes.item(i);
+ verifyNodeInfoGeneric(nm,
+ WebServicesTestUtils.getXmlString(element, "state"),
+ WebServicesTestUtils.getXmlString(element, "rack"),
+ WebServicesTestUtils.getXmlString(element, "healthStatus"),
+ WebServicesTestUtils.getXmlString(element, "id"),
+ WebServicesTestUtils.getXmlString(element, "nodeHostName"),
+ WebServicesTestUtils.getXmlString(element, "nodeHTTPAddress"),
+ WebServicesTestUtils.getXmlLong(element, "lastHealthUpdate"),
+ WebServicesTestUtils.getXmlString(element, "healthReport"),
+ WebServicesTestUtils.getXmlInt(element, "numContainers"),
+ WebServicesTestUtils.getXmlLong(element, "usedMemoryMB"),
+ WebServicesTestUtils.getXmlLong(element, "availMemoryMB"));
+ }
+ }
+
+ public void verifyNodeInfo(JSONObject nodeInfo, MockNM nm)
+ throws JSONException, Exception {
+ assertEquals("incorrect number of elements", 11, nodeInfo.length());
+
+ verifyNodeInfoGeneric(nm, nodeInfo.getString("state"),
+ nodeInfo.getString("rack"), nodeInfo.getString("healthStatus"),
+ nodeInfo.getString("id"), nodeInfo.getString("nodeHostName"),
+ nodeInfo.getString("nodeHTTPAddress"),
+ nodeInfo.getLong("lastHealthUpdate"),
+ nodeInfo.getString("healthReport"), nodeInfo.getInt("numContainers"),
+ nodeInfo.getLong("usedMemoryMB"), nodeInfo.getLong("availMemoryMB"));
+
+ }
+
+ public void verifyNodeInfoGeneric(MockNM nm, String state, String rack,
+ String healthStatus, String id, String nodeHostName,
+ String nodeHTTPAddress, long lastHealthUpdate, String healthReport,
+ int numContainers, long usedMemoryMB, long availMemoryMB)
+ throws JSONException, Exception {
+
+ RMNode node = rm.getRMContext().getRMNodes().get(nm.getNodeId());
+ NodeHealthStatus health = node.getNodeHealthStatus();
+ ResourceScheduler sched = rm.getResourceScheduler();
+ SchedulerNodeReport report = sched.getNodeReport(nm.getNodeId());
+
+ WebServicesTestUtils.checkStringMatch("state", node.getState().toString(),
+ state);
+ WebServicesTestUtils.checkStringMatch("rack", node.getRackName(), rack);
+ WebServicesTestUtils.checkStringMatch("healthStatus", "Healthy",
+ healthStatus);
+ WebServicesTestUtils.checkStringMatch("id", nm.getNodeId().toString(), id);
+ WebServicesTestUtils.checkStringMatch("nodeHostName", nm.getNodeId()
+ .getHost(), nodeHostName);
+ WebServicesTestUtils.checkStringMatch("healthReport",
+ String.valueOf(health.getHealthReport()), healthReport);
+ String expectedHttpAddress = nm.getNodeId().getHost() + ":"
+ + nm.getHttpPort();
+ WebServicesTestUtils.checkStringMatch("nodeHTTPAddress",
+ expectedHttpAddress, nodeHTTPAddress);
+
+ long expectedHealthUpdate = health.getLastHealthReportTime();
+ assertEquals("lastHealthUpdate doesn't match, got: " + lastHealthUpdate
+ + " expected: " + expectedHealthUpdate, expectedHealthUpdate,
+ lastHealthUpdate);
+
+ if (report != null) {
+ assertEquals("numContainers doesn't match: " + numContainers,
+ report.getNumContainers(), numContainers);
+ assertEquals("usedMemoryMB doesn't match: " + usedMemoryMB, report
+ .getUsedResource().getMemory(), usedMemoryMB);
+ assertEquals("availMemoryMB doesn't match: " + availMemoryMB, report
+ .getAvailableResource().getMemory(), availMemoryMB);
+ }
+ }
+
+}