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.assertNotNull;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assert.fail;
28
29 import com.google.common.collect.Sets;
30
31 import java.io.IOException;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.apache.hadoop.hbase.HRegionInfo;
39 import org.apache.hadoop.hbase.ServerName;
40 import org.apache.hadoop.hbase.TableName;
41 import org.apache.hadoop.hbase.TableNotFoundException;
42 import org.apache.hadoop.hbase.Waiter;
43 import org.apache.hadoop.hbase.client.ClusterConnection;
44 import org.apache.hadoop.hbase.master.HMaster;
45 import org.apache.hadoop.hbase.master.RegionState;
46 import org.apache.hadoop.hbase.net.Address;
47 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
48 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos;
49 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetServerInfoRequest;
50 import org.apache.hadoop.hbase.testclassification.MediumTests;
51 import org.apache.hadoop.hbase.util.Bytes;
52 import org.junit.After;
53 import org.junit.AfterClass;
54 import org.junit.Assert;
55 import org.junit.Before;
56 import org.junit.BeforeClass;
57 import org.junit.Test;
58 import org.junit.experimental.categories.Category;
59
60 @Category({MediumTests.class})
61 public class TestRSGroupsAdmin2 extends TestRSGroupsBase {
62 protected static final Log LOG = LogFactory.getLog(TestRSGroupsAdmin2.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
85 @Test
86 public void testRegionMove() throws Exception {
87 LOG.info("testRegionMove");
88
89 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, getGroupName("testRegionMove"), 1);
90 final TableName tableName = TableName.valueOf(tablePrefix + rand.nextInt());
91 final byte[] familyNameBytes = Bytes.toBytes("f");
92
93 TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 6);
94 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
95 @Override
96 public boolean evaluate() throws Exception {
97 List<String> regions = getTableRegionMap().get(tableName);
98 if (regions == null)
99 return false;
100 return getTableRegionMap().get(tableName).size() >= 6;
101 }
102 });
103
104
105 Map<ServerName,List<String>> assignMap =
106 getTableServerRegionMap().get(tableName);
107 String targetRegion = null;
108 for(ServerName server : assignMap.keySet()) {
109 targetRegion = assignMap.get(server).size() > 0 ? assignMap.get(server).get(0) : null;
110 if(targetRegion != null) {
111 break;
112 }
113 }
114
115 ServerName targetServer = null;
116 for(ServerName server : admin.getClusterStatus().getServers()) {
117 if(!newGroup.containsServer(server.getAddress())) {
118 targetServer = server;
119 break;
120 }
121 }
122 assertNotNull(targetServer);
123
124 final AdminProtos.AdminService.BlockingInterface targetRS =
125 admin.getConnection().getAdmin(targetServer);
126
127
128 rsGroupAdmin.moveServers(Sets.newHashSet(targetServer.getAddress()),
129 newGroup.getName());
130 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
131 @Override
132 public boolean evaluate() throws Exception {
133 return ProtobufUtil.getOnlineRegions(targetRS).size() <= 0;
134 }
135 });
136
137
138 TEST_UTIL.getHBaseAdmin().move(Bytes.toBytes(HRegionInfo.encodeRegionName(Bytes.toBytes(targetRegion))),
139 Bytes.toBytes(targetServer.getServerName()));
140 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
141 @Override
142 public boolean evaluate() throws Exception {
143 List<String> regions = getTableRegionMap().get(tableName);
144 Set<RegionState> regionsInTransition = admin.getClusterStatus().getRegionsInTransition();
145 return (regions != null && getTableRegionMap().get(tableName).size() == 6) &&
146 ( regionsInTransition == null || regionsInTransition.size() < 1);
147 }
148 });
149
150
151 for (HRegionInfo region: ProtobufUtil.getOnlineRegions(targetRS)) {
152 if (targetRegion.equals(region.getRegionNameAsString())) {
153 fail("Target server opened region");
154 }
155 }
156 }
157
158 @Test
159 public void testRegionServerMove() throws IOException,
160 InterruptedException {
161 LOG.info("testRegionServerMove");
162
163 int initNumGroups = rsGroupAdmin.listRSGroups().size();
164 RSGroupInfo appInfo = addGroup(rsGroupAdmin, getGroupName("testRegionServerMove"), 1);
165 RSGroupInfo adminInfo = addGroup(rsGroupAdmin, getGroupName("testRegionServerMove"), 1);
166 RSGroupInfo dInfo = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP);
167 Assert.assertEquals(initNumGroups + 2, rsGroupAdmin.listRSGroups().size());
168 assertEquals(1, adminInfo.getServers().size());
169 assertEquals(1, appInfo.getServers().size());
170 assertEquals(getNumServers() - 2, dInfo.getServers().size());
171 rsGroupAdmin.moveServers(appInfo.getServers(),
172 RSGroupInfo.DEFAULT_GROUP);
173 rsGroupAdmin.removeRSGroup(appInfo.getName());
174 rsGroupAdmin.moveServers(adminInfo.getServers(),
175 RSGroupInfo.DEFAULT_GROUP);
176 rsGroupAdmin.removeRSGroup(adminInfo.getName());
177 Assert.assertEquals(rsGroupAdmin.listRSGroups().size(), initNumGroups);
178 }
179
180 @Test
181 public void testMoveServers() throws Exception {
182 LOG.info("testMoveServers");
183
184
185 addGroup(rsGroupAdmin, "bar", 3);
186 rsGroupAdmin.addRSGroup("foo");
187
188 RSGroupInfo barGroup = rsGroupAdmin.getRSGroupInfo("bar");
189 RSGroupInfo fooGroup = rsGroupAdmin.getRSGroupInfo("foo");
190 assertEquals(3, barGroup.getServers().size());
191 assertEquals(0, fooGroup.getServers().size());
192
193
194 try {
195 rsGroupAdmin.moveServers(Sets.newHashSet(Address.fromString("foo:9999")),"foo");
196 fail("Bogus servers shouldn't have been successfully moved.");
197 } catch(IOException ex) {
198 String exp = "Server foo:9999 does not have a group.";
199 String msg = "Expected '"+exp+"' in exception message: ";
200 assertTrue(msg+" "+ex.getMessage(), ex.getMessage().contains(exp));
201 }
202
203
204 LOG.info("moving servers "+barGroup.getServers()+" to group foo");
205 rsGroupAdmin.moveServers(barGroup.getServers(), fooGroup.getName());
206
207 barGroup = rsGroupAdmin.getRSGroupInfo("bar");
208 fooGroup = rsGroupAdmin.getRSGroupInfo("foo");
209 assertEquals(0,barGroup.getServers().size());
210 assertEquals(3,fooGroup.getServers().size());
211
212 LOG.info("moving servers "+fooGroup.getServers()+" to group default");
213 rsGroupAdmin.moveServers(fooGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
214
215 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
216 @Override
217 public boolean evaluate() throws Exception {
218 return getNumServers() ==
219 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().size();
220 }
221 });
222
223 fooGroup = rsGroupAdmin.getRSGroupInfo("foo");
224 assertEquals(0,fooGroup.getServers().size());
225
226
227 LOG.info("Remove group "+barGroup.getName());
228 rsGroupAdmin.removeRSGroup(barGroup.getName());
229 Assert.assertEquals(null, rsGroupAdmin.getRSGroupInfo(barGroup.getName()));
230 LOG.info("Remove group "+fooGroup.getName());
231 rsGroupAdmin.removeRSGroup(fooGroup.getName());
232 Assert.assertEquals(null, rsGroupAdmin.getRSGroupInfo(fooGroup.getName()));
233 }
234
235 @Test
236 public void testRemoveServers() throws Exception {
237 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, "testRemoveServers", 3);
238 ServerName targetServer = ServerName.parseServerName(
239 newGroup.getServers().iterator().next().toString());
240 try {
241 rsGroupAdmin.removeServers(Sets.newHashSet(targetServer.getAddress()));
242 fail("Online servers shouldn't have been successfully removed.");
243 } catch(IOException ex) {
244 String exp = "Server " + targetServer.getAddress()
245 + " is an online server, not allowed to remove.";
246 String msg = "Expected '" + exp + "' in exception message: ";
247 assertTrue(msg + " " + ex.getMessage(), ex.getMessage().contains(exp));
248 }
249 assertTrue(newGroup.getServers().contains(targetServer.getAddress()));
250
251 AdminProtos.AdminService.BlockingInterface targetRS =
252 ((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
253 try {
254 targetServer = ProtobufUtil.toServerName(targetRS.getServerInfo(null,
255 GetServerInfoRequest.newBuilder().build()).getServerInfo().getServerName());
256
257
258 targetRS.stopServer(null,
259 AdminProtos.StopServerRequest.newBuilder().setReason("Die").build());
260 } catch(Exception e) {
261 }
262
263 final HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
264
265 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
266 @Override
267 public boolean evaluate() throws Exception {
268 return !master.getServerManager().areDeadServersInProgress()
269 && cluster.getClusterStatus().getDeadServerNames().size() > 0;
270 }
271 });
272
273 try {
274 rsGroupAdmin.removeServers(Sets.newHashSet(targetServer.getAddress()));
275 fail("Dead servers shouldn't have been successfully removed.");
276 } catch(IOException ex) {
277 String exp = "Server " + targetServer.getAddress() + " is on the dead servers list,"
278 + " Maybe it will come back again, not allowed to remove.";
279 String msg = "Expected '" + exp + "' in exception message: ";
280 assertTrue(msg + " " + ex.getMessage(), ex.getMessage().contains(exp));
281 }
282 assertTrue(newGroup.getServers().contains(targetServer.getAddress()));
283
284 ServerName sn = TEST_UTIL.getHBaseClusterInterface().getClusterStatus().getMaster();
285 TEST_UTIL.getHBaseClusterInterface().stopMaster(sn);
286 TEST_UTIL.getHBaseClusterInterface().waitForMasterToStop(sn, 60000);
287 TEST_UTIL.getHBaseClusterInterface().startMaster(sn.getHostname(), 0);
288 TEST_UTIL.getHBaseClusterInterface().waitForActiveAndReadyMaster(60000);
289
290 assertEquals(3, cluster.getClusterStatus().getServersSize());
291 assertFalse(cluster.getClusterStatus().getServers().contains(targetServer));
292 assertFalse(cluster.getClusterStatus().getDeadServerNames().contains(targetServer));
293 assertTrue(newGroup.getServers().contains(targetServer.getAddress()));
294
295 rsGroupAdmin.removeServers(Sets.newHashSet(targetServer.getAddress()));
296 Set<Address> newGroupServers = rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getServers();
297 assertFalse(newGroupServers.contains(targetServer.getAddress()));
298 assertEquals(2, newGroupServers.size());
299
300 assertTrue(observer.preRemoveServersCalled);
301 }
302
303 @Test
304 public void testNonExistentTableMove() throws Exception {
305 TableName tableName = TableName.valueOf(tablePrefix + rand.nextInt());
306
307 RSGroupInfo tableGrp = rsGroupAdmin.getRSGroupInfoOfTable(tableName);
308 assertNull(tableGrp);
309
310
311 boolean exist = admin.tableExists(tableName);
312 assertFalse(exist);
313
314 LOG.info("Moving table "+ tableName + " to " + RSGroupInfo.DEFAULT_GROUP);
315 try {
316 rsGroupAdmin.moveTables(Sets.newHashSet(tableName), RSGroupInfo.DEFAULT_GROUP);
317 fail("Table " + tableName + " shouldn't have been successfully moved.");
318 } catch(IOException ex) {
319 assertTrue(ex instanceof TableNotFoundException);
320 }
321
322 try {
323 rsGroupAdmin.moveServersAndTables(
324 Sets.newHashSet(Address.fromParts("bogus",123)),
325 Sets.newHashSet(tableName), RSGroupInfo.DEFAULT_GROUP);
326 fail("Table " + tableName + " shouldn't have been successfully moved.");
327 } catch(IOException ex) {
328 assertTrue(ex instanceof TableNotFoundException);
329 }
330
331 assertNull(rsGroupAdmin.getRSGroupInfoOfTable(tableName));
332 }
333
334 @Test
335 public void testMoveServersAndTables() throws Exception {
336 final TableName tableName = TableName.valueOf(tablePrefix + "_testMoveServersAndTables");
337 final RSGroupInfo newGroup = addGroup(rsGroupAdmin, getGroupName("testMoveServersAndTables"), 1);
338
339
340 final byte[] familyNameBytes = Bytes.toBytes("f");
341 TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
342 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
343 @Override
344 public boolean evaluate() throws Exception {
345 List<String> regions = getTableRegionMap().get(tableName);
346 if (regions == null)
347 return false;
348 return getTableRegionMap().get(tableName).size() >= 5;
349 }
350 });
351
352
353 ServerName targetServer = null;
354 for(ServerName server : admin.getClusterStatus().getServers()) {
355 if(!newGroup.containsServer(server.getAddress()) &&
356 !rsGroupAdmin.getRSGroupInfo("master").containsServer(server.getAddress())) {
357 targetServer = server;
358 break;
359 }
360 }
361
362 LOG.debug("Print group info : " + rsGroupAdmin.listRSGroups());
363 int oldDefaultGroupServerSize =
364 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().size();
365 int oldDefaultGroupTableSize =
366 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables().size();
367
368
369 try {
370 rsGroupAdmin.moveServersAndTables(Sets.newHashSet(Address.fromString("foo:9999")),
371 Sets.newHashSet(tableName), newGroup.getName());
372 fail("Bogus servers shouldn't have been successfully moved.");
373 } catch(IOException ex) {
374 }
375
376
377 try {
378 rsGroupAdmin.moveServersAndTables(Sets.newHashSet(targetServer.getAddress()),
379 Sets.newHashSet(tableName), RSGroupInfo.DEFAULT_GROUP);
380 fail("servers shouldn't have been successfully moved.");
381 } catch(IOException ex) {
382 }
383
384
385 Assert.assertEquals(oldDefaultGroupServerSize,
386 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().size());
387 Assert.assertEquals(oldDefaultGroupTableSize,
388 rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables().size());
389
390
391 Assert.assertEquals(1,
392 rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getServers().size());
393 Assert.assertEquals(0,
394 rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables().size());
395
396
397 List<String> regionList = getTableRegionMap().get(tableName);
398 for(String region : regionList) {
399
400 admin.move(Bytes.toBytes(HRegionInfo.encodeRegionName(Bytes.toBytes(region))),
401 Bytes.toBytes(targetServer.getServerName()));
402 }
403
404 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
405 @Override
406 public boolean evaluate() throws Exception {
407 List<String> regions = getTableRegionMap().get(tableName);
408 Map<ServerName, List<String>> serverMap = getTableServerRegionMap().get(tableName);
409 Set<RegionState> regionsInTransition = admin.getClusterStatus().getRegionsInTransition();
410 return (regions != null && regions.size() == 5) &&
411 (serverMap != null && serverMap.size() == 1) &&
412 (regionsInTransition == null || regionsInTransition.size() < 1);
413 }
414 });
415
416
417 Assert.assertNotNull(getTableServerRegionMap().get(tableName));
418 Assert.assertNotNull(getTableServerRegionMap().get(tableName).get(targetServer));
419 Assert.assertEquals(5, getTableServerRegionMap().get(tableName).get(targetServer).size());
420
421
422 LOG.info("moving server and table to newGroup");
423 rsGroupAdmin.moveServersAndTables(Sets.newHashSet(targetServer.getAddress()),
424 Sets.newHashSet(tableName), newGroup.getName());
425
426
427 Assert.assertEquals(newGroup.getName(),
428 rsGroupAdmin.getRSGroupInfoOfTable(tableName).getName());
429
430
431 Set<Address> defaultServers = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers();
432 assertFalse(defaultServers.contains(targetServer.getAddress()));
433
434
435 Set<Address> newGroupServers = rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getServers();
436 assertTrue(newGroupServers.contains(targetServer.getAddress()));
437
438
439 Set<TableName> defaultTables = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables();
440 assertFalse(defaultTables.contains(tableName));
441
442
443 Set<TableName> newGroupTables = rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables();
444 assertTrue(newGroupTables.contains(tableName));
445
446 assertTrue(observer.preMoveServersAndTables);
447 assertTrue(observer.postMoveServersAndTables);
448 }
449
450 }