Merge -c 1225463 from trunk to branch-0.23 to fix MAPREDUCE-3547.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-0.23@1225466 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
fc62f00ffc
commit
c0e9c8bf5e
|
@ -87,6 +87,9 @@ Release 0.23.1 - Unreleased
|
||||||
MAPREDUCE-3391. Making a trivial change to correct a log message in
|
MAPREDUCE-3391. Making a trivial change to correct a log message in
|
||||||
DistributedShell app's AM. (Subroto Sanyal via vinodkv)
|
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
|
OPTIMIZATIONS
|
||||||
|
|
||||||
MAPREDUCE-3567. Extraneous JobConf objects in AM heap. (Vinod Kumar
|
MAPREDUCE-3567. Extraneous JobConf objects in AM heap. (Vinod Kumar
|
||||||
|
|
|
@ -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 <key></key>
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.ContainersInfo;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.webapp.dao.NodeInfo;
|
import org.apache.hadoop.yarn.server.nodemanager.webapp.dao.NodeInfo;
|
||||||
import org.apache.hadoop.yarn.util.ConverterUtils;
|
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.NotFoundException;
|
||||||
import org.apache.hadoop.yarn.webapp.WebApp;
|
import org.apache.hadoop.yarn.webapp.WebApp;
|
||||||
|
|
||||||
|
@ -92,12 +93,16 @@ public class NMWebServices {
|
||||||
|
|
||||||
AppInfo appInfo = new AppInfo(entry.getValue());
|
AppInfo appInfo = new AppInfo(entry.getValue());
|
||||||
if (stateQuery != null && !stateQuery.isEmpty()) {
|
if (stateQuery != null && !stateQuery.isEmpty()) {
|
||||||
ApplicationState state = ApplicationState.valueOf(stateQuery);
|
ApplicationState.valueOf(stateQuery);
|
||||||
if (!appInfo.getState().equalsIgnoreCase(stateQuery)) {
|
if (!appInfo.getState().equalsIgnoreCase(stateQuery)) {
|
||||||
continue;
|
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)) {
|
if (!appInfo.getUser().toString().equals(userQuery)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -146,11 +151,12 @@ public class NMWebServices {
|
||||||
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||||
public ContainerInfo getNodeContainer(@PathParam("containerid") String id) {
|
public ContainerInfo getNodeContainer(@PathParam("containerid") String id) {
|
||||||
ContainerId containerId = null;
|
ContainerId containerId = null;
|
||||||
|
try {
|
||||||
containerId = ConverterUtils.toContainerId(id);
|
containerId = ConverterUtils.toContainerId(id);
|
||||||
if (containerId == null) {
|
} catch (Exception e) {
|
||||||
throw new NotFoundException("container with id, " + id
|
throw new BadRequestException("invalid container id, " + id);
|
||||||
+ ", is empty or null");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Container container = nmContext.getContainers().get(containerId);
|
Container container = nmContext.getContainers().get(containerId);
|
||||||
if (container == null) {
|
if (container == null) {
|
||||||
throw new NotFoundException("container with id, " + id + ", not found");
|
throw new NotFoundException("container with id, " + id + ", not found");
|
||||||
|
|
|
@ -27,6 +27,7 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||||
import javax.xml.bind.annotation.XmlTransient;
|
import javax.xml.bind.annotation.XmlTransient;
|
||||||
|
|
||||||
import org.apache.hadoop.yarn.api.records.ContainerStatus;
|
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.conf.YarnConfiguration;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.Context;
|
import org.apache.hadoop.yarn.server.nodemanager.Context;
|
||||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
|
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,
|
public ContainerInfo(final Context nmContext, final Container container,
|
||||||
final String requestUri, final String pathPrefix) {
|
String requestUri, String pathPrefix) {
|
||||||
|
|
||||||
this.id = container.getContainerID().toString();
|
this.id = container.getContainerID().toString();
|
||||||
this.nodeId = nmContext.getNodeId().toString();
|
this.nodeId = nmContext.getNodeId().toString();
|
||||||
|
@ -71,10 +72,19 @@ public class ContainerInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.user = container.getUser();
|
this.user = container.getUser();
|
||||||
this.totalMemoryNeededMB = container.getLaunchContext().getResource()
|
Resource res = container.getLaunchContext().getResource();
|
||||||
.getMemory();
|
if (res != null) {
|
||||||
|
this.totalMemoryNeededMB = res.getMemory();
|
||||||
|
}
|
||||||
this.containerLogsShortLink = ujoin("containerlogs", this.id,
|
this.containerLogsShortLink = ujoin("containerlogs", this.id,
|
||||||
container.getUser());
|
container.getUser());
|
||||||
|
|
||||||
|
if (requestUri == null) {
|
||||||
|
requestUri = "";
|
||||||
|
}
|
||||||
|
if (pathPrefix == null) {
|
||||||
|
pathPrefix = "";
|
||||||
|
}
|
||||||
this.containerLogsLink = join(requestUri, pathPrefix,
|
this.containerLogsLink = join(requestUri, pathPrefix,
|
||||||
this.containerLogsShortLink);
|
this.containerLogsShortLink);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<ContainerId, Container> containers = new HashMap<ContainerId, Container>();
|
||||||
|
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<ContainerId, Container> getContainers() {
|
||||||
|
return containers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApplicationId getAppId() {
|
||||||
|
return appId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApplicationState getApplicationState() {
|
||||||
|
return appState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handle(ApplicationEvent event) {}
|
||||||
|
|
||||||
|
}
|
|
@ -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<Path, String> resource = new HashMap<Path, String>();
|
||||||
|
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<Path, String> 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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<String, String> 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<String, String> hash = new HashMap<String, String>();
|
||||||
|
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<String, String> hash = addAppContainers(app);
|
||||||
|
Application app2 = new MockApp(2);
|
||||||
|
nmContext.getApplications().put(app2.getAppId(), app2);
|
||||||
|
HashMap<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<String, String> 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<String, String> hash = new HashMap<String, String>();
|
||||||
|
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<String, String> 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<String, String> 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||||
import javax.xml.bind.annotation.XmlTransient;
|
import javax.xml.bind.annotation.XmlTransient;
|
||||||
import javax.xml.bind.annotation.XmlType;
|
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.CSQueue;
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.ParentQueue;
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.ParentQueue;
|
||||||
|
|
||||||
|
@ -90,7 +91,7 @@ public class CapacitySchedulerInfo extends SchedulerInfo {
|
||||||
if (max < EPSILON || max > 1f)
|
if (max < EPSILON || max > 1f)
|
||||||
max = 1f;
|
max = 1f;
|
||||||
float maxCapacity = max * 100;
|
float maxCapacity = max * 100;
|
||||||
String state = queue.getState().toString();
|
QueueState state = queue.getState();
|
||||||
CapacitySchedulerQueueInfo info = new CapacitySchedulerQueueInfo(
|
CapacitySchedulerQueueInfo info = new CapacitySchedulerQueueInfo(
|
||||||
capacity, usedCapacity, maxCapacity, queueName, state, queuePath);
|
capacity, usedCapacity, maxCapacity, queueName, state, queuePath);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
import javax.xml.bind.annotation.XmlRootElement;
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
import javax.xml.bind.annotation.XmlTransient;
|
import javax.xml.bind.annotation.XmlTransient;
|
||||||
|
|
||||||
|
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.CSQueue;
|
||||||
|
|
||||||
@XmlRootElement
|
@XmlRootElement
|
||||||
|
@ -43,14 +44,14 @@ public class CapacitySchedulerQueueInfo {
|
||||||
protected float usedCapacity;
|
protected float usedCapacity;
|
||||||
protected float maxCapacity;
|
protected float maxCapacity;
|
||||||
protected String queueName;
|
protected String queueName;
|
||||||
protected String state;
|
protected QueueState state;
|
||||||
protected ArrayList<CapacitySchedulerQueueInfo> subQueues;
|
protected ArrayList<CapacitySchedulerQueueInfo> subQueues;
|
||||||
|
|
||||||
CapacitySchedulerQueueInfo() {
|
CapacitySchedulerQueueInfo() {
|
||||||
};
|
};
|
||||||
|
|
||||||
CapacitySchedulerQueueInfo(float cap, float used, float max, String name,
|
CapacitySchedulerQueueInfo(float cap, float used, float max, String name,
|
||||||
String state, String path) {
|
QueueState state, String path) {
|
||||||
this.capacity = cap;
|
this.capacity = cap;
|
||||||
this.usedCapacity = used;
|
this.usedCapacity = used;
|
||||||
this.maxCapacity = max;
|
this.maxCapacity = max;
|
||||||
|
@ -84,7 +85,7 @@ public class CapacitySchedulerQueueInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getQueueState() {
|
public String getQueueState() {
|
||||||
return this.state;
|
return this.state.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getQueuePath() {
|
public String getQueuePath() {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
import org.apache.hadoop.util.VersionInfo;
|
import org.apache.hadoop.util.VersionInfo;
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
|
import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
|
||||||
|
import org.apache.hadoop.yarn.service.Service.STATE;
|
||||||
import org.apache.hadoop.yarn.util.YarnVersionInfo;
|
import org.apache.hadoop.yarn.util.YarnVersionInfo;
|
||||||
|
|
||||||
@XmlRootElement
|
@XmlRootElement
|
||||||
|
@ -31,7 +32,7 @@ public class ClusterInfo {
|
||||||
|
|
||||||
protected long id;
|
protected long id;
|
||||||
protected long startedOn;
|
protected long startedOn;
|
||||||
protected String state;
|
protected STATE state;
|
||||||
protected String resourceManagerVersion;
|
protected String resourceManagerVersion;
|
||||||
protected String resourceManagerBuildVersion;
|
protected String resourceManagerBuildVersion;
|
||||||
protected String resourceManagerVersionBuiltOn;
|
protected String resourceManagerVersionBuiltOn;
|
||||||
|
@ -46,7 +47,7 @@ public class ClusterInfo {
|
||||||
long ts = ResourceManager.clusterTimeStamp;
|
long ts = ResourceManager.clusterTimeStamp;
|
||||||
|
|
||||||
this.id = ts;
|
this.id = ts;
|
||||||
this.state = rm.getServiceState().toString();
|
this.state = rm.getServiceState();
|
||||||
this.startedOn = ts;
|
this.startedOn = ts;
|
||||||
this.resourceManagerVersion = YarnVersionInfo.getVersion();
|
this.resourceManagerVersion = YarnVersionInfo.getVersion();
|
||||||
this.resourceManagerBuildVersion = YarnVersionInfo.getBuildVersion();
|
this.resourceManagerBuildVersion = YarnVersionInfo.getBuildVersion();
|
||||||
|
@ -57,7 +58,7 @@ public class ClusterInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getState() {
|
public String getState() {
|
||||||
return this.state;
|
return this.state.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRMVersion() {
|
public String getRMVersion() {
|
||||||
|
|
|
@ -87,8 +87,12 @@ public class MockRM extends ResourceManager {
|
||||||
.newRecord(GetNewApplicationRequest.class));
|
.newRecord(GetNewApplicationRequest.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
// client
|
|
||||||
public RMApp submitApp(int masterMemory) throws Exception {
|
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();
|
ClientRMProtocol client = getClientRMService();
|
||||||
GetNewApplicationResponse resp = client.getNewApplication(Records
|
GetNewApplicationResponse resp = client.getNewApplication(Records
|
||||||
.newRecord(GetNewApplicationRequest.class));
|
.newRecord(GetNewApplicationRequest.class));
|
||||||
|
@ -99,8 +103,8 @@ public class MockRM extends ResourceManager {
|
||||||
ApplicationSubmissionContext sub = Records
|
ApplicationSubmissionContext sub = Records
|
||||||
.newRecord(ApplicationSubmissionContext.class);
|
.newRecord(ApplicationSubmissionContext.class);
|
||||||
sub.setApplicationId(appId);
|
sub.setApplicationId(appId);
|
||||||
sub.setApplicationName("");
|
sub.setApplicationName(name);
|
||||||
sub.setUser("");
|
sub.setUser(user);
|
||||||
ContainerLaunchContext clc = Records
|
ContainerLaunchContext clc = Records
|
||||||
.newRecord(ContainerLaunchContext.class);
|
.newRecord(ContainerLaunchContext.class);
|
||||||
Resource capability = Records.newRecord(Resource.class);
|
Resource capability = Records.newRecord(Resource.class);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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://"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<ContainerStatus>(), 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue