Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
TestRequestPoolService.java
Go to the documentation of this file.
1 // Copyright 2014 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.cloudera.impala.util;
16 
17 import java.io.File;
18 import java.io.IOException;
19 import java.lang.reflect.Field;
20 import java.net.URISyntaxException;
21 
22 import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.AllocationFileLoaderService;
23 import org.junit.After;
24 import org.junit.Assert;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.junit.rules.TemporaryFolder;
28 
30 import com.cloudera.impala.thrift.TErrorCode;
31 import com.cloudera.impala.thrift.TPoolConfigResult;
32 import com.cloudera.impala.thrift.TResolveRequestPoolParams;
33 import com.cloudera.impala.thrift.TResolveRequestPoolResult;
34 import com.google.common.collect.Iterables;
35 import com.google.common.io.Files;
36 
45 public class TestRequestPoolService {
46  // Pool definitions and includes memory resource limits, copied to a temporary file
47  private static final String ALLOCATION_FILE = "fair-scheduler-test.xml";
48 
49  // A second allocation file which overwrites the temporary file to check for changes.
50  private static final String ALLOCATION_FILE_MODIFIED = "fair-scheduler-test2.xml";
51  private static final String ALLOCATION_FILE_EMPTY = "fair-scheduler-empty.xml";
52  private static final String ALLOCATION_FILE_GROUP_RULE = "fair-scheduler-group-rule.xml";
53 
54  // Contains per-pool configurations for maximum number of running queries and queued
55  // requests.
56  private static final String LLAMA_CONFIG_FILE = "llama-site-test.xml";
57 
58  // A second Llama config which overwrites the temporary file to check for changes.
59  private static final String LLAMA_CONFIG_FILE_MODIFIED = "llama-site-test2.xml";
60  private static final String LLAMA_CONFIG_FILE_EMPTY = "llama-site-empty.xml";
61 
62  // Set the file check interval to something short so we don't have to wait long after
63  // changing the file.
64  private static final long CHECK_INTERVAL_MS = 100L;
65 
66  // Temp folder where the config files are copied so we can modify them in place.
67  // The JUnit @Rule creates and removes the temp folder between every test.
68  @Rule
69  public TemporaryFolder tempFolder = new TemporaryFolder();
70 
72  private File allocationConfFile_;
73  private File llamaConfFile_;
74 
82  void createPoolService(String allocationFile, String llamaConfFile)
83  throws Exception {
84  allocationConfFile_ = tempFolder.newFile("fair-scheduler-temp-file.xml");
85  Files.copy(getClasspathFile(allocationFile), allocationConfFile_);
86 
87  String llamaConfPath = null;
88  if (llamaConfFile != null) {
89  llamaConfFile_ = tempFolder.newFile("llama-conf-temp-file.xml");
90  Files.copy(getClasspathFile(llamaConfFile), llamaConfFile_);
91  llamaConfPath = llamaConfFile_.getAbsolutePath();
92  }
93  poolService_ = new RequestPoolService(allocationConfFile_.getAbsolutePath(),
94  llamaConfPath);
95 
96  // Lower the wait times on the AllocationFileLoaderService and RequestPoolService so
97  // the test doesn't have to wait very long to test that file changes are reloaded.
98  Field f = AllocationFileLoaderService.class.getDeclaredField("reloadIntervalMs");
99  f.setAccessible(true);
100  f.set(poolService_.allocLoader_, CHECK_INTERVAL_MS);
101  if (llamaConfFile != null) {
102  poolService_.llamaConfWatcher_.setCheckIntervalMs(CHECK_INTERVAL_MS);
103  }
104  poolService_.start();
105  }
106 
107  @After
108  public void cleanUp() throws Exception {
109  if (poolService_ != null) poolService_.stop();
110  }
111 
115  private File getClasspathFile(String filename) throws URISyntaxException {
116  return new File(getClass().getClassLoader().getResource(filename).toURI());
117  }
118 
119  @Test
120  public void testPoolResolution() throws Exception {
122  Assert.assertEquals("root.queueA", poolService_.assignToPool("root.queueA", "userA"));
123  Assert.assertNull(poolService_.assignToPool("queueC", "userA"));
124  }
125 
126  @Test
127  public void testResolvePrincipalName() throws Exception {
128  // Tests that we can resolve user names that are Kerberos principals/LDAP users.
130  TResolveRequestPoolResult result = poolService_.resolveRequestPool(
131  new TResolveRequestPoolParams("userA@abc.com", "root.queueA"));
132  Assert.assertEquals(TErrorCode.OK, result.getStatus().getStatus_code());
133  Assert.assertEquals("root.queueA", result.getResolved_pool());
134 
135  result = poolService_.resolveRequestPool(
136  new TResolveRequestPoolParams("userA/a.qualified.domain@abc.com", "root.queueA"));
137  Assert.assertEquals(TErrorCode.OK, result.getStatus().getStatus_code());
138  Assert.assertEquals("root.queueA", result.getResolved_pool());
139  }
140 
141  @Test
142  public void testUserNoGroupsError() throws Exception {
143  // Test fix for IMPALA-922: "Return helpful errors with Yarn group rules"
145  TResolveRequestPoolResult result = poolService_.resolveRequestPool(
146  new TResolveRequestPoolParams("userA", "root.NOT_A_POOL"));
147  Assert.assertEquals(false, result.isSetResolved_pool());
148  Assert.assertEquals(false, result.isSetHas_access());
149  Assert.assertEquals(TErrorCode.INTERNAL_ERROR, result.getStatus().getStatus_code());
150 
151  String expectedMessage = "Failed to resolve user 'userA' to a pool while " +
152  "evaluating the 'primaryGroup' or 'secondaryGroup' queue placement rules because " +
153  "no groups were found for the user. This is likely because the user does not " +
154  "exist on the local operating system.";
155  Assert.assertEquals(expectedMessage,
156  Iterables.getOnlyElement(result.getStatus().getError_msgs()));
157  }
158 
159  @Test
160  public void testPoolAcls() throws Exception {
162  Assert.assertTrue(poolService_.hasAccess("root.queueA", "userA"));
163  Assert.assertTrue(poolService_.hasAccess("root.queueB", "userB"));
164  Assert.assertFalse(poolService_.hasAccess("root.queueB", "userA"));
165  Assert.assertTrue(poolService_.hasAccess("root.queueB", "root"));
166  }
167 
168  @Test
169  public void testPoolLimitConfigs() throws Exception {
171  checkPoolConfigResult("root", 15, 50, -1);
172  checkPoolConfigResult("root.queueA", 10, 30, 1024 * ByteUnits.MEGABYTE);
173  checkPoolConfigResult("root.queueB", 5, 10, -1);
174  }
175 
176  @Test
177  public void testDefaultConfigs() throws Exception {
179  Assert.assertEquals("root.userA", poolService_.assignToPool("", "userA"));
180  Assert.assertTrue(poolService_.hasAccess("root.userA", "userA"));
181  checkPoolConfigResult("root", 200, 200, -1);
182  }
183 
184  @Test
185  public void testUpdatingConfigs() throws Exception {
186  // Tests updating the config files and then checking the pool resolution, ACLs, and
187  // pool limit configs. This tests all three together rather than separating into
188  // separate test cases because we updateConfigFiles() will end up waiting around 7
189  // seconds, so this helps cut down on the total test execution time.
190  // A one second pause is necessary to ensure the file timestamps are unique if the
191  // test gets here within one second.
193  Thread.sleep(1000L);
196  // Wait at least 1 second more than the time it will take for the
197  // AllocationFileLoaderService to update the file. The FileWatchService does not
198  // have that additional wait time, so it will be updated within 'CHECK_INTERVAL_MS'
199  Thread.sleep(1000L + CHECK_INTERVAL_MS +
200  AllocationFileLoaderService.ALLOC_RELOAD_WAIT_MS);
202  }
203 
204  @Test
205  public void testModifiedConfigs() throws Exception {
206  // Tests the results are the same as testUpdatingConfigs() as when we create the
207  // pool service with the same modified configs initially (i.e. not updating).
210  }
211 
212  @Test
213  public void testNullLlamaSite() throws Exception {
215 
216  // Test pool resolution
217  Assert.assertEquals("root.queueA", poolService_.assignToPool("queueA", "userA"));
218  Assert.assertNull(poolService_.assignToPool("queueX", "userA"));
219  Assert.assertEquals("root.queueC", poolService_.assignToPool("queueC", "userA"));
220 
221  // Test pool ACLs
222  Assert.assertTrue(poolService_.hasAccess("root.queueA", "userA"));
223  Assert.assertTrue(poolService_.hasAccess("root.queueB", "userB"));
224  Assert.assertTrue(poolService_.hasAccess("root.queueB", "userA"));
225  Assert.assertFalse(poolService_.hasAccess("root.queueC", "userA"));
226  Assert.assertTrue(poolService_.hasAccess("root.queueC", "root"));
227 
228  // Test pool limits
229  checkPoolConfigResult("root", 200, 200, -1);
230  checkPoolConfigResult("root.queueA", 200, 200, 100000 * ByteUnits.MEGABYTE);
231  checkPoolConfigResult("root.queueB", 200, 200, -1);
232  checkPoolConfigResult("root.queueC", 200, 200, 128 * ByteUnits.MEGABYTE);
233  }
234 
235  private void checkModifiedConfigResults() throws IOException {
236  // Test pool resolution: now there's a queueC
237  Assert.assertEquals("root.queueA", poolService_.assignToPool("queueA", "userA"));
238  Assert.assertNull(poolService_.assignToPool("queueX", "userA"));
239  Assert.assertEquals("root.queueC", poolService_.assignToPool("queueC", "userA"));
240 
241  // Test pool ACL changes
242  Assert.assertTrue(poolService_.hasAccess("root.queueA", "userA"));
243  Assert.assertTrue(poolService_.hasAccess("root.queueB", "userB"));
244  Assert.assertTrue(poolService_.hasAccess("root.queueB", "userA"));
245  Assert.assertFalse(poolService_.hasAccess("root.queueC", "userA"));
246  Assert.assertTrue(poolService_.hasAccess("root.queueC", "root"));
247 
248  // Test pool limit changes
249  checkPoolConfigResult("root", 15, 100, -1);
250  checkPoolConfigResult("root.queueA", 10, 30, 100000 * ByteUnits.MEGABYTE);
251  checkPoolConfigResult("root.queueB", 5, 10, -1);
252  checkPoolConfigResult("root.queueC", 10, 30, 128 * ByteUnits.MEGABYTE);
253  }
254 
258  private void checkPoolConfigResult(String pool, long expectedMaxRequests,
259  long expectedMaxQueued, long expectedMaxMemUsage) {
260  TPoolConfigResult expectedResult = new TPoolConfigResult();
261  expectedResult.setMax_requests(expectedMaxRequests);
262  expectedResult.setMax_queued(expectedMaxQueued);
263  expectedResult.setMem_limit(expectedMaxMemUsage);
264  Assert.assertEquals("Unexpected config values for pool " + pool,
265  expectedResult, poolService_.getPoolConfig(pool));
266  }
267 }
void checkPoolConfigResult(String pool, long expectedMaxRequests, long expectedMaxQueued, long expectedMaxMemUsage)
ObjectPool pool
void createPoolService(String allocationFile, String llamaConfFile)
uint64_t Test(T *ht, const ProbeTuple *input, uint64_t num_tuples)