1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.rsgroup;
21
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertNull;
25 import static org.junit.Assert.assertTrue;
26 import static org.junit.Assert.fail;
27
28 import java.io.IOException;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.hadoop.hbase.HColumnDescriptor;
37 import org.apache.hadoop.hbase.HTableDescriptor;
38 import org.apache.hadoop.hbase.NamespaceDescriptor;
39 import org.apache.hadoop.hbase.ServerName;
40 import org.apache.hadoop.hbase.TableName;
41 import org.apache.hadoop.hbase.Waiter;
42 import org.apache.hadoop.hbase.constraint.ConstraintException;
43 import org.apache.hadoop.hbase.master.ServerManager;
44 import org.apache.hadoop.hbase.master.TableNamespaceManager;
45 import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
46 import org.apache.hadoop.hbase.net.Address;
47 import org.apache.hadoop.hbase.quotas.QuotaUtil;
48 import org.apache.hadoop.hbase.testclassification.MediumTests;
49 import org.apache.hadoop.hbase.util.Bytes;
50 import org.junit.After;
51 import org.junit.AfterClass;
52 import org.junit.Assert;
53 import org.junit.Before;
54 import org.junit.BeforeClass;
55 import org.junit.Test;
56 import org.junit.experimental.categories.Category;
57
58 import com.google.common.collect.Sets;
59
60 @Category({MediumTests.class})
61 public class TestRSGroupsAdmin1 extends TestRSGroupsBase {
62 protected static final Log LOG = LogFactory.getLog(TestRSGroupsAdmin1.class);
63
64 @BeforeClass
65 public static void setUp() throws Exception {
66 setUpTestBeforeClass();
67 }
68
69 @AfterClass
70 public static void tearDown() throws Exception {
71 tearDownAfterClass();
72 }
73
74 @Before
75 public void beforeMethod() throws Exception {
76 setUpBeforeMethod();
77 }
78
79 @After
80 public void afterMethod() throws Exception {
81 tearDownAfterMethod();
82 }
83
84 @Test
85 public void testValidGroupNames() throws IOException {
86 String[] badNames = {"foo*","foo@","-"};
87 String[] goodNames = {"foo_123"};
88
89 for(String entry: badNames) {
90 try {
91 rsGroupAdmin.addRSGroup(entry);
92 fail("Expected a constraint exception for: "+entry);
93 } catch(ConstraintException ex) {
94
95 }
96 }
97
98 for(String entry: goodNames) {
99 rsGroupAdmin.addRSGroup(entry);
100 }
101 }
102
103 @Test
104 public void testBogusArgs() throws Exception {
105 assertNull(rsGroupAdmin.getRSGroupInfoOfTable(TableName.valueOf("nonexistent")));
106 assertNull(rsGroupAdmin.getRSGroupOfServer(Address.fromParts("bogus",123)));
107 assertNull(rsGroupAdmin.getRSGroupInfo("bogus"));
108
109 try {
110 rsGroupAdmin.removeRSGroup("bogus");
111 fail("Expected removing bogus group to fail");
112 } catch(ConstraintException ex) {
113
114 }
115
116 try {
117 rsGroupAdmin.moveTables(Sets.newHashSet(TableName.valueOf("bogustable")), "bogus");
118 fail("Expected move with bogus group to fail");
119 } catch(ConstraintException ex) {
120
121 }
122
123 try {
124 rsGroupAdmin.moveServers(Sets.newHashSet(Address.fromParts("bogus",123)), "bogus");
125 fail("Expected move with bogus group to fail");
126 } catch(ConstraintException ex) {
127
128 }
129
130 try {
131 rsGroupAdmin.balanceRSGroup("bogus");
132 fail("Expected move with bogus group to fail");
133 } catch(ConstraintException ex) {
134
135 }
136 }
137
138 @Test
139 public void testNamespaceConstraint() throws Exception {
140 String nsName = tablePrefix+"_foo";
141 String groupName = tablePrefix+"_foo";
142 LOG.info("testNamespaceConstraint");
143 rsGroupAdmin.addRSGroup(groupName);
144 assertTrue(observer.preAddRSGroupCalled);
145 assertTrue(observer.postAddRSGroupCalled);
146 admin.createNamespace(NamespaceDescriptor.create(nsName)
147 .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName)
148 .build());
149
150 try {
151 rsGroupAdmin.removeRSGroup(groupName);
152 fail("Expected a constraint exception");
153 } catch (IOException ex) {
154 }
155
156
157 admin.modifyNamespace(
158 NamespaceDescriptor.create(nsName)
159 .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName)
160 .build());
161 String anotherGroup = tablePrefix+"_anotherGroup";
162 rsGroupAdmin.addRSGroup(anotherGroup);
163
164 admin.deleteNamespace(nsName);
165 rsGroupAdmin.removeRSGroup(groupName);
166 assertTrue(observer.preRemoveRSGroupCalled);
167 assertTrue(observer.postRemoveRSGroupCalled);
168 try {
169 admin.createNamespace(NamespaceDescriptor.create(nsName)
170 .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "foo")
171 .build());
172 fail("Expected a constraint exception");
173 } catch (IOException ex) {
174 }
175 }
176
177 @Test
178 public void testGroupInfoMultiAccessing() throws Exception {
179 RSGroupInfoManager manager = RSGroupAdminEndpoint.getGroupInfoManager();
180 final RSGroupInfo defaultGroup = manager.getRSGroup("default");
181
182
183 Iterator<Address> it = defaultGroup.getServers().iterator();
184 manager.getRSGroup("default");
185 it.next();
186 }
187
188 @Test
189 public void testFailRemoveGroup() throws IOException, InterruptedException {
190 LOG.info("testFailRemoveGroup");
191
192 int initNumGroups = rsGroupAdmin.listRSGroups().size();
193 addGroup(rsGroupAdmin, "bar", 3);
194 TableName tableName = TableName.valueOf(tablePrefix+"_my_table");
195 TEST_UTIL.createTable(tableName, Bytes.toBytes("f"));
196 rsGroupAdmin.moveTables(Sets.newHashSet(tableName), "bar");
197 RSGroupInfo barGroup = rsGroupAdmin.getRSGroupInfo("bar");
198
199 try {
200 rsGroupAdmin.removeRSGroup(barGroup.getName());
201 fail("Expected remove group to fail");
202 } catch(IOException e) {
203 }
204
205 try {
206 rsGroupAdmin.moveServers(barGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
207 fail("Expected move servers to fail");
208 } catch(IOException e) {
209 }
210
211 rsGroupAdmin.moveTables(barGroup.getTables(), RSGroupInfo.DEFAULT_GROUP);
212 try {
213 rsGroupAdmin.removeRSGroup(barGroup.getName());
214 fail("Expected move servers to fail");
215 } catch(IOException e) {
216 }
217
218 rsGroupAdmin.moveServers(barGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
219 rsGroupAdmin.removeRSGroup(barGroup.getName());
220
221 Assert.assertEquals(initNumGroups, rsGroupAdmin.listRSGroups().size());
222 }
223
224 @Test
225 public void testMultiTableMove() throws Exception {
226 LOG.info("testMultiTableMove");
227
228 final TableName tableNameA = TableName.valueOf(tablePrefix + "_testMultiTableMoveA");
229 final TableName tableNameB = TableName.valueOf(tablePrefix + "_testMultiTableMoveB");
230 final byte[] familyNameBytes = Bytes.toBytes("f");
231 String newGroupName = getGroupName("testMultiTableMove");
232 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, newGroupName, 1);
233
234 TEST_UTIL.createTable(tableNameA, familyNameBytes);
235 TEST_UTIL.createTable(tableNameB, familyNameBytes);
236 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
237 @Override
238 public boolean evaluate() throws Exception {
239 List<String> regionsA = getTableRegionMap().get(tableNameA);
240 if (regionsA == null) {
241 return false;
242 }
243 List<String> regionsB = getTableRegionMap().get(tableNameB);
244 if (regionsB == null) {
245 return false;
246 }
247 return getTableRegionMap().get(tableNameA).size() >= 1
248 && getTableRegionMap().get(tableNameB).size() >= 1;
249 }
250 });
251
252 RSGroupInfo tableGrpA = rsGroupAdmin.getRSGroupInfoOfTable(tableNameA);
253 assertTrue(tableGrpA.getName().equals(RSGroupInfo.DEFAULT_GROUP));
254
255 RSGroupInfo tableGrpB = rsGroupAdmin.getRSGroupInfoOfTable(tableNameB);
256 assertTrue(tableGrpB.getName().equals(RSGroupInfo.DEFAULT_GROUP));
257
258 LOG.info("Moving table [" + tableNameA + "," + tableNameB + "] to " + newGroup.getName());
259 rsGroupAdmin.moveTables(Sets.newHashSet(tableNameA, tableNameB), newGroup.getName());
260
261
262 Assert.assertEquals(newGroup.getName(),
263 rsGroupAdmin.getRSGroupInfoOfTable(tableNameA).getName());
264
265 Assert.assertEquals(newGroup.getName(),
266 rsGroupAdmin.getRSGroupInfoOfTable(tableNameB).getName());
267
268
269 Set<TableName> DefaultTables =
270 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables();
271 assertFalse(DefaultTables.contains(tableNameA));
272 assertFalse(DefaultTables.contains(tableNameB));
273
274
275 Set<TableName> newGroupTables = rsGroupAdmin.getRSGroupInfo(newGroupName).getTables();
276 assertTrue(newGroupTables.contains(tableNameA));
277 assertTrue(newGroupTables.contains(tableNameB));
278 }
279
280 @Test
281 public void testTableMoveTruncateAndDrop() throws Exception {
282 LOG.info("testTableMove");
283
284 final TableName tableName = TableName.valueOf(tablePrefix + "_testTableMoveAndDrop");
285 final byte[] familyNameBytes = Bytes.toBytes("f");
286 String newGroupName = getGroupName("testTableMove");
287 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, newGroupName, 2);
288
289 TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
290 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
291 @Override
292 public boolean evaluate() throws Exception {
293 List<String> regions = getTableRegionMap().get(tableName);
294 if (regions == null)
295 return false;
296 return getTableRegionMap().get(tableName).size() >= 5;
297 }
298 });
299
300 RSGroupInfo tableGrp = rsGroupAdmin.getRSGroupInfoOfTable(tableName);
301 assertTrue(tableGrp.getName().equals(RSGroupInfo.DEFAULT_GROUP));
302
303
304 LOG.info("Moving table "+tableName+" to "+newGroup.getName());
305 rsGroupAdmin.moveTables(Sets.newHashSet(tableName), newGroup.getName());
306
307
308 Assert.assertEquals(newGroup.getName(),
309 rsGroupAdmin.getRSGroupInfoOfTable(tableName).getName());
310
311 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
312 @Override
313 public boolean evaluate() throws Exception {
314 Map<ServerName, List<String>> serverMap = getTableServerRegionMap().get(tableName);
315 int count = 0;
316 if (serverMap != null) {
317 for (ServerName rs : serverMap.keySet()) {
318 if (newGroup.containsServer(rs.getAddress())) {
319 count += serverMap.get(rs).size();
320 }
321 }
322 }
323 return count == 5;
324 }
325 });
326
327
328 admin.disableTable(tableName);
329 admin.truncateTable(tableName, true);
330 Assert.assertEquals(1, rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables().size());
331 Assert.assertEquals(tableName, rsGroupAdmin.getRSGroupInfo(
332 newGroup.getName()).getTables().first());
333
334
335 TEST_UTIL.deleteTable(tableName);
336 Assert.assertEquals(0, rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables().size());
337
338 assertTrue(observer.preMoveTablesCalled);
339 assertTrue(observer.postMoveTablesCalled);
340 }
341
342 @Test
343 public void testDisabledTableMove() throws Exception {
344 final TableName tableName = TableName.valueOf(tablePrefix + "_testDisabledTableMove");
345 final byte[] familyNameBytes = Bytes.toBytes("f");
346 String newGroupName = getGroupName("testDisabledTableMove");
347 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, newGroupName, 2);
348
349 TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
350 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
351 @Override
352 public boolean evaluate() throws Exception {
353 List<String> regions = getTableRegionMap().get(tableName);
354 if (regions == null) {
355 return false;
356 }
357 return getTableRegionMap().get(tableName).size() >= 5;
358 }
359 });
360
361 RSGroupInfo tableGrp = rsGroupAdmin.getRSGroupInfoOfTable(tableName);
362 assertTrue(tableGrp.getName().equals(RSGroupInfo.DEFAULT_GROUP));
363
364
365 admin.disableTable(tableName);
366
367
368 LOG.info("Moving table "+ tableName + " to " + newGroup.getName());
369 rsGroupAdmin.moveTables(Sets.newHashSet(tableName), newGroup.getName());
370
371
372 Assert.assertEquals(newGroup.getName(),
373 rsGroupAdmin.getRSGroupInfoOfTable(tableName).getName());
374 }
375
376 @Test
377 public void testRSGroupListDoesNotContainFailedTableCreation() throws Exception {
378 toggleQuotaCheckAndRestartMiniCluster(true);
379 String nsp = "np1";
380 NamespaceDescriptor nspDesc =
381 NamespaceDescriptor.create(nsp).addConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "5")
382 .addConfiguration(TableNamespaceManager.KEY_MAX_TABLES, "2").build();
383 admin.createNamespace(nspDesc);
384 assertEquals(3, admin.listNamespaceDescriptors().length);
385 HColumnDescriptor fam1 = new HColumnDescriptor("fam1");
386 HTableDescriptor tableDescOne =
387 new HTableDescriptor(TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table1"));
388 tableDescOne.addFamily(fam1);
389 admin.createTable(tableDescOne);
390
391 HTableDescriptor tableDescTwo =
392 new HTableDescriptor(TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table2"));
393 tableDescTwo.addFamily(fam1);
394 boolean constraintViolated = false;
395
396 try {
397 admin.createTable(tableDescTwo, Bytes.toBytes("AAA"), Bytes.toBytes("ZZZ"),
398 6);
399 Assert.fail("Creation table should fail because of quota violation.");
400 } catch (Exception exp) {
401 assertTrue(exp instanceof IOException);
402 constraintViolated = true;
403 } finally {
404 assertTrue("Constraint not violated for table " + tableDescTwo.getTableName(),
405 constraintViolated);
406 }
407 List<RSGroupInfo> rsGroupInfoList = rsGroupAdmin.listRSGroups();
408 boolean foundTable2 = false;
409 boolean foundTable1 = false;
410 for (int i = 0; i < rsGroupInfoList.size(); i++){
411 if(rsGroupInfoList.get(i).getTables().contains(tableDescTwo.getTableName())){
412 foundTable2 = true;
413 }
414 if(rsGroupInfoList.get(i).getTables().contains(tableDescOne.getTableName())){
415 foundTable1 = true;
416 }
417 }
418 assertFalse("Found table2 in rsgroup list.", foundTable2);
419 assertTrue("Did not find table1 in rsgroup list", foundTable1);
420
421 TEST_UTIL.deleteTable(tableDescOne.getTableName());
422 admin.deleteNamespace(nspDesc.getName());
423 toggleQuotaCheckAndRestartMiniCluster(false);
424
425 }
426
427 private void toggleQuotaCheckAndRestartMiniCluster(boolean enable) throws Exception {
428 TEST_UTIL.shutdownMiniCluster();
429 TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, enable);
430 TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE - 1);
431 TEST_UTIL.getConfiguration().setInt(
432 ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART,
433 NUM_SLAVES_BASE - 1);
434 TEST_UTIL.getConfiguration().setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
435 initialize();
436 }
437
438 }