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