|
@@ -25,28 +25,37 @@ import static org.junit.Assert.fail;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.when;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
|
|
|
|
+import java.io.IOException;
|
|
import java.io.StringReader;
|
|
import java.io.StringReader;
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
import java.util.EnumSet;
|
|
import java.util.EnumSet;
|
|
|
|
+import java.util.Enumeration;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
+import java.util.Properties;
|
|
import java.util.Set;
|
|
import java.util.Set;
|
|
import java.util.HashSet;
|
|
import java.util.HashSet;
|
|
import java.util.TreeMap;
|
|
import java.util.TreeMap;
|
|
import java.util.Iterator;
|
|
import java.util.Iterator;
|
|
|
|
|
|
|
|
+import javax.servlet.FilterConfig;
|
|
|
|
+import javax.servlet.ServletException;
|
|
import javax.ws.rs.core.MediaType;
|
|
import javax.ws.rs.core.MediaType;
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
|
|
|
|
-import org.apache.hadoop.conf.Configuration;
|
|
|
|
import org.apache.hadoop.http.JettyUtils;
|
|
import org.apache.hadoop.http.JettyUtils;
|
|
|
|
+import org.apache.hadoop.security.UserGroupInformation;
|
|
|
|
+import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
|
|
|
|
+import org.apache.hadoop.security.authentication.server.PseudoAuthenticationHandler;
|
|
import org.apache.hadoop.yarn.api.records.ContainerStatus;
|
|
import org.apache.hadoop.yarn.api.records.ContainerStatus;
|
|
import org.apache.hadoop.yarn.api.records.NodeAttribute;
|
|
import org.apache.hadoop.yarn.api.records.NodeAttribute;
|
|
import org.apache.hadoop.yarn.api.records.NodeAttributeType;
|
|
import org.apache.hadoop.yarn.api.records.NodeAttributeType;
|
|
import org.apache.hadoop.yarn.api.records.NodeId;
|
|
import org.apache.hadoop.yarn.api.records.NodeId;
|
|
import org.apache.hadoop.yarn.api.records.NodeState;
|
|
import org.apache.hadoop.yarn.api.records.NodeState;
|
|
import org.apache.hadoop.yarn.api.records.Resource;
|
|
import org.apache.hadoop.yarn.api.records.Resource;
|
|
|
|
+import org.apache.hadoop.yarn.api.records.ResourceOption;
|
|
import org.apache.hadoop.yarn.api.records.ResourceUtilization;
|
|
import org.apache.hadoop.yarn.api.records.ResourceUtilization;
|
|
|
|
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
|
import org.apache.hadoop.yarn.server.utils.BuilderUtils;
|
|
import org.apache.hadoop.yarn.server.utils.BuilderUtils;
|
|
import org.apache.hadoop.yarn.server.api.records.NodeHealthStatus;
|
|
import org.apache.hadoop.yarn.server.api.records.NodeHealthStatus;
|
|
import org.apache.hadoop.yarn.server.api.records.NodeStatus;
|
|
import org.apache.hadoop.yarn.server.api.records.NodeStatus;
|
|
@@ -66,6 +75,9 @@ 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.ResourceScheduler;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerNodeReport;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerNodeReport;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.constraint.AllocationTagsManager;
|
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.constraint.AllocationTagsManager;
|
|
|
|
+import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.NodeInfo;
|
|
|
|
+import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ResourceInfo;
|
|
|
|
+import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ResourceOptionInfo;
|
|
import org.apache.hadoop.yarn.util.Records;
|
|
import org.apache.hadoop.yarn.util.Records;
|
|
import org.apache.hadoop.yarn.util.RackResolver;
|
|
import org.apache.hadoop.yarn.util.RackResolver;
|
|
import org.apache.hadoop.yarn.util.YarnVersionInfo;
|
|
import org.apache.hadoop.yarn.util.YarnVersionInfo;
|
|
@@ -85,6 +97,7 @@ import org.xml.sax.InputSource;
|
|
|
|
|
|
import com.google.common.base.Joiner;
|
|
import com.google.common.base.Joiner;
|
|
import com.google.inject.Guice;
|
|
import com.google.inject.Guice;
|
|
|
|
+import com.google.inject.Singleton;
|
|
import com.google.inject.servlet.ServletModule;
|
|
import com.google.inject.servlet.ServletModule;
|
|
import com.sun.jersey.api.client.ClientResponse;
|
|
import com.sun.jersey.api.client.ClientResponse;
|
|
import com.sun.jersey.api.client.ClientResponse.Status;
|
|
import com.sun.jersey.api.client.ClientResponse.Status;
|
|
@@ -96,22 +109,58 @@ import com.sun.jersey.test.framework.WebAppDescriptor;
|
|
public class TestRMWebServicesNodes extends JerseyTestBase {
|
|
public class TestRMWebServicesNodes extends JerseyTestBase {
|
|
|
|
|
|
private static MockRM rm;
|
|
private static MockRM rm;
|
|
|
|
+ private static YarnConfiguration conf;
|
|
|
|
+
|
|
|
|
+ private static String userName;
|
|
|
|
|
|
private static class WebServletModule extends ServletModule {
|
|
private static class WebServletModule extends ServletModule {
|
|
@Override
|
|
@Override
|
|
protected void configureServlets() {
|
|
protected void configureServlets() {
|
|
bind(JAXBContextResolver.class);
|
|
bind(JAXBContextResolver.class);
|
|
|
|
+ try {
|
|
|
|
+ userName = UserGroupInformation.getCurrentUser().getShortUserName();
|
|
|
|
+ } catch (IOException ioe) {
|
|
|
|
+ throw new RuntimeException("Unable to get current user name "
|
|
|
|
+ + ioe.getMessage(), ioe);
|
|
|
|
+ }
|
|
|
|
+ conf = new YarnConfiguration();
|
|
|
|
+ conf.set(YarnConfiguration.YARN_ADMIN_ACL, userName);
|
|
bind(RMWebServices.class);
|
|
bind(RMWebServices.class);
|
|
bind(GenericExceptionHandler.class);
|
|
bind(GenericExceptionHandler.class);
|
|
- rm = new MockRM(new Configuration());
|
|
|
|
|
|
+ rm = new MockRM(conf);
|
|
rm.getRMContext().getContainerTokenSecretManager().rollMasterKey();
|
|
rm.getRMContext().getContainerTokenSecretManager().rollMasterKey();
|
|
rm.getRMContext().getNMTokenSecretManager().rollMasterKey();
|
|
rm.getRMContext().getNMTokenSecretManager().rollMasterKey();
|
|
rm.disableDrainEventsImplicitly();
|
|
rm.disableDrainEventsImplicitly();
|
|
bind(ResourceManager.class).toInstance(rm);
|
|
bind(ResourceManager.class).toInstance(rm);
|
|
|
|
+ filter("/*").through(TestRMCustomAuthFilter.class);
|
|
serve("/*").with(GuiceContainer.class);
|
|
serve("/*").with(GuiceContainer.class);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Custom filter to be able to test auth methods and let the other ones go.
|
|
|
|
+ */
|
|
|
|
+ @Singleton
|
|
|
|
+ public static class TestRMCustomAuthFilter extends AuthenticationFilter {
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ protected Properties getConfiguration(String configPrefix,
|
|
|
|
+ FilterConfig filterConfig) throws ServletException {
|
|
|
|
+ Properties props = new Properties();
|
|
|
|
+ Enumeration<?> names = filterConfig.getInitParameterNames();
|
|
|
|
+ while (names.hasMoreElements()) {
|
|
|
|
+ String name = (String) names.nextElement();
|
|
|
|
+ if (name.startsWith(configPrefix)) {
|
|
|
|
+ String value = filterConfig.getInitParameter(name);
|
|
|
|
+ props.put(name.substring(configPrefix.length()), value);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ props.put(AuthenticationFilter.AUTH_TYPE, "simple");
|
|
|
|
+ props.put(PseudoAuthenticationHandler.ANONYMOUS_ALLOWED, "true");
|
|
|
|
+ return props;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
static {
|
|
static {
|
|
GuiceServletConfig.setInjector(
|
|
GuiceServletConfig.setInjector(
|
|
Guice.createInjector(new WebServletModule()));
|
|
Guice.createInjector(new WebServletModule()));
|
|
@@ -541,7 +590,7 @@ public class TestRMWebServicesNodes extends JerseyTestBase {
|
|
}
|
|
}
|
|
|
|
|
|
private void verifyNonexistNodeException(String message, String type, String classname) {
|
|
private void verifyNonexistNodeException(String message, String type, String classname) {
|
|
- assertTrue("exception message incorrect",
|
|
|
|
|
|
+ assertTrue("exception message incorrect: " + message,
|
|
"java.lang.Exception: nodeId, node_invalid:99, is not found"
|
|
"java.lang.Exception: nodeId, node_invalid:99, is not found"
|
|
.matches(message));
|
|
.matches(message));
|
|
assertTrue("exception type incorrect", "NotFoundException".matches(type));
|
|
assertTrue("exception type incorrect", "NotFoundException".matches(type));
|
|
@@ -714,6 +763,64 @@ public class TestRMWebServicesNodes extends JerseyTestBase {
|
|
verifyNodeInfo(info, rmnode1);
|
|
verifyNodeInfo(info, rmnode1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Test
|
|
|
|
+ public void testUpdateNodeResource() throws Exception {
|
|
|
|
+ WebResource r = resource().path(RMWSConsts.RM_WEB_SERVICE_PATH);
|
|
|
|
+
|
|
|
|
+ r = r.queryParam("user.name", userName);
|
|
|
|
+ RMNode rmnode = getRunningRMNode("h1", 1234, 5120);
|
|
|
|
+ String rmnodeId = rmnode.getNodeID().toString();
|
|
|
|
+ assertEquals("h1:1234", rmnodeId);
|
|
|
|
+
|
|
|
|
+ // assert memory and default vcores
|
|
|
|
+ ClientResponse response = r.path(RMWSConsts.NODES).path(rmnodeId)
|
|
|
|
+ .accept(MediaType.APPLICATION_XML)
|
|
|
|
+ .get(ClientResponse.class);
|
|
|
|
+ NodeInfo nodeInfo0 = response.getEntity(NodeInfo.class);
|
|
|
|
+ ResourceInfo nodeResource0 = nodeInfo0.getTotalResource();
|
|
|
|
+ assertEquals(5120, nodeResource0.getMemorySize());
|
|
|
|
+ assertEquals(4, nodeResource0.getvCores());
|
|
|
|
+
|
|
|
|
+ // the RM needs to be running to process the resource update
|
|
|
|
+ rm.start();
|
|
|
|
+
|
|
|
|
+ // update memory to 8192MB and 5 cores
|
|
|
|
+ Resource resource = Resource.newInstance(8192, 5);
|
|
|
|
+ ResourceOptionInfo resourceOption = new ResourceOptionInfo(
|
|
|
|
+ ResourceOption.newInstance(resource, 1000));
|
|
|
|
+ response = r.path(RMWSConsts.NODES).path(rmnodeId).path("resource")
|
|
|
|
+ .entity(resourceOption, MediaType.APPLICATION_XML_TYPE)
|
|
|
|
+ .accept(MediaType.APPLICATION_XML)
|
|
|
|
+ .post(ClientResponse.class);
|
|
|
|
+ assertResponseStatusCode(Status.OK, response.getStatusInfo());
|
|
|
|
+ ResourceInfo updatedResource = response.getEntity(ResourceInfo.class);
|
|
|
|
+ assertEquals(8192, updatedResource.getMemorySize());
|
|
|
|
+ assertEquals(5, updatedResource.getvCores());
|
|
|
|
+
|
|
|
|
+ // assert updated memory and cores
|
|
|
|
+ response = r.path(RMWSConsts.NODES).path(rmnodeId)
|
|
|
|
+ .accept(MediaType.APPLICATION_XML)
|
|
|
|
+ .get(ClientResponse.class);
|
|
|
|
+ NodeInfo nodeInfo1 = response.getEntity(NodeInfo.class);
|
|
|
|
+ ResourceInfo nodeResource1 = nodeInfo1.getTotalResource();
|
|
|
|
+ assertEquals(8192, nodeResource1.getMemorySize());
|
|
|
|
+ assertEquals(5, nodeResource1.getvCores());
|
|
|
|
+
|
|
|
|
+ // test non existing node
|
|
|
|
+ response = r.path(RMWSConsts.NODES).path("badnode").path("resource")
|
|
|
|
+ .entity(resourceOption, MediaType.APPLICATION_XML_TYPE)
|
|
|
|
+ .accept(MediaType.APPLICATION_JSON)
|
|
|
|
+ .post(ClientResponse.class);
|
|
|
|
+ assertResponseStatusCode(Status.BAD_REQUEST, response.getStatusInfo());
|
|
|
|
+ JSONObject json = response.getEntity(JSONObject.class);
|
|
|
|
+ JSONObject exception = json.getJSONObject("RemoteException");
|
|
|
|
+ assertEquals("IllegalArgumentException", exception.getString("exception"));
|
|
|
|
+ String msg = exception.getString("message");
|
|
|
|
+ assertTrue("Wrong message: " + msg, msg.startsWith("Invalid NodeId"));
|
|
|
|
+
|
|
|
|
+ rm.stop();
|
|
|
|
+ }
|
|
|
|
+
|
|
public void verifyNodesXML(NodeList nodes, RMNode nm)
|
|
public void verifyNodesXML(NodeList nodes, RMNode nm)
|
|
throws JSONException,
|
|
throws JSONException,
|
|
Exception {
|
|
Exception {
|
|
@@ -750,7 +857,7 @@ public class TestRMWebServicesNodes extends JerseyTestBase {
|
|
|
|
|
|
public void verifyNodeInfo(JSONObject nodeInfo, RMNode nm)
|
|
public void verifyNodeInfo(JSONObject nodeInfo, RMNode nm)
|
|
throws JSONException, Exception {
|
|
throws JSONException, Exception {
|
|
- assertEquals("incorrect number of elements", 20, nodeInfo.length());
|
|
|
|
|
|
+ assertEquals("incorrect number of elements", 21, nodeInfo.length());
|
|
|
|
|
|
JSONObject resourceInfo = nodeInfo.getJSONObject("resourceUtilization");
|
|
JSONObject resourceInfo = nodeInfo.getJSONObject("resourceUtilization");
|
|
verifyNodeInfoGeneric(nm, nodeInfo.getString("state"),
|
|
verifyNodeInfoGeneric(nm, nodeInfo.getString("state"),
|