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 com.google.common.collect.Maps;
23 import com.google.common.collect.Sets;
24
25 import java.io.IOException;
26 import java.util.HashSet;
27 import java.util.LinkedList;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Random;
31 import java.util.Set;
32 import java.util.TreeMap;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.hadoop.hbase.ClusterStatus;
37 import org.apache.hadoop.hbase.HBaseCluster;
38 import org.apache.hadoop.hbase.HBaseTestingUtility;
39 import org.apache.hadoop.hbase.HConstants;
40 import org.apache.hadoop.hbase.HRegionInfo;
41 import org.apache.hadoop.hbase.HTableDescriptor;
42 import org.apache.hadoop.hbase.MiniHBaseCluster;
43 import org.apache.hadoop.hbase.NamespaceDescriptor;
44 import org.apache.hadoop.hbase.RegionLoad;
45 import org.apache.hadoop.hbase.ServerName;
46 import org.apache.hadoop.hbase.TableName;
47 import org.apache.hadoop.hbase.Waiter;
48 import org.apache.hadoop.hbase.client.HBaseAdmin;
49 import org.apache.hadoop.hbase.coprocessor.BaseMasterObserver;
50 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
51 import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
52 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
53 import org.apache.hadoop.hbase.master.HMaster;
54 import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
55 import org.apache.hadoop.hbase.master.ServerManager;
56 import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
57 import org.apache.hadoop.hbase.net.Address;
58 import org.apache.hadoop.hbase.util.Bytes;
59 import org.apache.hadoop.hbase.util.JVMClusterUtil;
60
61 public abstract class TestRSGroupsBase {
62 protected static final Log LOG = LogFactory.getLog(TestRSGroupsBase.class);
63
64
65 protected final static String groupPrefix = "Group";
66 protected final static String tablePrefix = "Group";
67 protected final static Random rand = new Random();
68
69
70 protected static HBaseTestingUtility TEST_UTIL;
71 protected static HBaseAdmin admin;
72 protected static HBaseCluster cluster;
73 protected static RSGroupAdmin rsGroupAdmin;
74 protected static HMaster master;
75 protected static boolean init = false;
76 protected static RSGroupAdminEndpoint RSGroupAdminEndpoint;
77 protected static CPMasterObserver observer;
78
79 public final static long WAIT_TIMEOUT = 60000*5;
80 public final static int NUM_SLAVES_BASE = 4;
81
82 public static void setUpTestBeforeClass() throws Exception {
83 TEST_UTIL = new HBaseTestingUtility();
84 TEST_UTIL.getConfiguration().setFloat(
85 "hbase.master.balancer.stochastic.tableSkewCost", 6000);
86 TEST_UTIL.getConfiguration().set(
87 HConstants.HBASE_MASTER_LOADBALANCER_CLASS,
88 RSGroupBasedLoadBalancer.class.getName());
89 TEST_UTIL.getConfiguration().set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
90 RSGroupAdminEndpoint.class.getName() + "," + CPMasterObserver.class.getName());
91 TEST_UTIL.getConfiguration().setBoolean(
92 HConstants.ZOOKEEPER_USEMULTI,
93 true);
94 TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE - 1);
95 TEST_UTIL.getConfiguration().setInt(
96 ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART,
97 NUM_SLAVES_BASE - 1);
98 TEST_UTIL.getConfiguration().setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
99 initialize();
100 }
101
102 protected static void initialize() throws Exception {
103 admin = TEST_UTIL.getHBaseAdmin();
104 cluster = TEST_UTIL.getHBaseCluster();
105 master = ((MiniHBaseCluster)cluster).getMaster();
106 master.balanceSwitch(true);
107
108
109 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
110 @Override
111 public boolean evaluate() throws Exception {
112 return master.isInitialized() &&
113 ((RSGroupBasedLoadBalancer) master.getLoadBalancer()).isOnline();
114 }
115 });
116 admin.setBalancerRunning(false,true);
117 rsGroupAdmin = new VerifyingRSGroupAdminClient(new RSGroupAdminClient(TEST_UTIL.getConnection()),
118 TEST_UTIL.getConfiguration());
119 MasterCoprocessorHost host = master.getMasterCoprocessorHost();
120 observer = (CPMasterObserver) host.findCoprocessor(CPMasterObserver.class.getName());
121 RSGroupAdminEndpoint =
122 host.findCoprocessors(RSGroupAdminEndpoint.class).get(0);
123 }
124
125 public static void tearDownAfterClass() throws Exception {
126 TEST_UTIL.shutdownMiniCluster();
127 }
128
129 public void setUpBeforeMethod() throws Exception {
130 if(!init) {
131 init = true;
132 tearDownAfterMethod();
133 }
134 observer.resetFlags();
135 }
136
137 public void tearDownAfterMethod() throws Exception {
138 deleteTableIfNecessary();
139 deleteNamespaceIfNecessary();
140 deleteGroups();
141
142 int missing = NUM_SLAVES_BASE - getNumServers();
143 LOG.info("Restoring servers: "+missing);
144 for(int i=0; i<missing; i++) {
145 ((MiniHBaseCluster)cluster).startRegionServer();
146 }
147
148 rsGroupAdmin.addRSGroup("master");
149 ServerName masterServerName =
150 ((MiniHBaseCluster)cluster).getMaster().getServerName();
151
152 try {
153 rsGroupAdmin.moveServers(
154 Sets.newHashSet(masterServerName.getAddress()),
155 "master");
156 } catch (Exception ex) {
157
158 }
159
160 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
161 @Override
162 public boolean evaluate() throws Exception {
163 LOG.info("Waiting for cleanup to finish " + rsGroupAdmin.listRSGroups());
164
165
166
167 return rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().size()
168 == NUM_SLAVES_BASE;
169 }
170 });
171 }
172
173
174 protected int getNumServers() throws IOException {
175 ClusterStatus status = admin.getClusterStatus();
176 ServerName master = status.getMaster();
177 int count = 0;
178 for (ServerName sn : status.getServers()) {
179 if (!sn.equals(master)) {
180 count++;
181 }
182 }
183 return count;
184 }
185
186 protected RSGroupInfo addGroup(RSGroupAdmin gAdmin, String groupName,
187 int serverCount) throws IOException, InterruptedException {
188 RSGroupInfo defaultInfo = gAdmin
189 .getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP);
190 gAdmin.addRSGroup(groupName);
191
192 Set<Address> set = new HashSet<Address>();
193 for(Address server: defaultInfo.getServers()) {
194 if(set.size() == serverCount) {
195 break;
196 }
197 set.add(server);
198 }
199 gAdmin.moveServers(set, groupName);
200 RSGroupInfo result = gAdmin.getRSGroupInfo(groupName);
201 return result;
202 }
203
204 static void removeGroup(RSGroupAdminClient groupAdmin, String groupName) throws IOException {
205 RSGroupInfo info = groupAdmin.getRSGroupInfo(groupName);
206 groupAdmin.moveTables(info.getTables(), RSGroupInfo.DEFAULT_GROUP);
207 groupAdmin.moveServers(info.getServers(), RSGroupInfo.DEFAULT_GROUP);
208 groupAdmin.removeRSGroup(groupName);
209 }
210
211 protected void deleteTableIfNecessary() throws IOException {
212 for (HTableDescriptor desc : TEST_UTIL.getHBaseAdmin().listTables(tablePrefix+".*")) {
213 TEST_UTIL.deleteTable(desc.getTableName());
214 }
215 }
216
217 protected void deleteNamespaceIfNecessary() throws IOException {
218 for (NamespaceDescriptor desc : TEST_UTIL.getHBaseAdmin().listNamespaceDescriptors()) {
219 if(desc.getName().startsWith(tablePrefix)) {
220 admin.deleteNamespace(desc.getName());
221 }
222 }
223 }
224
225 protected void deleteGroups() throws IOException {
226 try (RSGroupAdmin groupAdmin = new RSGroupAdminClient(TEST_UTIL.getConnection())) {
227 for(RSGroupInfo group: groupAdmin.listRSGroups()) {
228 if(!group.getName().equals(RSGroupInfo.DEFAULT_GROUP)) {
229 groupAdmin.moveTables(group.getTables(), RSGroupInfo.DEFAULT_GROUP);
230 groupAdmin.moveServers(group.getServers(), RSGroupInfo.DEFAULT_GROUP);
231 groupAdmin.removeRSGroup(group.getName());
232 }
233 }
234 }
235 }
236
237 public Map<TableName, List<String>> getTableRegionMap() throws IOException {
238 Map<TableName, List<String>> map = Maps.newTreeMap();
239 Map<TableName, Map<ServerName, List<String>>> tableServerRegionMap
240 = getTableServerRegionMap();
241 for(TableName tableName : tableServerRegionMap.keySet()) {
242 if(!map.containsKey(tableName)) {
243 map.put(tableName, new LinkedList<String>());
244 }
245 for(List<String> subset: tableServerRegionMap.get(tableName).values()) {
246 map.get(tableName).addAll(subset);
247 }
248 }
249 return map;
250 }
251
252 public Map<TableName, Map<ServerName, List<String>>> getTableServerRegionMap()
253 throws IOException {
254 Map<TableName, Map<ServerName, List<String>>> map = Maps.newTreeMap();
255 ClusterStatus status = TEST_UTIL.getHBaseClusterInterface().getClusterStatus();
256 for(ServerName serverName : status.getServers()) {
257 for(RegionLoad rl : status.getLoad(serverName).getRegionsLoad().values()) {
258 TableName tableName = null;
259 try {
260 tableName = HRegionInfo.getTable(rl.getName());
261 } catch (IllegalArgumentException e) {
262 LOG.warn("Failed parse a table name from regionname=" +
263 Bytes.toStringBinary(rl.getName()));
264 continue;
265 }
266 if(!map.containsKey(tableName)) {
267 map.put(tableName, new TreeMap<ServerName, List<String>>());
268 }
269 if(!map.get(tableName).containsKey(serverName)) {
270 map.get(tableName).put(serverName, new LinkedList<String>());
271 }
272 map.get(tableName).get(serverName).add(rl.getNameAsString());
273 }
274 }
275 return map;
276 }
277
278 protected String getGroupName(String baseName) {
279 return groupPrefix+"_"+baseName+"_"+rand.nextInt(Integer.MAX_VALUE);
280 }
281
282
283
284
285
286 protected final ServerName getServerName(Address addr) {
287 for (JVMClusterUtil.RegionServerThread rsThread:
288 TEST_UTIL.getMiniHBaseCluster().getRegionServerThreads()) {
289 ServerName sn = rsThread.getRegionServer().getServerName();
290 if (sn.getAddress().equals(addr)) {
291 return sn;
292 }
293 }
294 return null;
295 }
296
297 public static class CPMasterObserver extends BaseMasterObserver {
298 boolean preBalanceRSGroupCalled = false;
299 boolean postBalanceRSGroupCalled = false;
300 boolean preMoveServersCalled = false;
301 boolean postMoveServersCalled = false;
302 boolean preMoveTablesCalled = false;
303 boolean postMoveTablesCalled = false;
304 boolean preAddRSGroupCalled = false;
305 boolean postAddRSGroupCalled = false;
306 boolean preRemoveRSGroupCalled = false;
307 boolean postRemoveRSGroupCalled = false;
308 boolean preRemoveServersCalled = false;
309 boolean postRemoveServersCalled = false;
310 boolean preMoveServersAndTables = false;
311 boolean postMoveServersAndTables = false;
312 boolean preRenameRSGroupCalled = false;
313 boolean postRenameRSGroupCalled = false;
314
315 public void resetFlags() {
316 preBalanceRSGroupCalled = false;
317 postBalanceRSGroupCalled = false;
318 preMoveServersCalled = false;
319 postMoveServersCalled = false;
320 preMoveTablesCalled = false;
321 postMoveTablesCalled = false;
322 preAddRSGroupCalled = false;
323 postAddRSGroupCalled = false;
324 preRemoveRSGroupCalled = false;
325 postRemoveRSGroupCalled = false;
326 preRemoveServersCalled = false;
327 postRemoveServersCalled = false;
328 preMoveServersAndTables = false;
329 postMoveServersAndTables = false;
330 preRenameRSGroupCalled = false;
331 postRenameRSGroupCalled = false;
332 }
333
334 @Override
335 public void preMoveServersAndTables(final ObserverContext<MasterCoprocessorEnvironment> ctx,
336 Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException {
337 preMoveServersAndTables = true;
338 }
339
340 @Override
341 public void postMoveServersAndTables(final ObserverContext<MasterCoprocessorEnvironment> ctx,
342 Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException {
343 postMoveServersAndTables = true;
344 }
345
346 @Override
347 public void preRemoveServers(
348 final ObserverContext<MasterCoprocessorEnvironment> ctx,
349 Set<Address> servers) throws IOException {
350 preRemoveServersCalled = true;
351 }
352
353 @Override
354 public void postRemoveServers(
355 final ObserverContext<MasterCoprocessorEnvironment> ctx,
356 Set<Address> servers) throws IOException {
357 postRemoveServersCalled = true;
358 }
359
360 @Override
361 public void preRemoveRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx,
362 String name) throws IOException {
363 preRemoveRSGroupCalled = true;
364 }
365
366 @Override
367 public void postRemoveRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx,
368 String name) throws IOException {
369 postRemoveRSGroupCalled = true;
370 }
371
372 @Override
373 public void preAddRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx,
374 String name) throws IOException {
375 preAddRSGroupCalled = true;
376 }
377
378 @Override
379 public void postAddRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx,
380 String name) throws IOException {
381 postAddRSGroupCalled = true;
382 }
383
384 @Override
385 public void preMoveTables(final ObserverContext<MasterCoprocessorEnvironment> ctx,
386 Set<TableName> tables, String targetGroup) throws IOException {
387 preMoveTablesCalled = true;
388 }
389
390 @Override
391 public void postMoveTables(final ObserverContext<MasterCoprocessorEnvironment> ctx,
392 Set<TableName> tables, String targetGroup) throws IOException {
393 postMoveTablesCalled = true;
394 }
395
396 @Override
397 public void preMoveServers(final ObserverContext<MasterCoprocessorEnvironment> ctx,
398 Set<Address> servers, String targetGroup) throws IOException {
399 preMoveServersCalled = true;
400 }
401
402 @Override
403 public void postMoveServers(final ObserverContext<MasterCoprocessorEnvironment> ctx,
404 Set<Address> servers, String targetGroup) throws IOException {
405 postMoveServersCalled = true;
406 }
407
408 @Override
409 public void preBalanceRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx,
410 String groupName) throws IOException {
411 preBalanceRSGroupCalled = true;
412 }
413
414 @Override
415 public void postBalanceRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx,
416 String groupName, boolean balancerRan) throws IOException {
417 postBalanceRSGroupCalled = true;
418 }
419
420 @Override
421 public void preRenameRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
422 String oldName, String newName) throws IOException {
423 preRenameRSGroupCalled = true;
424 }
425
426 @Override
427 public void postRenameRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx,
428 String oldName, String newName) throws IOException {
429 postRenameRSGroupCalled = true;
430 }
431 }
432 }