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