001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.rsgroup; 019 020import static org.junit.jupiter.api.Assertions.assertTrue; 021 022import java.io.IOException; 023import java.util.ArrayList; 024import java.util.EnumSet; 025import java.util.HashSet; 026import java.util.LinkedList; 027import java.util.List; 028import java.util.Map; 029import java.util.Optional; 030import java.util.Set; 031import java.util.TreeMap; 032import java.util.concurrent.ThreadLocalRandom; 033import java.util.regex.Pattern; 034import org.apache.hadoop.conf.Configuration; 035import org.apache.hadoop.hbase.ClusterMetrics; 036import org.apache.hadoop.hbase.ClusterMetrics.Option; 037import org.apache.hadoop.hbase.HBaseClusterInterface; 038import org.apache.hadoop.hbase.HBaseTestingUtil; 039import org.apache.hadoop.hbase.NamespaceDescriptor; 040import org.apache.hadoop.hbase.ServerName; 041import org.apache.hadoop.hbase.SingleProcessHBaseCluster; 042import org.apache.hadoop.hbase.TableName; 043import org.apache.hadoop.hbase.Waiter; 044import org.apache.hadoop.hbase.client.AbstractTestUpdateConfiguration; 045import org.apache.hadoop.hbase.client.Admin; 046import org.apache.hadoop.hbase.client.BalanceRequest; 047import org.apache.hadoop.hbase.client.BalanceResponse; 048import org.apache.hadoop.hbase.client.RegionInfo; 049import org.apache.hadoop.hbase.client.TableDescriptor; 050import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; 051import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor; 052import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment; 053import org.apache.hadoop.hbase.coprocessor.MasterObserver; 054import org.apache.hadoop.hbase.coprocessor.ObserverContext; 055import org.apache.hadoop.hbase.master.HMaster; 056import org.apache.hadoop.hbase.master.MasterCoprocessorHost; 057import org.apache.hadoop.hbase.master.ServerManager; 058import org.apache.hadoop.hbase.master.snapshot.SnapshotManager; 059import org.apache.hadoop.hbase.net.Address; 060import org.apache.hadoop.hbase.quotas.QuotaUtil; 061import org.junit.jupiter.api.TestInfo; 062import org.slf4j.Logger; 063import org.slf4j.LoggerFactory; 064 065import org.apache.hbase.thirdparty.com.google.common.collect.Maps; 066import org.apache.hbase.thirdparty.com.google.common.collect.Sets; 067 068public abstract class TestRSGroupsBase extends AbstractTestUpdateConfiguration { 069 protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsBase.class); 070 071 // shared 072 protected static final String GROUP_PREFIX = "Group"; 073 protected static final String TABLE_PREFIX = "Group"; 074 075 // shared, cluster type specific 076 protected static HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 077 protected static Admin ADMIN; 078 protected static HBaseClusterInterface CLUSTER; 079 protected static HMaster MASTER; 080 protected boolean INIT = false; 081 protected static CPMasterObserver OBSERVER; 082 083 public final static long WAIT_TIMEOUT = 60000; 084 public final static int NUM_SLAVES_BASE = 4; // number of slaves for the smallest cluster 085 public static int NUM_DEAD_SERVERS = 0; 086 087 protected static final class MethodName { 088 private String methodName; 089 090 public String getMethodName() { 091 return methodName; 092 } 093 094 void setMethodName(String methodName) { 095 this.methodName = methodName; 096 } 097 } 098 099 // Per test variables 100 protected final MethodName name = new MethodName(); 101 protected TableName tableName; 102 103 public static String getNameWithoutIndex(String name) { 104 return name.split("\\[")[0]; 105 } 106 107 public static void setUpTestBeforeClass() throws Exception { 108 Configuration conf = TEST_UTIL.getConfiguration(); 109 conf.setFloat("hbase.master.balancer.stochastic.tableSkewCost", 6000); 110 if (conf.get(RSGroupUtil.RS_GROUP_ENABLED) == null) { 111 RSGroupUtil.enableRSGroup(conf); 112 } 113 if (conf.get(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY) != null) { 114 conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, 115 conf.get(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY) + "," 116 + CPMasterObserver.class.getName()); 117 } else { 118 conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, CPMasterObserver.class.getName()); 119 } 120 121 conf.setInt(ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART, NUM_SLAVES_BASE); 122 conf.setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true); 123 conf.setInt("hbase.rpc.timeout", 100000); 124 125 TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE); 126 initialize(); 127 } 128 129 protected static void initialize() throws Exception { 130 ADMIN = new VerifyingRSGroupAdmin(TEST_UTIL.getConfiguration()); 131 CLUSTER = TEST_UTIL.getHBaseCluster(); 132 MASTER = TEST_UTIL.getMiniHBaseCluster().getMaster(); 133 134 // wait for balancer to come online 135 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() { 136 @Override 137 public boolean evaluate() throws Exception { 138 return MASTER.isInitialized() 139 && ((RSGroupBasedLoadBalancer) MASTER.getLoadBalancer()).isOnline(); 140 } 141 }); 142 ADMIN.balancerSwitch(false, true); 143 MasterCoprocessorHost host = MASTER.getMasterCoprocessorHost(); 144 OBSERVER = (CPMasterObserver) host.findCoprocessor(CPMasterObserver.class.getName()); 145 } 146 147 public static void tearDownAfterClass() throws Exception { 148 TEST_UTIL.shutdownMiniCluster(); 149 } 150 151 public void setUpBeforeMethod(TestInfo testInfo) throws Exception { 152 name.setMethodName(testInfo.getTestMethod().get().getName()); 153 LOG.info(name.getMethodName()); 154 tableName = TableName.valueOf(TABLE_PREFIX + "_" + name.getMethodName().split("\\[")[0]); 155 if (!INIT) { 156 INIT = true; 157 tearDownAfterMethod(); 158 } 159 OBSERVER.resetFlags(); 160 } 161 162 public void tearDownAfterMethod() throws Exception { 163 deleteTableIfNecessary(); 164 deleteNamespaceIfNecessary(); 165 deleteGroups(); 166 167 for (ServerName sn : ADMIN.listDecommissionedRegionServers()) { 168 ADMIN.recommissionRegionServer(sn, null); 169 } 170 assertTrue(ADMIN.listDecommissionedRegionServers().isEmpty()); 171 172 int missing = NUM_SLAVES_BASE - getNumServers(); 173 LOG.info("Restoring servers: " + missing); 174 for (int i = 0; i < missing; i++) { 175 ((SingleProcessHBaseCluster) CLUSTER).startRegionServer(); 176 } 177 ADMIN.addRSGroup("master"); 178 ServerName masterServerName = ((SingleProcessHBaseCluster) CLUSTER).getMaster().getServerName(); 179 try { 180 ADMIN.moveServersToRSGroup(Sets.newHashSet(masterServerName.getAddress()), "master"); 181 } catch (Exception ex) { 182 LOG.warn("Got this on setup, FYI", ex); 183 } 184 assertTrue(OBSERVER.preMoveServersCalled); 185 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() { 186 @Override 187 public boolean evaluate() throws Exception { 188 LOG.info("Waiting for cleanup to finish " + ADMIN.listRSGroups()); 189 // Might be greater since moving servers back to default 190 // is after starting a server 191 192 return ADMIN.getRSGroup(RSGroupInfo.DEFAULT_GROUP).getServers().size() == NUM_SLAVES_BASE; 193 } 194 }); 195 } 196 197 protected final RSGroupInfo addGroup(String groupName, int serverCount) 198 throws IOException, InterruptedException { 199 RSGroupInfo defaultInfo = ADMIN.getRSGroup(RSGroupInfo.DEFAULT_GROUP); 200 ADMIN.addRSGroup(groupName); 201 Set<Address> set = new HashSet<>(); 202 for (Address server : defaultInfo.getServers()) { 203 if (set.size() == serverCount) { 204 break; 205 } 206 set.add(server); 207 } 208 ADMIN.moveServersToRSGroup(set, groupName); 209 RSGroupInfo result = ADMIN.getRSGroup(groupName); 210 return result; 211 } 212 213 protected final void removeGroup(String groupName) throws IOException { 214 Set<TableName> tables = new HashSet<>(); 215 for (TableDescriptor td : ADMIN.listTableDescriptors(true)) { 216 RSGroupInfo groupInfo = ADMIN.getRSGroup(td.getTableName()); 217 if (groupInfo != null && groupInfo.getName().equals(groupName)) { 218 tables.add(td.getTableName()); 219 } 220 } 221 ADMIN.setRSGroup(tables, RSGroupInfo.DEFAULT_GROUP); 222 for (NamespaceDescriptor nd : ADMIN.listNamespaceDescriptors()) { 223 if (groupName.equals(nd.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP))) { 224 nd.removeConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP); 225 ADMIN.modifyNamespace(nd); 226 } 227 } 228 RSGroupInfo groupInfo = ADMIN.getRSGroup(groupName); 229 ADMIN.moveServersToRSGroup(groupInfo.getServers(), RSGroupInfo.DEFAULT_GROUP); 230 ADMIN.removeRSGroup(groupName); 231 } 232 233 protected final void deleteTableIfNecessary() throws IOException { 234 for (TableDescriptor desc : TEST_UTIL.getAdmin() 235 .listTableDescriptors(Pattern.compile(TABLE_PREFIX + ".*"))) { 236 TEST_UTIL.deleteTable(desc.getTableName()); 237 } 238 } 239 240 protected final void deleteNamespaceIfNecessary() throws IOException { 241 for (NamespaceDescriptor desc : TEST_UTIL.getAdmin().listNamespaceDescriptors()) { 242 if (desc.getName().startsWith(TABLE_PREFIX)) { 243 ADMIN.deleteNamespace(desc.getName()); 244 } 245 } 246 } 247 248 protected final void deleteGroups() throws IOException { 249 for (RSGroupInfo groupInfo : ADMIN.listRSGroups()) { 250 if (!groupInfo.getName().equals(RSGroupInfo.DEFAULT_GROUP)) { 251 removeGroup(groupInfo.getName()); 252 } 253 } 254 } 255 256 protected Map<TableName, List<String>> getTableRegionMap() throws IOException { 257 Map<TableName, List<String>> map = Maps.newTreeMap(); 258 Map<TableName, Map<ServerName, List<String>>> tableServerRegionMap = getTableServerRegionMap(); 259 for (TableName tableName : tableServerRegionMap.keySet()) { 260 if (!map.containsKey(tableName)) { 261 map.put(tableName, new LinkedList<>()); 262 } 263 for (List<String> subset : tableServerRegionMap.get(tableName).values()) { 264 map.get(tableName).addAll(subset); 265 } 266 } 267 return map; 268 } 269 270 protected Map<TableName, Map<ServerName, List<String>>> getTableServerRegionMap() 271 throws IOException { 272 Map<TableName, Map<ServerName, List<String>>> map = Maps.newTreeMap(); 273 Admin admin = TEST_UTIL.getAdmin(); 274 ClusterMetrics metrics = 275 admin.getClusterMetrics(EnumSet.of(ClusterMetrics.Option.SERVERS_NAME)); 276 for (ServerName serverName : metrics.getServersName()) { 277 for (RegionInfo region : admin.getRegions(serverName)) { 278 TableName tableName = region.getTable(); 279 map.computeIfAbsent(tableName, k -> new TreeMap<>()) 280 .computeIfAbsent(serverName, k -> new ArrayList<>()).add(region.getRegionNameAsString()); 281 } 282 } 283 return map; 284 } 285 286 // return the real number of region servers, excluding the master embedded region server in 2.0+ 287 protected int getNumServers() throws IOException { 288 ClusterMetrics status = ADMIN.getClusterMetrics(EnumSet.of(Option.MASTER, Option.LIVE_SERVERS)); 289 ServerName masterName = status.getMasterName(); 290 int count = 0; 291 for (ServerName sn : status.getLiveServerMetrics().keySet()) { 292 if (!sn.equals(masterName)) { 293 count++; 294 } 295 } 296 return count; 297 } 298 299 protected final String getGroupName(String baseName) { 300 return GROUP_PREFIX + "_" + getNameWithoutIndex(baseName) + "_" 301 + ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE); 302 } 303 304 /** 305 * The server name in group does not contain the start code, this method will find out the start 306 * code and construct the ServerName object. 307 */ 308 protected final ServerName getServerName(Address addr) { 309 return TEST_UTIL.getMiniHBaseCluster().getRegionServerThreads().stream() 310 .map(t -> t.getRegionServer().getServerName()).filter(sn -> sn.getAddress().equals(addr)) 311 .findFirst().get(); 312 } 313 314 protected final void toggleQuotaCheckAndRestartMiniCluster(boolean enable) throws Exception { 315 TEST_UTIL.shutdownMiniCluster(); 316 TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, enable); 317 TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE); 318 TEST_UTIL.getConfiguration().setInt(ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART, 319 NUM_SLAVES_BASE); 320 TEST_UTIL.getConfiguration().setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true); 321 initialize(); 322 } 323 324 public static class CPMasterObserver implements MasterCoprocessor, MasterObserver { 325 boolean preBalanceRSGroupCalled = false; 326 boolean postBalanceRSGroupCalled = false; 327 boolean preMoveServersCalled = false; 328 boolean postMoveServersCalled = false; 329 boolean preMoveTablesCalled = false; 330 boolean postMoveTablesCalled = false; 331 boolean preAddRSGroupCalled = false; 332 boolean postAddRSGroupCalled = false; 333 boolean preRemoveRSGroupCalled = false; 334 boolean postRemoveRSGroupCalled = false; 335 boolean preRemoveServersCalled = false; 336 boolean postRemoveServersCalled = false; 337 boolean preMoveServersAndTables = false; 338 boolean postMoveServersAndTables = false; 339 boolean preGetRSGroupInfoCalled = false; 340 boolean postGetRSGroupInfoCalled = false; 341 boolean preGetRSGroupInfoOfTableCalled = false; 342 boolean postGetRSGroupInfoOfTableCalled = false; 343 boolean preListRSGroupsCalled = false; 344 boolean postListRSGroupsCalled = false; 345 boolean preGetRSGroupInfoOfServerCalled = false; 346 boolean postGetRSGroupInfoOfServerCalled = false; 347 boolean preSetRSGroupForTablesCalled = false; 348 boolean postSetRSGroupForTablesCalled = false; 349 boolean preListTablesInRSGroupCalled = false; 350 boolean postListTablesInRSGroupCalled = false; 351 boolean preGetConfiguredNamespacesAndTablesInRSGroupCalled = false; 352 boolean postGetConfiguredNamespacesAndTablesInRSGroupCalled = false; 353 boolean preRenameRSGroup = false; 354 boolean postRenameRSGroup = false; 355 boolean preUpdateRSGroupConfig = false; 356 boolean postUpdateRSGroupConfig = false; 357 358 public void resetFlags() { 359 preBalanceRSGroupCalled = false; 360 postBalanceRSGroupCalled = false; 361 preMoveServersCalled = false; 362 postMoveServersCalled = false; 363 preMoveTablesCalled = false; 364 postMoveTablesCalled = false; 365 preAddRSGroupCalled = false; 366 postAddRSGroupCalled = false; 367 preRemoveRSGroupCalled = false; 368 postRemoveRSGroupCalled = false; 369 preRemoveServersCalled = false; 370 postRemoveServersCalled = false; 371 preMoveServersAndTables = false; 372 postMoveServersAndTables = false; 373 preGetRSGroupInfoCalled = false; 374 postGetRSGroupInfoCalled = false; 375 preGetRSGroupInfoOfTableCalled = false; 376 postGetRSGroupInfoOfTableCalled = false; 377 preListRSGroupsCalled = false; 378 postListRSGroupsCalled = false; 379 preGetRSGroupInfoOfServerCalled = false; 380 postGetRSGroupInfoOfServerCalled = false; 381 preSetRSGroupForTablesCalled = false; 382 postSetRSGroupForTablesCalled = false; 383 preListTablesInRSGroupCalled = false; 384 postListTablesInRSGroupCalled = false; 385 preGetConfiguredNamespacesAndTablesInRSGroupCalled = false; 386 postGetConfiguredNamespacesAndTablesInRSGroupCalled = false; 387 preRenameRSGroup = false; 388 postRenameRSGroup = false; 389 preUpdateRSGroupConfig = false; 390 postUpdateRSGroupConfig = false; 391 } 392 393 @Override 394 public Optional<MasterObserver> getMasterObserver() { 395 return Optional.of(this); 396 } 397 398 @Override 399 public void preMoveServersAndTables(final ObserverContext<MasterCoprocessorEnvironment> ctx, 400 Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException { 401 preMoveServersAndTables = true; 402 } 403 404 @Override 405 public void postMoveServersAndTables(final ObserverContext<MasterCoprocessorEnvironment> ctx, 406 Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException { 407 postMoveServersAndTables = true; 408 } 409 410 @Override 411 public void preRemoveServers(final ObserverContext<MasterCoprocessorEnvironment> ctx, 412 Set<Address> servers) throws IOException { 413 preRemoveServersCalled = true; 414 } 415 416 @Override 417 public void postRemoveServers(final ObserverContext<MasterCoprocessorEnvironment> ctx, 418 Set<Address> servers) throws IOException { 419 postRemoveServersCalled = true; 420 } 421 422 @Override 423 public void preRemoveRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx, 424 String name) throws IOException { 425 preRemoveRSGroupCalled = true; 426 } 427 428 @Override 429 public void postRemoveRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx, 430 String name) throws IOException { 431 postRemoveRSGroupCalled = true; 432 } 433 434 @Override 435 public void preAddRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx, String name) 436 throws IOException { 437 preAddRSGroupCalled = true; 438 } 439 440 @Override 441 public void postAddRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx, String name) 442 throws IOException { 443 postAddRSGroupCalled = true; 444 } 445 446 @Override 447 public void preMoveTables(final ObserverContext<MasterCoprocessorEnvironment> ctx, 448 Set<TableName> tables, String targetGroup) throws IOException { 449 preMoveTablesCalled = true; 450 } 451 452 @Override 453 public void postMoveTables(final ObserverContext<MasterCoprocessorEnvironment> ctx, 454 Set<TableName> tables, String targetGroup) throws IOException { 455 postMoveTablesCalled = true; 456 } 457 458 @Override 459 public void preMoveServers(final ObserverContext<MasterCoprocessorEnvironment> ctx, 460 Set<Address> servers, String targetGroup) throws IOException { 461 preMoveServersCalled = true; 462 } 463 464 @Override 465 public void postMoveServers(final ObserverContext<MasterCoprocessorEnvironment> ctx, 466 Set<Address> servers, String targetGroup) throws IOException { 467 postMoveServersCalled = true; 468 } 469 470 @Override 471 public void preBalanceRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx, 472 String groupName, BalanceRequest request) throws IOException { 473 preBalanceRSGroupCalled = true; 474 } 475 476 @Override 477 public void postBalanceRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx, 478 String groupName, BalanceRequest request, BalanceResponse response) throws IOException { 479 postBalanceRSGroupCalled = true; 480 } 481 482 @Override 483 public void preGetRSGroupInfo(final ObserverContext<MasterCoprocessorEnvironment> ctx, 484 final String groupName) throws IOException { 485 preGetRSGroupInfoCalled = true; 486 } 487 488 @Override 489 public void postGetRSGroupInfo(final ObserverContext<MasterCoprocessorEnvironment> ctx, 490 final String groupName) throws IOException { 491 postGetRSGroupInfoCalled = true; 492 } 493 494 @Override 495 public void preGetRSGroupInfoOfTable(final ObserverContext<MasterCoprocessorEnvironment> ctx, 496 final TableName tableName) throws IOException { 497 preGetRSGroupInfoOfTableCalled = true; 498 } 499 500 @Override 501 public void postGetRSGroupInfoOfTable(final ObserverContext<MasterCoprocessorEnvironment> ctx, 502 final TableName tableName) throws IOException { 503 postGetRSGroupInfoOfTableCalled = true; 504 } 505 506 @Override 507 public void preListRSGroups(final ObserverContext<MasterCoprocessorEnvironment> ctx) 508 throws IOException { 509 preListRSGroupsCalled = true; 510 } 511 512 @Override 513 public void postListRSGroups(final ObserverContext<MasterCoprocessorEnvironment> ctx) 514 throws IOException { 515 postListRSGroupsCalled = true; 516 } 517 518 @Override 519 public void preGetRSGroupInfoOfServer(final ObserverContext<MasterCoprocessorEnvironment> ctx, 520 final Address server) throws IOException { 521 preGetRSGroupInfoOfServerCalled = true; 522 } 523 524 @Override 525 public void postGetRSGroupInfoOfServer(final ObserverContext<MasterCoprocessorEnvironment> ctx, 526 final Address server) throws IOException { 527 postGetRSGroupInfoOfServerCalled = true; 528 } 529 530 @Override 531 public void preListTablesInRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx, 532 String groupName) throws IOException { 533 preListTablesInRSGroupCalled = true; 534 } 535 536 @Override 537 public void postListTablesInRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx, 538 String groupName) throws IOException { 539 postListTablesInRSGroupCalled = true; 540 } 541 542 @Override 543 public void preGetConfiguredNamespacesAndTablesInRSGroup( 544 ObserverContext<MasterCoprocessorEnvironment> ctx, String groupName) throws IOException { 545 preGetConfiguredNamespacesAndTablesInRSGroupCalled = true; 546 } 547 548 @Override 549 public void postGetConfiguredNamespacesAndTablesInRSGroup( 550 ObserverContext<MasterCoprocessorEnvironment> ctx, String groupName) throws IOException { 551 postGetConfiguredNamespacesAndTablesInRSGroupCalled = true; 552 } 553 554 @Override 555 public void preRenameRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx, String oldName, 556 String newName) throws IOException { 557 preRenameRSGroup = true; 558 } 559 560 @Override 561 public void postRenameRSGroup(ObserverContext<MasterCoprocessorEnvironment> ctx, String oldName, 562 String newName) throws IOException { 563 postRenameRSGroup = true; 564 } 565 566 @Override 567 public void preUpdateRSGroupConfig(final ObserverContext<MasterCoprocessorEnvironment> ctx, 568 final String groupName, final Map<String, String> configuration) throws IOException { 569 preUpdateRSGroupConfig = true; 570 } 571 572 @Override 573 public void postUpdateRSGroupConfig(final ObserverContext<MasterCoprocessorEnvironment> ctx, 574 final String groupName, final Map<String, String> configuration) throws IOException { 575 postUpdateRSGroupConfig = true; 576 } 577 } 578}