From 4b89ee24f33d6dc268a6910ea497e9d0a98a14a9 Mon Sep 17 00:00:00 2001 From: XinSun Date: Wed, 24 Jun 2020 18:46:09 +0800 Subject: [PATCH] HBASE-24431 RSGroupInfo add configuration map to store something extra (#1782) Signed-off-by: Duo Zhang Signed-off-by: Nick Dimiduk Signed-off-by: Guanghao Zhang --- .../org/apache/hadoop/hbase/client/Admin.java | 8 ++ .../hbase/client/AdminOverAsyncAdmin.java | 6 ++ .../hadoop/hbase/client/AsyncAdmin.java | 8 ++ .../hadoop/hbase/client/AsyncHBaseAdmin.java | 6 ++ .../hbase/client/RawAsyncHBaseAdmin.java | 21 ++++ .../hbase/shaded/protobuf/ProtobufUtil.java | 16 ++- .../hadoop/hbase/rsgroup/RSGroupInfo.java | 32 ++++++ .../main/protobuf/server/master/Master.proto | 3 + .../protobuf/server/rsgroup/RSGroup.proto | 1 + .../server/rsgroup/RSGroupAdmin.proto | 8 ++ .../hbase/coprocessor/MasterObserver.java | 21 ++++ .../hbase/master/MasterCoprocessorHost.java | 21 ++++ .../hbase/master/MasterRpcServices.java | 26 +++++ .../rsgroup/DisabledRSGroupInfoManager.java | 6 ++ .../hbase/rsgroup/RSGroupInfoManager.java | 9 ++ .../hbase/rsgroup/RSGroupInfoManagerImpl.java | 8 ++ .../hbase/rsgroup/TestRSGroupConfig.java | 99 +++++++++++++++++++ .../hbase/rsgroup/VerifyingRSGroupAdmin.java | 7 ++ .../src/main/ruby/hbase/rsgroup_admin.rb | 37 +++++++ hbase-shell/src/main/ruby/shell.rb | 2 + .../shell/commands/alter_rsgroup_config.rb | 38 +++++++ .../shell/commands/show_rsgroup_config.rb | 43 ++++++++ .../src/test/ruby/shell/rsgroup_shell_test.rb | 14 +++ .../hbase/thrift2/client/ThriftAdmin.java | 6 ++ 24 files changed, 441 insertions(+), 5 deletions(-) create mode 100644 hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupConfig.java create mode 100644 hbase-shell/src/main/ruby/shell/commands/alter_rsgroup_config.rb create mode 100644 hbase-shell/src/main/ruby/shell/commands/show_rsgroup_config.rb diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java index c82b1015951..520a8fc0604 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java @@ -2428,4 +2428,12 @@ public interface Admin extends Abortable, Closeable { */ void renameRSGroup(String oldName, String newName) throws IOException; + /** + * Update RSGroup configuration + * @param groupName the group name + * @param configuration new configuration of the group name to be set + * @throws IOException if a remote or network exception occurs + */ + void updateRSGroupConfig(String groupName, Map configuration) throws IOException; + } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AdminOverAsyncAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AdminOverAsyncAdmin.java index 8f2d2888383..50dce8984f1 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AdminOverAsyncAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AdminOverAsyncAdmin.java @@ -1041,4 +1041,10 @@ class AdminOverAsyncAdmin implements Admin { public void renameRSGroup(String oldName, String newName) throws IOException { get(admin.renameRSGroup(oldName, newName)); } + + @Override + public void updateRSGroupConfig(String groupName, Map configuration) + throws IOException { + get(admin.updateRSGroupConfig(groupName, configuration)); + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java index c6ef55c97a2..10f2b8a33f2 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java @@ -1639,4 +1639,12 @@ public interface AsyncAdmin { * @throws IOException if a remote or network exception occurs */ CompletableFuture renameRSGroup(String oldName, String newName); + + /** + * Update RSGroup configuration + * @param groupName the group name + * @param configuration new configuration of the group name to be set + * @throws IOException if a remote or network exception occurs + */ + CompletableFuture updateRSGroupConfig(String groupName, Map configuration); } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java index 8b29ac97c4d..704359fbabc 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java @@ -918,4 +918,10 @@ class AsyncHBaseAdmin implements AsyncAdmin { public CompletableFuture renameRSGroup(String oldName, String newName) { return wrap(rawAdmin.renameRSGroup(oldName, newName)); } + + @Override + public CompletableFuture + updateRSGroupConfig(String groupName, Map configuration) { + return wrap(rawAdmin.updateRSGroupConfig(groupName, configuration)); + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java index 184bbe35038..8cc911ac58e 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java @@ -145,6 +145,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.StopServerR import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.UpdateConfigurationRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.UpdateConfigurationResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; +import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.NameStringPair; import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ProcedureDescription; import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType; import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.TableSchema; @@ -311,6 +312,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.Remo import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveServersResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RenameRSGroupRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RenameRSGroupResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.UpdateRSGroupConfigRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.UpdateRSGroupConfigResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.AddReplicationPeerRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.AddReplicationPeerResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.DisableReplicationPeerRequest; @@ -4164,4 +4167,22 @@ class RawAsyncHBaseAdmin implements AsyncAdmin { ) ).call(); } + + @Override + public CompletableFuture + updateRSGroupConfig(String groupName, Map configuration) { + UpdateRSGroupConfigRequest.Builder request = UpdateRSGroupConfigRequest.newBuilder() + .setGroupName(groupName); + if (configuration != null) { + configuration.entrySet().forEach(e -> + request.addConfiguration(NameStringPair.newBuilder().setName(e.getKey()) + .setValue(e.getValue()).build())); + } + return this. newMasterCaller() + .action(((controller, stub) -> + this. call( + controller, stub, request.build(), + (s, c, req, done) -> s.updateRSGroupConfig(c, req, done), resp -> null)) + ).call(); + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java index 4de8778cf12..4cdbfbc510c 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java @@ -3514,14 +3514,16 @@ public final class ProtobufUtil { } public static RSGroupInfo toGroupInfo(RSGroupProtos.RSGroupInfo proto) { - RSGroupInfo RSGroupInfo = new RSGroupInfo(proto.getName()); + RSGroupInfo rsGroupInfo = new RSGroupInfo(proto.getName()); for (HBaseProtos.ServerName el : proto.getServersList()) { - RSGroupInfo.addServer(Address.fromParts(el.getHostName(), el.getPort())); + rsGroupInfo.addServer(Address.fromParts(el.getHostName(), el.getPort())); } for (HBaseProtos.TableName pTableName : proto.getTablesList()) { - RSGroupInfo.addTable(ProtobufUtil.toTableName(pTableName)); + rsGroupInfo.addTable(ProtobufUtil.toTableName(pTableName)); } - return RSGroupInfo; + proto.getConfigurationList().forEach(pair -> + rsGroupInfo.setConfiguration(pair.getName(), pair.getValue())); + return rsGroupInfo; } public static RSGroupProtos.RSGroupInfo toProtoGroupInfo(RSGroupInfo pojo) { @@ -3534,7 +3536,11 @@ public final class ProtobufUtil { hostports.add(HBaseProtos.ServerName.newBuilder().setHostName(el.getHostname()) .setPort(el.getPort()).build()); } + List configuration = pojo.getConfiguration().entrySet() + .stream().map(entry -> NameStringPair.newBuilder() + .setName(entry.getKey()).setValue(entry.getValue()).build()) + .collect(Collectors.toList()); return RSGroupProtos.RSGroupInfo.newBuilder().setName(pojo.getName()).addAllServers(hostports) - .addAllTables(tables).build(); + .addAllTables(tables).addAllConfiguration(configuration).build(); } } diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfo.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfo.java index 5d70d1b3022..616e6f75d5e 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfo.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfo.java @@ -19,6 +19,10 @@ package org.apache.hadoop.hbase.rsgroup; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; import java.util.SortedSet; import java.util.TreeSet; import org.apache.hadoop.hbase.TableName; @@ -46,6 +50,8 @@ public class RSGroupInfo { @Deprecated private final SortedSet tables; + private final Map configuration; + public RSGroupInfo(String name) { this(name, new TreeSet
(), new TreeSet()); } @@ -54,6 +60,7 @@ public class RSGroupInfo { this.name = name; this.servers = servers == null ? new TreeSet<>() : new TreeSet<>(servers); this.tables = new TreeSet<>(); + configuration = new HashMap<>(); } /** @@ -65,6 +72,7 @@ public class RSGroupInfo { this.name = name; this.servers = (servers == null) ? new TreeSet<>() : new TreeSet<>(servers); this.tables = (tables == null) ? new TreeSet<>() : new TreeSet<>(tables); + configuration = new HashMap<>(); } public RSGroupInfo(RSGroupInfo src) { @@ -114,6 +122,30 @@ public class RSGroupInfo { return servers.remove(hostPort); } + /** + * Getter for fetching an unmodifiable {@link #configuration} map. + */ + public Map getConfiguration() { + // shallow pointer copy + return Collections.unmodifiableMap(configuration); + } + + /** + * Setter for storing a configuration setting in {@link #configuration} map. + * @param key Config key. + * @param value String value. + */ + public void setConfiguration(String key, String value) { + configuration.put(key, Objects.requireNonNull(value)); + } + + /** + * Remove a config setting represented by the key from the {@link #configuration} map + */ + public void removeConfiguration(final String key) { + configuration.remove(key); + } + /** * Get set of tables that are members of the group. * @deprecated Since 3.0.0, will be removed in 4.0.0. The rsgroup information will be stored in diff --git a/hbase-protocol-shaded/src/main/protobuf/server/master/Master.proto b/hbase-protocol-shaded/src/main/protobuf/server/master/Master.proto index 6c68c806c93..286c96f688f 100644 --- a/hbase-protocol-shaded/src/main/protobuf/server/master/Master.proto +++ b/hbase-protocol-shaded/src/main/protobuf/server/master/Master.proto @@ -1117,6 +1117,9 @@ service MasterService { rpc RenameRSGroup(RenameRSGroupRequest) returns (RenameRSGroupResponse); + + rpc UpdateRSGroupConfig(UpdateRSGroupConfigRequest) + returns (UpdateRSGroupConfigResponse); } // HBCK Service definitions. diff --git a/hbase-protocol-shaded/src/main/protobuf/server/rsgroup/RSGroup.proto b/hbase-protocol-shaded/src/main/protobuf/server/rsgroup/RSGroup.proto index bfa54c11003..2a46cb03c86 100644 --- a/hbase-protocol-shaded/src/main/protobuf/server/rsgroup/RSGroup.proto +++ b/hbase-protocol-shaded/src/main/protobuf/server/rsgroup/RSGroup.proto @@ -30,4 +30,5 @@ message RSGroupInfo { required string name = 1; repeated ServerName servers = 4; repeated TableName tables = 3; + repeated NameStringPair configuration = 5; } diff --git a/hbase-protocol-shaded/src/main/protobuf/server/rsgroup/RSGroupAdmin.proto b/hbase-protocol-shaded/src/main/protobuf/server/rsgroup/RSGroupAdmin.proto index 860c5aa9c5c..9f38d2bc933 100644 --- a/hbase-protocol-shaded/src/main/protobuf/server/rsgroup/RSGroupAdmin.proto +++ b/hbase-protocol-shaded/src/main/protobuf/server/rsgroup/RSGroupAdmin.proto @@ -147,6 +147,14 @@ message RenameRSGroupRequest { message RenameRSGroupResponse { } +message UpdateRSGroupConfigRequest { + required string group_name = 1; + repeated NameStringPair configuration = 2; +} + +message UpdateRSGroupConfigResponse { +} + service RSGroupAdminService { rpc GetRSGroupInfo(GetRSGroupInfoRequest) returns (GetRSGroupInfoResponse); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java index f7487ea225c..ffe4f53ac66 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java @@ -20,6 +20,7 @@ package org.apache.hadoop.hbase.coprocessor; import java.io.IOException; import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.hadoop.hbase.ClusterMetrics; import org.apache.hadoop.hbase.HBaseInterfaceAudience; @@ -1358,6 +1359,26 @@ public interface MasterObserver { default void postRenameRSGroup(final ObserverContext ctx, final String oldName, final String newName) throws IOException {} + /** + * Called before update rsgroup config. + * @param ctx the environment to interact with the framework and master + * @param groupName the group name + * @param configuration new configuration of the group name to be set + */ + default void preUpdateRSGroupConfig(final ObserverContext ctx, + final String groupName, final Map configuration) + throws IOException {} + + /** + * Called after update rsgroup config. + * @param ctx the environment to interact with the framework and master + * @param groupName the group name + * @param configuration new configuration of the group name to be set + */ + default void postUpdateRSGroupConfig(final ObserverContext ctx, + final String groupName, final Map configuration) + throws IOException {} + /** * Called before getting the configured namespaces and tables in the region server group. * @param ctx the environment to interact with the framework and master diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java index 4d0f25c0b73..28c9c309091 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java @@ -21,6 +21,7 @@ package org.apache.hadoop.hbase.master; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.ClusterMetrics; @@ -1562,6 +1563,26 @@ public class MasterCoprocessorHost }); } + public void preUpdateRSGroupConfig(final String groupName, + final Map configuration) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + protected void call(MasterObserver observer) throws IOException { + observer.preUpdateRSGroupConfig(this, groupName, configuration); + } + }); + } + + public void postUpdateRSGroupConfig(final String groupName, + final Map configuration) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + protected void call(MasterObserver observer) throws IOException { + observer.postUpdateRSGroupConfig(this, groupName, configuration); + } + }); + } + public void preGetConfiguredNamespacesAndTablesInRSGroup(final String groupName) throws IOException { execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java index 2d903015d2a..fc29a381d47 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java @@ -345,6 +345,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.Remo import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveServersResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RenameRSGroupRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RenameRSGroupResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.UpdateRSGroupConfigRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.UpdateRSGroupConfigResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.FileArchiveNotificationRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.FileArchiveNotificationResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.GetLastFlushedSequenceIdRequest; @@ -3248,4 +3250,28 @@ public class MasterRpcServices extends RSRpcServices implements } return builder.build(); } + + @Override + public UpdateRSGroupConfigResponse updateRSGroupConfig(RpcController controller, + UpdateRSGroupConfigRequest request) + throws ServiceException { + UpdateRSGroupConfigResponse.Builder builder = UpdateRSGroupConfigResponse.newBuilder(); + String groupName = request.getGroupName(); + Map configuration = new HashMap<>(); + request.getConfigurationList().forEach(p -> configuration.put(p.getName(), p.getValue())); + LOG.info("{} update rsgroup {} configuration {}", master.getClientIdAuditPrefix(), groupName, + configuration); + try { + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preUpdateRSGroupConfig(groupName, configuration); + } + master.getRSGroupInfoManager().updateRSGroupConfig(groupName, configuration); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postUpdateRSGroupConfig(groupName, configuration); + } + } catch (IOException e) { + throw new ServiceException(e); + } + return builder.build(); + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/DisabledRSGroupInfoManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/DisabledRSGroupInfoManager.java index b86b471624d..3323acdb350 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/DisabledRSGroupInfoManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/DisabledRSGroupInfoManager.java @@ -20,6 +20,7 @@ package org.apache.hadoop.hbase.rsgroup; import java.io.IOException; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -125,4 +126,9 @@ class DisabledRSGroupInfoManager implements RSGroupInfoManager { public void renameRSGroup(String oldName, String newName) throws IOException { } + @Override + public void updateRSGroupConfig(String groupName, Map configuration) + throws IOException { + throw new DoNotRetryIOException("RSGroup is disabled"); + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManager.java index 10008f9942a..350f2b42be0 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManager.java @@ -19,6 +19,7 @@ package org.apache.hadoop.hbase.rsgroup; import java.io.IOException; import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.master.MasterServices; @@ -114,4 +115,12 @@ public interface RSGroupInfoManager { */ void renameRSGroup(String oldName, String newName) throws IOException; + /** + * Update RSGroup configuration + * @param groupName the group name + * @param configuration new configuration of the group name to be set + * @throws IOException if a remote or network exception occurs + */ + void updateRSGroupConfig(String groupName, Map configuration) throws IOException; + } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.java index 9e8c635cb57..1cb51cf38c9 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.java @@ -1244,4 +1244,12 @@ final class RSGroupInfoManagerImpl implements RSGroupInfoManager { setRSGroup(updateTables, newName); } + @Override + public synchronized void updateRSGroupConfig(String groupName, Map configuration) + throws IOException { + RSGroupInfo rsGroupInfo = getRSGroupInfo(groupName); + rsGroupInfo.getConfiguration().forEach((k, v) -> rsGroupInfo.removeConfiguration(k)); + configuration.forEach((k, v) -> rsGroupInfo.setConfiguration(k, v)); + flushConfig(); + } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupConfig.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupConfig.java new file mode 100644 index 00000000000..d39ac8f1fa8 --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupConfig.java @@ -0,0 +1,99 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.rsgroup; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.hadoop.hbase.HBaseClassTestRule; +import org.apache.hadoop.hbase.client.Admin; +import org.apache.hadoop.hbase.testclassification.MediumTests; +import org.apache.hadoop.hbase.testclassification.RSGroupTests; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.hbase.thirdparty.com.google.common.collect.Maps; + +@Category({ RSGroupTests.class, MediumTests.class }) +public class TestRSGroupConfig extends TestRSGroupsBase { + + @ClassRule + public static final HBaseClassTestRule CLASS_RULE = + HBaseClassTestRule.forClass(TestRSGroupConfig.class); + + @Rule + public TestName name = new TestName(); + + protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroupConfig.class); + + private static Admin admin; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + TestRSGroupsBase.setUpTestBeforeClass(); + admin = TEST_UTIL.getAdmin(); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + TestRSGroupsBase.tearDownAfterClass(); + } + + @Test + public void testSetDefaultGroupConfiguration() throws IOException { + testSetConfiguration(RSGroupInfo.DEFAULT_GROUP); + } + + @Test + public void testSetNonDefaultGroupConfiguration() throws IOException { + String group = GROUP_PREFIX + name.getMethodName(); + admin.addRSGroup(group); + testSetConfiguration(RSGroupInfo.DEFAULT_GROUP); + admin.removeRSGroup(group); + } + + private void testSetConfiguration(String group) throws IOException { + Map configuration = new HashMap<>(); + configuration.put("aaa", "111"); + configuration.put("bbb", "222"); + admin.updateRSGroupConfig(group, configuration); + RSGroupInfo rsGroup = admin.getRSGroup(group); + Map configFromGroup = Maps.newHashMap(rsGroup.getConfiguration()); + assertNotNull(configFromGroup); + assertEquals(2, configFromGroup.size()); + assertEquals("111", configFromGroup.get("aaa")); + // unset configuration + admin.updateRSGroupConfig(group, null); + rsGroup = admin.getRSGroup(group); + configFromGroup = rsGroup.getConfiguration(); + assertNotNull(configFromGroup); + assertEquals(0, configFromGroup.size()); + } + +} diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/VerifyingRSGroupAdmin.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/VerifyingRSGroupAdmin.java index 7e1ec6e1dd2..58ab1ca050f 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/VerifyingRSGroupAdmin.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/VerifyingRSGroupAdmin.java @@ -822,6 +822,13 @@ public class VerifyingRSGroupAdmin implements Admin, Closeable { verify(); } + @Override + public void updateRSGroupConfig(String groupName, Map configuration) + throws IOException { + admin.updateRSGroupConfig(groupName, configuration); + verify(); + } + private void verify() throws IOException { Map groupMap = Maps.newHashMap(); Set zList = Sets.newHashSet(); diff --git a/hbase-shell/src/main/ruby/hbase/rsgroup_admin.rb b/hbase-shell/src/main/ruby/hbase/rsgroup_admin.rb index fd39634889f..2027c778dbe 100644 --- a/hbase-shell/src/main/ruby/hbase/rsgroup_admin.rb +++ b/hbase-shell/src/main/ruby/hbase/rsgroup_admin.rb @@ -191,5 +191,42 @@ module Hbase def rename_rsgroup(oldname, newname) @admin.renameRSGroup(oldname, newname) end + + #---------------------------------------------------------------------------------------------- + # modify a rsgroup configuration + def alter_rsgroup_config(rsgroup_name, *args) + # Fail if table name is not a string + raise(ArgumentError, 'RSGroup name must be of type String') unless rsgroup_name.is_a?(String) + + group = @admin.getRSGroup(rsgroup_name) + + raise(ArgumentError, 'RSGroup does not exist') unless group + + configuration = java.util.HashMap.new + configuration.putAll(group.getConfiguration) + + # Flatten params array + args = args.flatten.compact + + # Start defining the table + args.each do |arg| + unless arg.is_a?(Hash) + raise(ArgumentError, "#{arg.class} of #{arg.inspect} is not of Hash type") + end + method = arg[METHOD] + if method == 'unset' + configuration.remove(arg[NAME]) + elsif method == 'set' + arg.delete(METHOD) + for k, v in arg + v = v.to_s unless v.nil? + configuration.put(k, v) + end + else + raise(ArgumentError, "Unknown method #{method}") + end + end + @admin.updateRSGroupConfig(rsgroup_name, configuration) + end end end diff --git a/hbase-shell/src/main/ruby/shell.rb b/hbase-shell/src/main/ruby/shell.rb index 885394c7030..92e52fae4a6 100644 --- a/hbase-shell/src/main/ruby/shell.rb +++ b/hbase-shell/src/main/ruby/shell.rb @@ -509,5 +509,7 @@ Shell.load_command_group( get_table_rsgroup remove_servers_rsgroup rename_rsgroup + alter_rsgroup_config + show_rsgroup_config ] ) diff --git a/hbase-shell/src/main/ruby/shell/commands/alter_rsgroup_config.rb b/hbase-shell/src/main/ruby/shell/commands/alter_rsgroup_config.rb new file mode 100644 index 00000000000..d27edd91ec7 --- /dev/null +++ b/hbase-shell/src/main/ruby/shell/commands/alter_rsgroup_config.rb @@ -0,0 +1,38 @@ +# +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module Shell + module Commands + class AlterRsgroupConfig < Command + def help + <<-EOF +Alter RSGroup configuration. +Example: + hbase> alter_rsgroup_config 'grp1', {METHOD => 'set', 'PROPERTY_NAME' => 'PROPERTY_VALUE'} +To delete a property: + hbase> alter_rsgroup_config 'grp1', {METHOD => 'unset', NAME=>'PROPERTY_NAME'} +EOF + end + + def command(group, args) + rsgroup_admin.alter_rsgroup_config(group, args) + end + end + end +end diff --git a/hbase-shell/src/main/ruby/shell/commands/show_rsgroup_config.rb b/hbase-shell/src/main/ruby/shell/commands/show_rsgroup_config.rb new file mode 100644 index 00000000000..88ebd5cbca0 --- /dev/null +++ b/hbase-shell/src/main/ruby/shell/commands/show_rsgroup_config.rb @@ -0,0 +1,43 @@ +# +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module Shell + module Commands + class ShowRsgroupConfig < Command + def help + <<-EOF +Show the configuration of a special RSGroup. +Example: + + hbase> show_rsgroup_config 'group' + +EOF + end + + def command(group) + formatter.header(%w['KEY' 'VALUE']) + config = rsgroup_admin.get_rsgroup(group).getConfiguration + config.each { |key, val| + formatter.row([key, val]) + } + formatter.footer(config.size) + end + end + end +end diff --git a/hbase-shell/src/test/ruby/shell/rsgroup_shell_test.rb b/hbase-shell/src/test/ruby/shell/rsgroup_shell_test.rb index d7bccdbe40c..33a6c498bec 100644 --- a/hbase-shell/src/test/ruby/shell/rsgroup_shell_test.rb +++ b/hbase-shell/src/test/ruby/shell/rsgroup_shell_test.rb @@ -140,5 +140,19 @@ module Hbase assert_equal(1, @admin.listTablesInRSGroup(new_rs_group_name).count) assert_true(@admin.listTablesInRSGroup(new_rs_group_name).contains(org.apache.hadoop.hbase.TableName.valueOf(table_name))) end + + define_test 'Test alter rsgroup configuration' do + group_name = 'grp1' + @shell.command('add_rsgroup', group_name) + assert_not_nil(@admin.getRSGroup(group_name)) + + @hbase.rsgroup_admin.alter_rsgroup_config(group_name, {'METHOD' => 'set', 'a' => 'a'}) + assert_equal(1, @admin.getRSGroup(group_name).getConfiguration.size) + @hbase.rsgroup_admin.alter_rsgroup_config(group_name, {'METHOD' => 'unset', 'NAME' => 'a'}) + assert_equal(0, @admin.getRSGroup(group_name).getConfiguration.size) + + @shell.command('remove_rsgroup', group_name) + assert_nil(@admin.getRSGroup(group_name)) + end end end diff --git a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java index 2e248977183..81c700d3ae4 100644 --- a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java +++ b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java @@ -1261,4 +1261,10 @@ public class ThriftAdmin implements Admin { public void renameRSGroup(String oldName, String newName) throws IOException { throw new NotImplementedException("renameRSGroup not supported in ThriftAdmin"); } + + @Override + public void updateRSGroupConfig(String groupName, Map configuration) + throws IOException { + throw new NotImplementedException("updateRSGroupConfig not supported in ThriftAdmin"); + } }