HBASE-15132 Master region merge RPC should authorize user request
This commit is contained in:
parent
772f30fe2a
commit
6ed3c759d0
|
@ -53,6 +53,16 @@ public abstract class BaseMasterAndRegionObserver extends BaseRegionObserver
|
|||
HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
HRegionInfo regionA, HRegionInfo regionB) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
HRegionInfo regionA, HRegionInfo regionB) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCreateTableHandler(
|
||||
final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
|
|
|
@ -64,6 +64,16 @@ public class BaseMasterObserver implements MasterObserver {
|
|||
HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
HRegionInfo regionA, HRegionInfo regionB) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
HRegionInfo regionA, HRegionInfo regionB) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDeleteTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
TableName tableName) throws IOException {
|
||||
|
|
|
@ -1217,4 +1217,25 @@ public interface MasterObserver extends Coprocessor {
|
|||
*/
|
||||
void postSetNamespaceQuota(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
final String namespace, final Quotas quotas) throws IOException;
|
||||
|
||||
/**
|
||||
* Called before dispatching region merge request.
|
||||
* It can't bypass the default action, e.g., ctx.bypass() won't have effect.
|
||||
* @param ctx coprocessor environment
|
||||
* @param regionA first region to be merged
|
||||
* @param regionB second region to be merged
|
||||
* @throws IOException if an error occurred on the coprocessor
|
||||
*/
|
||||
public void preDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
HRegionInfo regionA, HRegionInfo regionB) throws IOException;
|
||||
|
||||
/**
|
||||
* called after dispatching the region merge request.
|
||||
* @param c coprocessor environment
|
||||
* @param regionA first region to be merged
|
||||
* @param regionB second region to be merged
|
||||
* @throws IOException if an error occurred on the coprocessor
|
||||
*/
|
||||
void postDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> c,
|
||||
final HRegionInfo regionA, final HRegionInfo regionB) throws IOException;
|
||||
}
|
||||
|
|
|
@ -729,6 +729,28 @@ public class MasterCoprocessorHost
|
|||
});
|
||||
}
|
||||
|
||||
public void preDispatchMerge(final HRegionInfo regionInfoA, final HRegionInfo regionInfoB)
|
||||
throws IOException {
|
||||
execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
|
||||
@Override
|
||||
public void call(MasterObserver oserver, ObserverContext<MasterCoprocessorEnvironment> ctx)
|
||||
throws IOException {
|
||||
oserver.preDispatchMerge(ctx, regionInfoA, regionInfoB);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void postDispatchMerge(final HRegionInfo regionInfoA, final HRegionInfo regionInfoB)
|
||||
throws IOException {
|
||||
execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
|
||||
@Override
|
||||
public void call(MasterObserver oserver, ObserverContext<MasterCoprocessorEnvironment> ctx)
|
||||
throws IOException {
|
||||
oserver.postDispatchMerge(ctx, regionInfoA, regionInfoB);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean preBalance() throws IOException {
|
||||
return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
|
||||
@Override
|
||||
|
|
|
@ -514,8 +514,8 @@ public class MasterRpcServices extends RSRpcServices
|
|||
"Unable to merge regions not online " + regionStateA + ", " + regionStateB));
|
||||
}
|
||||
|
||||
HRegionInfo regionInfoA = regionStateA.getRegion();
|
||||
HRegionInfo regionInfoB = regionStateB.getRegion();
|
||||
final HRegionInfo regionInfoA = regionStateA.getRegion();
|
||||
final HRegionInfo regionInfoB = regionStateB.getRegion();
|
||||
if (regionInfoA.getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID ||
|
||||
regionInfoB.getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID) {
|
||||
throw new ServiceException(new MergeRegionException("Can't merge non-default replicas"));
|
||||
|
@ -524,6 +524,11 @@ public class MasterRpcServices extends RSRpcServices
|
|||
throw new ServiceException(new MergeRegionException(
|
||||
"Unable to merge a region to itself " + regionInfoA + ", " + regionInfoB));
|
||||
}
|
||||
try {
|
||||
master.cpHost.preDispatchMerge(regionInfoA, regionInfoB);
|
||||
} catch (IOException ioe) {
|
||||
throw new ServiceException(ioe);
|
||||
}
|
||||
|
||||
if (!forcible && !HRegionInfo.areAdjacent(regionInfoA, regionInfoB)) {
|
||||
throw new ServiceException(new MergeRegionException(
|
||||
|
@ -535,6 +540,7 @@ public class MasterRpcServices extends RSRpcServices
|
|||
|
||||
try {
|
||||
master.dispatchMergingRegions(regionInfoA, regionInfoB, forcible);
|
||||
master.cpHost.postDispatchMerge(regionInfoA, regionInfoB);
|
||||
} catch (IOException ioe) {
|
||||
throw new ServiceException(ioe);
|
||||
}
|
||||
|
|
|
@ -2529,6 +2529,13 @@ public class AccessController extends BaseMasterAndRegionObserver
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
HRegionInfo regionA, HRegionInfo regionB) throws IOException {
|
||||
requirePermission("mergeRegions", regionA.getTable(), null, null,
|
||||
Action.ADMIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preMerge(ObserverContext<RegionServerCoprocessorEnvironment> ctx, Region regionA,
|
||||
Region regionB) throws IOException {
|
||||
|
|
|
@ -25,6 +25,7 @@ import static org.junit.Assert.assertNull;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
@ -44,6 +45,9 @@ import org.apache.hadoop.hbase.ProcedureInfo;
|
|||
import org.apache.hadoop.hbase.ServerName;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.client.Admin;
|
||||
import org.apache.hadoop.hbase.client.Connection;
|
||||
import org.apache.hadoop.hbase.client.ConnectionFactory;
|
||||
import org.apache.hadoop.hbase.client.HTable;
|
||||
import org.apache.hadoop.hbase.client.RegionLocator;
|
||||
import org.apache.hadoop.hbase.client.Table;
|
||||
import org.apache.hadoop.hbase.master.AssignmentManager;
|
||||
|
@ -167,6 +171,8 @@ public class TestMasterObserver {
|
|||
private boolean postGetTableDescriptorsCalled;
|
||||
private boolean postGetTableNamesCalled;
|
||||
private boolean preGetTableNamesCalled;
|
||||
private boolean preDispatchMergeCalled;
|
||||
private boolean postDispatchMergeCalled;
|
||||
|
||||
public void enableBypass(boolean bypass) {
|
||||
this.bypass = bypass;
|
||||
|
@ -249,6 +255,24 @@ public class TestMasterObserver {
|
|||
postGetTableDescriptorsCalled = false;
|
||||
postGetTableNamesCalled = false;
|
||||
preGetTableNamesCalled = false;
|
||||
preDispatchMergeCalled = false;
|
||||
postDispatchMergeCalled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
HRegionInfo regionA, HRegionInfo regionB) throws IOException {
|
||||
preDispatchMergeCalled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDispatchMerge(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
HRegionInfo regionA, HRegionInfo regionB) throws IOException {
|
||||
postDispatchMergeCalled = true;
|
||||
}
|
||||
|
||||
public boolean wasDispatchMergeCalled() {
|
||||
return preDispatchMergeCalled && postDispatchMergeCalled;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1347,10 +1371,12 @@ public class TestMasterObserver {
|
|||
// create a table
|
||||
HTableDescriptor htd = new HTableDescriptor(tableName);
|
||||
htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
|
||||
Admin admin = UTIL.getHBaseAdmin();
|
||||
|
||||
try(Connection connection = ConnectionFactory.createConnection(UTIL.getConfiguration());
|
||||
Admin admin = connection.getAdmin()) {
|
||||
tableCreationLatch = new CountDownLatch(1);
|
||||
admin.createTable(htd);
|
||||
admin.createTable(htd, Arrays.copyOfRange(HBaseTestingUtility.KEYS,
|
||||
1, HBaseTestingUtility.KEYS.length));
|
||||
|
||||
// preCreateTable can't bypass default action.
|
||||
assertTrue("Test table should be created", cp.wasCreateTableCalled());
|
||||
tableCreationLatch.await();
|
||||
|
@ -1359,6 +1385,14 @@ public class TestMasterObserver {
|
|||
assertTrue("Table create handler should be called.",
|
||||
cp.wasCreateTableHandlerCalled());
|
||||
|
||||
RegionLocator regionLocator = connection.getRegionLocator(htd.getTableName());
|
||||
List<HRegionLocation> regions = regionLocator.getAllRegionLocations();
|
||||
|
||||
admin.mergeRegions(regions.get(0).getRegionInfo().getEncodedNameAsBytes(),
|
||||
regions.get(1).getRegionInfo().getEncodedNameAsBytes(), true);
|
||||
assertTrue("Coprocessor should have been called on region merge",
|
||||
cp.wasDispatchMergeCalled());
|
||||
|
||||
tableCreationLatch = new CountDownLatch(1);
|
||||
admin.disableTable(tableName);
|
||||
assertTrue(admin.isTableDisabled(tableName));
|
||||
|
@ -1497,6 +1531,7 @@ public class TestMasterObserver {
|
|||
assertTrue("Delete table handler should be called.",
|
||||
cp.wasDeleteTableHandlerCalled());
|
||||
}
|
||||
}
|
||||
|
||||
@Test (timeout=180000)
|
||||
public void testSnapshotOperations() throws Exception {
|
||||
|
|
Loading…
Reference in New Issue