You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by ca...@apache.org on 2023/02/03 08:09:00 UTC
[ozone] branch master updated: HDDS-3591. ozone.administrators support dynamic changes through the cli. (#4221)
This is an automated email from the ASF dual-hosted git repository.
captainzmc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 15cc89b602 HDDS-3591. ozone.administrators support dynamic changes through the cli. (#4221)
15cc89b602 is described below
commit 15cc89b6024948faebd9ec89a917bc07ed851581
Author: Hongbing Wang <28...@qq.com>
AuthorDate: Fri Feb 3 16:08:55 2023 +0800
HDDS-3591. ozone.administrators support dynamic changes through the cli. (#4221)
* HDDS-3591. ozone.administrators support dynamic changes through the cli.
---
.../docs/content/feature/Reconfigurability.md | 65 ++++++++
.../docs/content/feature/Reconfigurability.zh.md | 62 +++++++
.../hadoop/hdds/protocol/ReconfigureProtocol.java | 56 +++++++
.../ReconfigureProtocolClientSideTranslatorPB.java | 178 +++++++++++++++++++++
.../hdds/protocolPB/ReconfigureProtocolPB.java | 36 +++++
.../ReconfigureProtocolServerSideTranslatorPB.java | 128 +++++++++++++++
.../org/apache/hadoop/hdds/server/OzoneAdmins.java | 13 +-
.../hadoop/hdds/server/ServiceRuntimeInfoImpl.java | 24 ++-
hadoop-hdds/interface-client/pom.xml | 2 +
.../src/main/proto/ReconfigureProtocol.proto | 80 +++++++++
.../hadoop/ozone/reconfig/TestOmReconfigure.java | 100 ++++++++++++
.../apache/hadoop/ozone/om/OzoneConfigUtil.java | 14 +-
.../org/apache/hadoop/ozone/om/OzoneManager.java | 104 +++++++++++-
.../ozone/admin/reconfig/ReconfigureCommands.java | 75 +++++++++
.../reconfig/ReconfigurePropertiesSubcommand.java | 53 ++++++
.../admin/reconfig/ReconfigureStartSubcommand.java | 49 ++++++
.../reconfig/ReconfigureStatusSubcommand.java | 89 +++++++++++
.../admin/reconfig/ReconfigureSubCommandUtil.java | 46 ++++++
.../hadoop/ozone/admin/reconfig/package-info.java | 23 +++
19 files changed, 1181 insertions(+), 16 deletions(-)
diff --git a/hadoop-hdds/docs/content/feature/Reconfigurability.md b/hadoop-hdds/docs/content/feature/Reconfigurability.md
new file mode 100644
index 0000000000..c822b75096
--- /dev/null
+++ b/hadoop-hdds/docs/content/feature/Reconfigurability.md
@@ -0,0 +1,65 @@
+---
+title: "Reconfigurability"
+weight: 11
+menu:
+ main:
+ parent: Features
+summary: Dynamic reloading configuration.
+---
+<!---
+ 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.
+-->
+
+Ozone supports dynamic loading of certain properties without restarting the service.
+If a property is reconfigurable, you can modify it in the configuration file (`ozone-site.xml`) and then invoke the command to flush it to memory.
+
+## OM Reconfigurability
+
+**Reconfigurable properties**
+key | description
+-----------------------------------|-----------------------------------------
+ozone.administrators | OM startup user will be added to admin by default
+
+```shell
+ozone admin reconfig --address=<ip:port> start|status|properties
+```
+
+The meaning of command options:
+- **--address**: RPC address for one server
+- Three operations are provided:
+ - `start`: Execute the reconfig operation asynchronously
+ - `status`: Check reconfig status
+ - `properties`: List reconfigurable properties
+
+>For example, modify `ozone.administrators` in ozone-site.xml and execute:
+>
+> $ `ozone admin reconfig --address=hadoop1:9862 start`<br>
+Started OM reconfiguration task on node [hadoop1:9862].
+>
+>$ `ozone admin reconfig --address=hadoop1:9862 status`<br>
+Reconfiguring status for node [hadoop1:9862]: started at Wed Dec 28 19:04:44 CST 2022 and finished at Wed Dec 28 19:04:44 CST 2022.<br>
+SUCCESS: Changed property ozone.administrators<br>
+From: "hadoop"<br>
+To: "hadoop,bigdata"
+>
+> $ `ozone admin reconfig -address=hadoop1:9862 properties`<br>
+Node [hadoop1:9862] Reconfigurable properties:<br>
+ozone.administrators
+
+
+## SCM Reconfigurability
+
+Add later if needed.
\ No newline at end of file
diff --git a/hadoop-hdds/docs/content/feature/Reconfigurability.zh.md b/hadoop-hdds/docs/content/feature/Reconfigurability.zh.md
new file mode 100644
index 0000000000..177878a522
--- /dev/null
+++ b/hadoop-hdds/docs/content/feature/Reconfigurability.zh.md
@@ -0,0 +1,62 @@
+---
+title: "动态加载配置"
+weight: 8
+summary: 动态加载配置
+menu:
+ main:
+ parent: 特性
+---
+<!---
+ 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.
+-->
+
+Ozone支持在不重启服务的情况下动态加载某些配置。如果某个属性支持热加载,就可以先在配置文件(`ozone-site.xml`)中修改它然后调用命令使之刷新到内存。
+
+## OM动态配置
+
+**支持动态加载的属性**
+配置项 | 描述
+-----------------------------------|-----------------------------------------
+ozone.administrators | OM启动用户将默认成为一个管理员
+
+```shell
+ozone admin reconfig --address=<ip:port> start|status|properties
+```
+
+命令项的含义:
+- **--address**: 一台服务所在的主机与客户端通信的RPC地址
+- 提供3中操作:
+ - `start`: 开始异步执行动态加载配置
+ - `status`: 查看最近一次动态加载的状态
+ - `properties`: 列出支持动态加载的配置项
+
+>例如, 在`ozone-site.xml`文件中修改`ozone.administrators`的值并执行:
+>
+> $ `ozone admin reconfig --address=hadoop1:9862 start`<br>
+Started reconfiguration task on node [hadoop1:9862].
+>
+>$ `ozone admin reconfig --address=hadoop1:9862 status`<br>
+Reconfiguring status for node [hadoop1:9862]: started at Wed Dec 28 19:04:44 CST 2022 and finished at Wed Dec 28 19:04:44 CST 2022.<br>
+SUCCESS: Changed property ozone.administrators<br>
+From: "hadoop"<br>
+To: "hadoop,bigdata"
+>
+> $ `ozone admin reconfig --address=hadoop1:9862 properties`<br>
+Node [hadoop1:9862] Reconfigurable properties:<br>
+ozone.administrators
+
+## SCM动态配置
+
diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocol/ReconfigureProtocol.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocol/ReconfigureProtocol.java
new file mode 100644
index 0000000000..8d0dfbcabe
--- /dev/null
+++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocol/ReconfigureProtocol.java
@@ -0,0 +1,56 @@
+/**
+ * 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.hdds.protocol;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.conf.ReconfigurationTaskStatus;
+import org.apache.hadoop.io.retry.Idempotent;
+
+import java.io.IOException;
+import java.util.List;
+
+/**********************************************************************
+ * ReconfigureProtocol is used by ozone admin to reload configuration.
+ **********************************************************************/
+@InterfaceAudience.Private
+@InterfaceStability.Evolving
+public interface ReconfigureProtocol {
+
+ long VERSIONID = 1L;
+
+ /**
+ * Asynchronously reload configuration on disk and apply changes.
+ */
+ @Idempotent
+ void startReconfigure() throws IOException;
+
+ /**
+ * Get the status of the previously issued reconfig task.
+ * @see ReconfigurationTaskStatus
+ */
+ @Idempotent
+ ReconfigurationTaskStatus getReconfigureStatus() throws IOException;
+
+ /**
+ * Get a list of allowed properties for reconfiguration.
+ */
+ @Idempotent
+ List<String> listReconfigureProperties() throws IOException;
+}
diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/ReconfigureProtocolClientSideTranslatorPB.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/ReconfigureProtocolClientSideTranslatorPB.java
new file mode 100644
index 0000000000..30f4aa3740
--- /dev/null
+++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/ReconfigureProtocolClientSideTranslatorPB.java
@@ -0,0 +1,178 @@
+/**
+ * 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.hdds.protocolPB;
+
+import com.google.common.collect.Maps;
+import com.google.protobuf.RpcController;
+import com.google.protobuf.ServiceException;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.conf.ReconfigurationTaskStatus;
+import org.apache.hadoop.conf.ReconfigurationUtil.PropertyChange;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.protocol.ReconfigureProtocol;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.GetConfigurationChangeProto;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.GetReconfigureStatusResponseProto;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.GetReconfigureStatusRequestProto;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.ListReconfigurePropertiesRequestProto;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.ListReconfigurePropertiesResponseProto;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.StartReconfigureRequestProto;
+import org.apache.hadoop.hdds.utils.LegacyHadoopConfigurationSource;
+import org.apache.hadoop.ipc.ProtobufHelper;
+import org.apache.hadoop.ipc.ProtobufRpcEngine;
+import org.apache.hadoop.ipc.ProtocolMetaInterface;
+import org.apache.hadoop.ipc.ProtocolTranslator;
+import org.apache.hadoop.ipc.RPC;
+import org.apache.hadoop.ipc.RpcClientUtil;
+import org.apache.hadoop.net.NetUtils;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * This class is the client side translator to translate the requests made on
+ * {@link ReconfigureProtocol} interfaces to the RPC server implementing
+ * {@link ReconfigureProtocolPB}.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Stable
+public class ReconfigureProtocolClientSideTranslatorPB implements
+ ProtocolMetaInterface, ReconfigureProtocol, ProtocolTranslator, Closeable {
+ public static final Logger LOG = LoggerFactory
+ .getLogger(ReconfigureProtocolClientSideTranslatorPB.class);
+
+ private static final RpcController NULL_CONTROLLER = null;
+ private static final StartReconfigureRequestProto VOID_START_RECONFIG =
+ StartReconfigureRequestProto.newBuilder().build();
+
+ private static final ListReconfigurePropertiesRequestProto
+ VOID_LIST_RECONFIGURABLE_PROPERTIES =
+ ListReconfigurePropertiesRequestProto.newBuilder().build();
+
+ private static final GetReconfigureStatusRequestProto
+ VOID_GET_RECONFIG_STATUS =
+ GetReconfigureStatusRequestProto.newBuilder().build();
+
+ private final ReconfigureProtocolPB rpcProxy;
+
+ public ReconfigureProtocolClientSideTranslatorPB(InetSocketAddress addr,
+ UserGroupInformation ugi, OzoneConfiguration conf)
+ throws IOException {
+ rpcProxy = createReconfigureProtocolProxy(addr, ugi, conf);
+ }
+
+ static ReconfigureProtocolPB createReconfigureProtocolProxy(
+ InetSocketAddress addr, UserGroupInformation ugi,
+ OzoneConfiguration conf) throws IOException {
+
+ RPC.setProtocolEngine(OzoneConfiguration.of(conf),
+ ReconfigureProtocolPB.class, ProtobufRpcEngine.class);
+ Configuration hadoopConf = LegacyHadoopConfigurationSource
+ .asHadoopConfiguration(conf);
+ return RPC.getProtocolProxy(
+ ReconfigureProtocolPB.class,
+ RPC.getProtocolVersion(ReconfigureProtocolPB.class),
+ addr, ugi, hadoopConf,
+ NetUtils.getDefaultSocketFactory(hadoopConf))
+ .getProxy();
+ }
+
+ @Override
+ public void close() throws IOException {
+ RPC.stopProxy(rpcProxy);
+ }
+
+ @Override
+ public Object getUnderlyingProxyObject() {
+ return rpcProxy;
+ }
+
+ @Override
+ public void startReconfigure() throws IOException {
+ try {
+ rpcProxy.startReconfigure(NULL_CONTROLLER, VOID_START_RECONFIG);
+ } catch (ServiceException e) {
+ throw ProtobufHelper.getRemoteException(e);
+ }
+ }
+
+ @Override
+ public ReconfigurationTaskStatus getReconfigureStatus()
+ throws IOException {
+ try {
+ GetReconfigureStatusResponseProto response = rpcProxy
+ .getReconfigureStatus(NULL_CONTROLLER, VOID_GET_RECONFIG_STATUS);
+ return getReconfigureStatus(response);
+ } catch (ServiceException e) {
+ throw ProtobufHelper.getRemoteException(e);
+ }
+ }
+
+ private ReconfigurationTaskStatus getReconfigureStatus(
+ GetReconfigureStatusResponseProto response) {
+ Map<PropertyChange, Optional<String>> statusMap = null;
+ long startTime;
+ long endTime = 0;
+
+ startTime = response.getStartTime();
+ if (response.hasEndTime()) {
+ endTime = response.getEndTime();
+ }
+ if (response.getChangesCount() > 0) {
+ statusMap = Maps.newHashMap();
+ for (GetConfigurationChangeProto change : response.getChangesList()) {
+ PropertyChange pc = new PropertyChange(change.getName(),
+ change.getNewValue(), change.getOldValue());
+ String errorMessage = null;
+ if (change.hasErrorMessage()) {
+ errorMessage = change.getErrorMessage();
+ }
+ statusMap.put(pc, Optional.ofNullable(errorMessage));
+ }
+ }
+ return new ReconfigurationTaskStatus(startTime, endTime, statusMap);
+ }
+
+ @Override
+ public List<String> listReconfigureProperties() throws IOException {
+ ListReconfigurePropertiesResponseProto response;
+ try {
+ response = rpcProxy.listReconfigureProperties(NULL_CONTROLLER,
+ VOID_LIST_RECONFIGURABLE_PROPERTIES);
+ return response.getNameList();
+ } catch (ServiceException e) {
+ throw ProtobufHelper.getRemoteException(e);
+ }
+ }
+
+ @Override
+ public boolean isMethodSupported(String methodName) throws IOException {
+ return RpcClientUtil.isMethodSupported(rpcProxy,
+ ReconfigureProtocolPB.class,
+ RPC.RpcKind.RPC_PROTOCOL_BUFFER,
+ RPC.getProtocolVersion(ReconfigureProtocolPB.class),
+ methodName);
+ }
+}
diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/ReconfigureProtocolPB.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/ReconfigureProtocolPB.java
new file mode 100644
index 0000000000..e1702ce0ad
--- /dev/null
+++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/ReconfigureProtocolPB.java
@@ -0,0 +1,36 @@
+/**
+ * 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.hdds.protocolPB;
+
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.ReconfigureProtocolService;
+import org.apache.hadoop.hdds.scm.ScmConfig;
+import org.apache.hadoop.ipc.ProtocolInfo;
+import org.apache.hadoop.security.KerberosInfo;
+
+/**
+ * Protocol that clients use to communicate with the OM/SCM to do
+ * reconfiguration on the fly.
+ */
+@ProtocolInfo(
+ protocolName = "org.apache.hadoop.hdds.protocol.ReconfigureProtocol",
+ protocolVersion = 1)
+@KerberosInfo(serverPrincipal = ScmConfig.ConfigStrings
+ .HDDS_SCM_KERBEROS_PRINCIPAL_KEY)
+public interface ReconfigureProtocolPB extends
+ ReconfigureProtocolService.BlockingInterface {
+}
diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/ReconfigureProtocolServerSideTranslatorPB.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/ReconfigureProtocolServerSideTranslatorPB.java
new file mode 100644
index 0000000000..5273c91513
--- /dev/null
+++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/protocolPB/ReconfigureProtocolServerSideTranslatorPB.java
@@ -0,0 +1,128 @@
+/**
+ * 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.hdds.protocolPB;
+
+import com.google.protobuf.RpcController;
+import com.google.protobuf.ServiceException;
+import org.apache.hadoop.conf.ReconfigurationTaskStatus;
+import org.apache.hadoop.conf.ReconfigurationUtil.PropertyChange;
+import org.apache.hadoop.hdds.protocol.ReconfigureProtocol;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.GetConfigurationChangeProto;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.GetReconfigureStatusRequestProto;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.GetReconfigureStatusResponseProto;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.ListReconfigurePropertiesRequestProto;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.ListReconfigurePropertiesResponseProto;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.StartReconfigureRequestProto;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.StartReconfigureResponseProto;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * This class is used on the server side. Calls come across the wire for the
+ * for protocol {@link ReconfigureProtocolPB}.
+ * This class translates the PB data types
+ * to the native data types used inside the NN/DN as specified in the generic
+ * ReconfigureProtocol.
+ */
+public class ReconfigureProtocolServerSideTranslatorPB implements
+ ReconfigureProtocolPB {
+
+ private final ReconfigureProtocol impl;
+
+ private static final StartReconfigureResponseProto START_RECONFIG_RESP =
+ StartReconfigureResponseProto.newBuilder().build();
+
+ public ReconfigureProtocolServerSideTranslatorPB(
+ ReconfigureProtocol impl) {
+ this.impl = impl;
+ }
+
+ @Override
+ public StartReconfigureResponseProto startReconfigure(
+ RpcController controller, StartReconfigureRequestProto request)
+ throws ServiceException {
+ try {
+ impl.startReconfigure();
+ } catch (IOException e) {
+ throw new ServiceException(e);
+ }
+ return START_RECONFIG_RESP;
+ }
+
+ @Override
+ public ListReconfigurePropertiesResponseProto listReconfigureProperties(
+ RpcController controller, ListReconfigurePropertiesRequestProto request)
+ throws ServiceException {
+ try {
+ return listReconfigureProperties(impl.listReconfigureProperties());
+ } catch (IOException e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ private ListReconfigurePropertiesResponseProto listReconfigureProperties(
+ List<String> reconfigurableProperties) {
+ ListReconfigurePropertiesResponseProto.Builder builder =
+ ListReconfigurePropertiesResponseProto.newBuilder();
+ builder.addAllName(reconfigurableProperties);
+ return builder.build();
+ }
+
+ @Override
+ public GetReconfigureStatusResponseProto getReconfigureStatus(
+ RpcController unused, GetReconfigureStatusRequestProto request)
+ throws ServiceException {
+ try {
+ return getReconfigureStatus(impl.getReconfigureStatus());
+ } catch (IOException e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ private GetReconfigureStatusResponseProto getReconfigureStatus(
+ ReconfigurationTaskStatus status) {
+ GetReconfigureStatusResponseProto.Builder builder =
+ GetReconfigureStatusResponseProto.newBuilder();
+
+ builder.setStartTime(status.getStartTime());
+ if (status.stopped()) {
+ builder.setEndTime(status.getEndTime());
+ assert status.getStatus() != null;
+ for (Map.Entry<PropertyChange, Optional<String>> result : status
+ .getStatus().entrySet()) {
+ GetConfigurationChangeProto.Builder changeBuilder =
+ GetConfigurationChangeProto.newBuilder();
+ PropertyChange change = result.getKey();
+ changeBuilder.setName(change.prop);
+ changeBuilder.setOldValue(change.oldVal != null ? change.oldVal : "");
+ if (change.newVal != null) {
+ changeBuilder.setNewValue(change.newVal);
+ }
+ if (result.getValue().isPresent()) {
+ // Get full stack trace.
+ changeBuilder.setErrorMessage(result.getValue().get());
+ }
+ builder.addChanges(changeBuilder);
+ }
+ }
+ return builder.build();
+ }
+}
diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/OzoneAdmins.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/OzoneAdmins.java
index 342e10a1b9..a705783d19 100644
--- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/OzoneAdmins.java
+++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/OzoneAdmins.java
@@ -38,7 +38,7 @@ public class OzoneAdmins {
/**
* Ozone super user / admin username list.
*/
- private final Set<String> adminUsernames;
+ private volatile Set<String> adminUsernames;
/**
* Ozone super user / admin group list.
*/
@@ -50,9 +50,7 @@ public class OzoneAdmins {
public OzoneAdmins(Collection<String> adminUsernames,
Collection<String> adminGroups) {
- this.adminUsernames = adminUsernames != null ?
- Collections.unmodifiableSet(new LinkedHashSet<>(adminUsernames)) :
- Collections.emptySet();
+ setAdminUsernames(adminUsernames);
this.adminGroups = adminGroups != null ?
Collections.unmodifiableSet(new LinkedHashSet<>(adminGroups)) :
Collections.emptySet();
@@ -84,4 +82,11 @@ public class OzoneAdmins {
public Set<String> getAdminUsernames() {
return adminUsernames;
}
+
+ public void setAdminUsernames(Collection<String> adminUsernames) {
+ this.adminUsernames = adminUsernames != null ?
+ Collections.unmodifiableSet(new LinkedHashSet<>(adminUsernames)) :
+ Collections.emptySet();
+ }
+
}
diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServiceRuntimeInfoImpl.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServiceRuntimeInfoImpl.java
index 2dffc6f902..42d63dffe0 100644
--- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServiceRuntimeInfoImpl.java
+++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/ServiceRuntimeInfoImpl.java
@@ -17,13 +17,20 @@
package org.apache.hadoop.hdds.server;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.conf.ReconfigurableBase;
+import org.apache.hadoop.conf.ReconfigurationException;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.utils.VersionInfo;
+import java.util.Collection;
+
/**
* Helper base class to report the standard version and runtime information.
*
*/
-public class ServiceRuntimeInfoImpl implements ServiceRuntimeInfo {
+public class ServiceRuntimeInfoImpl extends ReconfigurableBase
+ implements ServiceRuntimeInfo {
private long startedTimeInMillis;
private final VersionInfo versionInfo;
@@ -57,4 +64,19 @@ public class ServiceRuntimeInfoImpl implements ServiceRuntimeInfo {
startedTimeInMillis = System.currentTimeMillis();
}
+ @Override
+ protected Configuration getNewConf() {
+ return new OzoneConfiguration();
+ }
+
+ @Override
+ public Collection<String> getReconfigurableProperties() {
+ return null;
+ }
+
+ @Override
+ protected String reconfigurePropertyImpl(String property, String newVal)
+ throws ReconfigurationException {
+ throw new ReconfigurationException();
+ }
}
diff --git a/hadoop-hdds/interface-client/pom.xml b/hadoop-hdds/interface-client/pom.xml
index eac95a00e1..3fe96d3d90 100644
--- a/hadoop-hdds/interface-client/pom.xml
+++ b/hadoop-hdds/interface-client/pom.xml
@@ -103,6 +103,7 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd">
<protoSourceRoot>${basedir}/src/main/proto/</protoSourceRoot>
<includes>
<include>hdds.proto</include>
+ <include>ReconfigureProtocol.proto</include>
</includes>
<outputDirectory>target/generated-sources/java</outputDirectory>
<clearOutputDirectory>false</clearOutputDirectory>
@@ -121,6 +122,7 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd">
<protoSourceRoot>${basedir}/src/main/proto/</protoSourceRoot>
<includes>
<include>hdds.proto</include>
+ <include>ReconfigureProtocol.proto</include>
</includes>
<outputDirectory>target/generated-sources/java/proto3</outputDirectory>
<clearOutputDirectory>false</clearOutputDirectory>
diff --git a/hadoop-hdds/interface-client/src/main/proto/ReconfigureProtocol.proto b/hadoop-hdds/interface-client/src/main/proto/ReconfigureProtocol.proto
new file mode 100644
index 0000000000..4bc78c3056
--- /dev/null
+++ b/hadoop-hdds/interface-client/src/main/proto/ReconfigureProtocol.proto
@@ -0,0 +1,80 @@
+/**
+ * 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.
+ */
+
+/**
+ * These .proto interfaces are private and unstable.
+ * Please see http://wiki.apache.org/hadoop/Compatibility
+ * for what changes are allowed for an *unstable* .proto interface.
+ */
+
+// This file contains protocol buffers that are used to reconfigure OM and SCM
+// by ozone admin.
+
+syntax="proto2";
+option java_package = "org.apache.hadoop.hdds.protocol.proto";
+option java_outer_classname = "ReconfigureProtocolProtos";
+option java_generic_services = true;
+option java_generate_equals_and_hash = true;
+package hadoop.hdds;
+
+/** Asks OM/SCM to reload configuration file. */
+message StartReconfigureRequestProto {
+}
+
+message StartReconfigureResponseProto {
+}
+
+/** Query the running status of reconfiguration process */
+message GetReconfigureStatusRequestProto {
+}
+
+message GetConfigurationChangeProto {
+ required string name = 1;
+ required string oldValue = 2;
+ optional string newValue = 3;
+ optional string errorMessage = 4; // It is empty if success.
+}
+
+message GetReconfigureStatusResponseProto {
+ required int64 startTime = 1;
+ optional int64 endTime = 2;
+ repeated GetConfigurationChangeProto changes = 3;
+}
+
+/** Query the reconfigurable properties on OM/SCM. */
+message ListReconfigurePropertiesRequestProto {
+}
+
+message ListReconfigurePropertiesResponseProto {
+ repeated string name = 1;
+}
+
+/**
+ * Protocol used from client to the OM.
+ * See the request and response for details of rpc call.
+ */
+service ReconfigureProtocolService {
+ rpc getReconfigureStatus(GetReconfigureStatusRequestProto)
+ returns(GetReconfigureStatusResponseProto);
+
+ rpc startReconfigure(StartReconfigureRequestProto)
+ returns(StartReconfigureResponseProto);
+
+ rpc listReconfigureProperties(ListReconfigurePropertiesRequestProto)
+ returns(ListReconfigurePropertiesResponseProto);
+}
\ No newline at end of file
diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/reconfig/TestOmReconfigure.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/reconfig/TestOmReconfigure.java
new file mode 100644
index 0000000000..3ce6cab55b
--- /dev/null
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/reconfig/TestOmReconfigure.java
@@ -0,0 +1,100 @@
+package org.apache.hadoop.ozone.reconfig;
+
+/*
+ * 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.
+ *
+ */
+
+import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ADMINISTRATORS;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import java.util.UUID;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.ozone.MiniOzoneCluster;
+import org.apache.hadoop.ozone.MiniOzoneHAClusterImpl;
+import org.apache.hadoop.ozone.om.OzoneManager;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.Timeout;
+
+/**
+ * Tests for OM Reconfigure.
+ */
+public class TestOmReconfigure {
+
+ /**
+ * Set a timeout for each test.
+ */
+ @Rule
+ public Timeout timeout = new Timeout(300000);
+ private OzoneConfiguration conf;
+ private MiniOzoneHAClusterImpl cluster;
+ private OzoneManager ozoneManager;
+
+ /**
+ * Create a MiniDFSCluster for testing.
+ */
+ @Before
+ public void setup() throws Exception {
+
+ conf = new OzoneConfiguration();
+ String omServiceId = UUID.randomUUID().toString();
+ cluster = (MiniOzoneHAClusterImpl) MiniOzoneCluster.newOMHABuilder(conf)
+ .setClusterId(UUID.randomUUID().toString())
+ .setScmId(UUID.randomUUID().toString())
+ .setOMServiceId(omServiceId)
+ .setNumOfOzoneManagers(3)
+ .setNumDatanodes(1)
+ .build();
+
+ cluster.waitForClusterToBeReady();
+ ozoneManager = cluster.getOzoneManager();
+
+ }
+
+ /**
+ * Shutdown MiniDFSCluster.
+ */
+ @After
+ public void shutdown() {
+ if (cluster != null) {
+ cluster.shutdown();
+ }
+ }
+
+ /**
+ * Test reconfigure om "ozone.administrators".
+ */
+ @Test
+ public void testOmAdminUsersReconfigure() throws Exception {
+ String userA = "mockUserA";
+ String userB = "mockUserB";
+ conf.set(OZONE_ADMINISTRATORS, userA);
+ ozoneManager.reconfigurePropertyImpl(OZONE_ADMINISTRATORS, userA);
+ assertTrue(userA + " should be an admin user",
+ ozoneManager.getOmAdminUsernames().contains(userA));
+
+ conf.set(OZONE_ADMINISTRATORS, userB);
+ ozoneManager.reconfigurePropertyImpl(OZONE_ADMINISTRATORS, userB);
+ assertFalse(userA + " should NOT be an admin user",
+ ozoneManager.getOmAdminUsernames().contains(userA));
+ assertTrue(userB + " should be an admin user",
+ ozoneManager.getOmAdminUsernames().contains(userB));
+ }
+
+}
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneConfigUtil.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneConfigUtil.java
index b73a3b7173..ce6c59dd72 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneConfigUtil.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneConfigUtil.java
@@ -44,14 +44,14 @@ public final class OzoneConfigUtil {
/**
* Return list of OzoneAdministrators from config.
+ * The service startup user will default to an admin.
*/
- static Collection<String> getOzoneAdminsFromConfig(OzoneConfiguration conf)
- throws IOException {
- Collection<String> ozAdmins =
- conf.getTrimmedStringCollection(OZONE_ADMINISTRATORS);
- String omSPN = UserGroupInformation.getCurrentUser().getShortUserName();
- if (!ozAdmins.contains(omSPN)) {
- ozAdmins.add(omSPN);
+ static Collection<String> getOzoneAdminsFromConfig(OzoneConfiguration conf,
+ String starterUser) {
+ Collection<String> ozAdmins = conf.getTrimmedStringCollection(
+ OZONE_ADMINISTRATORS);
+ if (!ozAdmins.contains(starterUser)) {
+ ozAdmins.add(starterUser);
}
return ozAdmins;
}
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
index 169e87fa39..67803786df 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
@@ -43,6 +43,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.SortedSet;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
@@ -50,7 +51,11 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Lists;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.conf.ReconfigurationException;
+import org.apache.hadoop.conf.ReconfigurationTaskStatus;
import org.apache.hadoop.conf.StorageUnit;
import org.apache.hadoop.crypto.key.KeyProvider;
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
@@ -64,7 +69,11 @@ import org.apache.hadoop.hdds.client.ReplicationConfig;
import org.apache.hadoop.hdds.client.ReplicationType;
import org.apache.hadoop.hdds.conf.ConfigurationException;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.protocol.ReconfigureProtocol;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
+import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.ReconfigureProtocolService;
+import org.apache.hadoop.hdds.protocolPB.ReconfigureProtocolPB;
+import org.apache.hadoop.hdds.protocolPB.ReconfigureProtocolServerSideTranslatorPB;
import org.apache.hadoop.hdds.scm.ScmInfo;
import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
import org.apache.hadoop.hdds.server.OzoneAdmins;
@@ -220,6 +229,7 @@ import static org.apache.hadoop.ozone.OzoneConfigKeys.DFS_CONTAINER_RATIS_ENABLE
import static org.apache.hadoop.ozone.OzoneConfigKeys.DFS_CONTAINER_RATIS_ENABLED_KEY;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_ENABLED;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ACL_ENABLED_DEFAULT;
+import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ADMINISTRATORS;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_FLEXIBLE_FQDN_RESOLUTION_ENABLED;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_FLEXIBLE_FQDN_RESOLUTION_ENABLED_DEFAULT;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_KEY_PREALLOCATION_BLOCKS_MAX;
@@ -291,7 +301,7 @@ import org.slf4j.LoggerFactory;
@InterfaceAudience.LimitedPrivate({"HDFS", "CBLOCK", "OZONE", "HBASE"})
public final class OzoneManager extends ServiceRuntimeInfoImpl
implements OzoneManagerProtocol, OMInterServiceProtocol,
- OMMXBean, Auditor {
+ ReconfigureProtocol, OMMXBean, Auditor {
public static final Logger LOG =
LoggerFactory.getLogger(OzoneManager.class);
@@ -329,6 +339,7 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
/**
* OM super user / admin list.
*/
+ private final String omStarterUser;
private final OzoneAdmins omAdmins;
private final OzoneAdmins s3OzoneAdmins;
@@ -435,6 +446,12 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
private OmMetadataReader omMetadataReader;
private OmSnapshotManager omSnapshotManager;
+ /** A list of property that are reconfigurable at runtime. */
+ private final SortedSet<String> reconfigurableProperties =
+ ImmutableSortedSet.of(
+ OZONE_ADMINISTRATORS
+ );
+
@SuppressWarnings("methodlength")
private OzoneManager(OzoneConfiguration conf, StartupOption startupOption)
throws IOException, AuthenticationException {
@@ -587,10 +604,12 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
metrics = OMMetrics.create();
// Get admin list
+ omStarterUser = UserGroupInformation.getCurrentUser().getShortUserName();
Collection<String> omAdminUsernames =
- OzoneConfigUtil.getOzoneAdminsFromConfig(configuration);
+ OzoneConfigUtil.getOzoneAdminsFromConfig(configuration, omStarterUser);
Collection<String> omAdminGroups =
OzoneConfigUtil.getOzoneAdminsGroupsFromConfig(configuration);
+ LOG.info("OM start with adminUsers: {}", omAdminUsernames);
omAdmins = new OzoneAdmins(omAdminUsernames, omAdminGroups);
Collection<String> s3AdminUsernames =
@@ -1132,8 +1151,14 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
OzoneManagerAdminService.newReflectiveBlockingService(
omMetadataServerProtocol);
+ ReconfigureProtocolServerSideTranslatorPB reconfigureServerProtocol
+ = new ReconfigureProtocolServerSideTranslatorPB(this);
+ BlockingService reconfigureService =
+ ReconfigureProtocolService.newReflectiveBlockingService(
+ reconfigureServerProtocol);
+
return startRpcServer(configuration, omNodeRpcAddr, omService,
- omInterService, omAdminService, handlerCount);
+ omInterService, omAdminService, reconfigureService, handlerCount);
}
/**
@@ -1144,6 +1169,8 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
* (OzoneManagerProtocolPB impl)
* @param interOMProtocolService RPC protocol for inter OM communication
* (OMInterServiceProtocolPB impl)
+ * @param reconfigureProtocolService RPC protocol for reconfigure
+ * * (ReconfigureProtocolPB impl)
* @param handlerCount RPC server handler count
* @return RPC server
* @throws IOException if there is an I/O error while creating RPC server
@@ -1152,6 +1179,7 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
InetSocketAddress addr, BlockingService clientProtocolService,
BlockingService interOMProtocolService,
BlockingService omAdminProtocolService,
+ BlockingService reconfigureProtocolService,
int handlerCount)
throws IOException {
RPC.Server rpcServer = new RPC.Builder(conf)
@@ -1168,6 +1196,8 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
interOMProtocolService, rpcServer);
HddsServerUtil.addPBProtocol(conf, OMAdminProtocolPB.class,
omAdminProtocolService, rpcServer);
+ HddsServerUtil.addPBProtocol(conf, ReconfigureProtocolPB.class,
+ reconfigureProtocolService, rpcServer);
if (conf.getBoolean(CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION,
false)) {
@@ -3701,6 +3731,12 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
return LOG;
}
+ // ReconfigurableBase get base configuration
+ @Override
+ public Configuration getConf() {
+ return getConfiguration();
+ }
+
public OzoneConfiguration getConfiguration() {
return configuration;
}
@@ -3843,7 +3879,7 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
/**
* Return the list of Ozone administrators in effect.
*/
- Collection<String> getOmAdminUsernames() {
+ public Collection<String> getOmAdminUsernames() {
return omAdmins.getAdminUsernames();
}
@@ -3859,6 +3895,17 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
return callerUgi != null && omAdmins.isAdmin(callerUgi);
}
+ /**
+ * Check ozone admin privilege, throws exception if not admin.
+ */
+ public void checkAdminUserPrivilege(String operation) throws IOException {
+ final UserGroupInformation ugi = getRemoteUser();
+ if (!isAdmin(ugi)) {
+ throw new OMException("Only Ozone admins are allowed to " + operation,
+ PERMISSION_DENIED);
+ }
+ }
+
public boolean isS3Admin(UserGroupInformation callerUgi) {
return callerUgi != null && s3OzoneAdmins.isAdmin(callerUgi);
}
@@ -4325,4 +4372,53 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
return omSnapshotManager.getSnapshotDiffReport(volume, bucket,
fromSnapshot, toSnapshot);
}
+
+ @Override // ReconfigureProtocol
+ public void startReconfigure() throws IOException {
+ String operationName = "startOmReconfiguration";
+ checkAdminUserPrivilege(operationName);
+ startReconfigurationTask();
+ }
+
+ @Override // ReconfigureProtocol
+ public ReconfigurationTaskStatus getReconfigureStatus()
+ throws IOException {
+ String operationName = "getOmReconfigurationStatus";
+ checkAdminUserPrivilege(operationName);
+ return getReconfigurationTaskStatus();
+ }
+
+ @Override // ReconfigureProtocol
+ public List<String> listReconfigureProperties() throws IOException {
+ String operationName = "listOmReconfigurableProperties";
+ checkAdminUserPrivilege(operationName);
+ return Lists.newArrayList(getReconfigurableProperties());
+ }
+
+ @Override // ReconfigurableBase
+ public Collection<String> getReconfigurableProperties() {
+ return reconfigurableProperties;
+ }
+
+ @Override // ReconfigurableBase
+ public String reconfigurePropertyImpl(String property, String newVal)
+ throws ReconfigurationException {
+ if (property.equals(OZONE_ADMINISTRATORS)) {
+ return reconfOzoneAdmins(newVal);
+ } else {
+ throw new ReconfigurationException(property, newVal,
+ getConfiguration().get(property));
+ }
+ }
+
+ private String reconfOzoneAdmins(String newVal) {
+ getConfiguration().set(OZONE_ADMINISTRATORS, newVal);
+ Collection<String> admins =
+ OzoneConfigUtil.getOzoneAdminsFromConfig(getConfiguration(),
+ omStarterUser);
+ omAdmins.setAdminUsernames(admins);
+ LOG.info("Load conf {} : {}, and now admins are: {}", OZONE_ADMINISTRATORS,
+ newVal, admins);
+ return String.valueOf(newVal);
+ }
}
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigureCommands.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigureCommands.java
new file mode 100644
index 0000000000..f47c439711
--- /dev/null
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigureCommands.java
@@ -0,0 +1,75 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ozone.admin.reconfig;
+
+import org.apache.hadoop.hdds.cli.GenericCli;
+import org.apache.hadoop.hdds.cli.HddsVersionProvider;
+import org.apache.hadoop.hdds.cli.OzoneAdmin;
+import org.apache.hadoop.hdds.cli.SubcommandWithParent;
+import org.kohsuke.MetaInfServices;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Model.CommandSpec;
+import picocli.CommandLine.Spec;
+
+import java.util.concurrent.Callable;
+
+/**
+ * Subcommand to group reconfigure OM related operations.
+ */
+@Command(
+ name = "reconfig",
+ description = "Dynamically reconfigure server without restarting it",
+ mixinStandardHelpOptions = true,
+ versionProvider = HddsVersionProvider.class,
+ subcommands = {
+ ReconfigureStartSubcommand.class,
+ ReconfigureStatusSubcommand.class,
+ ReconfigurePropertiesSubcommand.class
+ })
+@MetaInfServices(SubcommandWithParent.class)
+public class ReconfigureCommands implements Callable<Void>,
+ SubcommandWithParent {
+
+ @CommandLine.ParentCommand
+ private OzoneAdmin parent;
+
+ @Spec
+ private CommandSpec spec;
+
+ @CommandLine.Option(names = {"--address"},
+ description = "node address: <ip:port> or <hostname:port>",
+ required = true)
+ private String address;
+
+ @Override
+ public Void call() throws Exception {
+ GenericCli.missingSubcommand(spec);
+ return null;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ @Override
+ public Class<?> getParentType() {
+ return OzoneAdmin.class;
+ }
+
+}
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigurePropertiesSubcommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigurePropertiesSubcommand.java
new file mode 100644
index 0000000000..1206d6117e
--- /dev/null
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigurePropertiesSubcommand.java
@@ -0,0 +1,53 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ozone.admin.reconfig;
+
+import org.apache.hadoop.hdds.protocol.ReconfigureProtocol;
+import org.apache.hadoop.hdds.cli.HddsVersionProvider;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+ * Handler of ozone admin reconfig properties command.
+ */
+@Command(
+ name = "properties",
+ description = "List reconfigurable properties",
+ mixinStandardHelpOptions = true,
+ versionProvider = HddsVersionProvider.class)
+public class ReconfigurePropertiesSubcommand implements Callable<Void> {
+
+ @CommandLine.ParentCommand
+ private ReconfigureCommands parent;
+
+ @Override
+ public Void call() throws Exception {
+ ReconfigureProtocol reconfigProxy = ReconfigureSubCommandUtil
+ .getSingleNodeReconfigureProxy(parent.getAddress());
+ List<String> properties = reconfigProxy.listReconfigureProperties();
+ System.out.printf("Node [%s] Reconfigurable properties:%n",
+ parent.getAddress());
+ for (String name : properties) {
+ System.out.println(name);
+ }
+ return null;
+ }
+
+}
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigureStartSubcommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigureStartSubcommand.java
new file mode 100644
index 0000000000..7f3866154f
--- /dev/null
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigureStartSubcommand.java
@@ -0,0 +1,49 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ozone.admin.reconfig;
+
+import org.apache.hadoop.hdds.cli.HddsVersionProvider;
+import org.apache.hadoop.hdds.protocol.ReconfigureProtocol;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import java.util.concurrent.Callable;
+
+/**
+ * Handler of ozone admin reconfig start command.
+ */
+@Command(
+ name = "start",
+ description = "Start reconfig asynchronously",
+ mixinStandardHelpOptions = true,
+ versionProvider = HddsVersionProvider.class)
+public class ReconfigureStartSubcommand implements Callable<Void> {
+
+ @CommandLine.ParentCommand
+ private ReconfigureCommands parent;
+
+ @Override
+ public Void call() throws Exception {
+ ReconfigureProtocol reconfigProxy = ReconfigureSubCommandUtil
+ .getSingleNodeReconfigureProxy(parent.getAddress());
+ reconfigProxy.startReconfigure();
+ System.out.printf("Started reconfiguration task on node [%s].%n",
+ parent.getAddress());
+ return null;
+ }
+
+}
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigureStatusSubcommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigureStatusSubcommand.java
new file mode 100644
index 0000000000..e6f2da9700
--- /dev/null
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigureStatusSubcommand.java
@@ -0,0 +1,89 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ozone.admin.reconfig;
+
+import org.apache.hadoop.conf.ReconfigurationTaskStatus;
+import org.apache.hadoop.conf.ReconfigurationUtil;
+import org.apache.hadoop.hdds.cli.HddsVersionProvider;
+import org.apache.hadoop.hdds.protocol.ReconfigureProtocol;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.Callable;
+
+/**
+ * Handler of ozone admin reconfig status command.
+ */
+@Command(
+ name = "status",
+ description = "Check reconfig status",
+ mixinStandardHelpOptions = true,
+ versionProvider = HddsVersionProvider.class)
+public class ReconfigureStatusSubcommand implements Callable<Void> {
+
+ @CommandLine.ParentCommand
+ private ReconfigureCommands parent;
+
+ @Override
+ public Void call() throws Exception {
+ ReconfigureProtocol reconfigProxy = ReconfigureSubCommandUtil
+ .getSingleNodeReconfigureProxy(parent.getAddress());
+ ReconfigurationTaskStatus status = reconfigProxy.getReconfigureStatus();
+ System.out.printf("Reconfiguring status for node [%s]: ",
+ parent.getAddress());
+ printReconfigurationStatus(status);
+ return null;
+ }
+
+ private void printReconfigurationStatus(ReconfigurationTaskStatus status) {
+ if (!status.hasTask()) {
+ System.out.println("no task was found.");
+ return;
+ }
+ System.out.print("started at " + new Date(status.getStartTime()));
+ if (!status.stopped()) {
+ System.out.println(" and is still running.");
+ return;
+ }
+ System.out.printf(" and finished at %s.%n", new Date(status.getEndTime()));
+ if (status.getStatus() == null) {
+ // Nothing to report.
+ return;
+ }
+ for (Map.Entry<ReconfigurationUtil.PropertyChange, Optional<String>>
+ result : status.getStatus().entrySet()) {
+ if (!result.getValue().isPresent()) {
+ System.out.printf(
+ "SUCCESS: Changed property %s%n\tFrom: \"%s\"%n\tTo: \"%s\"%n",
+ result.getKey().prop, result.getKey().oldVal,
+ result.getKey().newVal);
+ } else {
+ final String errorMsg = result.getValue().get();
+ System.out.printf(
+ "FAILED: Change property %s%n\tFrom: \"%s\"%n\tTo: \"%s\"%n",
+ result.getKey().prop, result.getKey().oldVal,
+ result.getKey().newVal);
+ System.out.println("\tError: " + errorMsg + ".");
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigureSubCommandUtil.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigureSubCommandUtil.java
new file mode 100644
index 0000000000..44c74ab2dc
--- /dev/null
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/ReconfigureSubCommandUtil.java
@@ -0,0 +1,46 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.ozone.admin.reconfig;
+
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.protocol.ReconfigureProtocol;
+import org.apache.hadoop.hdds.protocolPB.ReconfigureProtocolClientSideTranslatorPB;
+import org.apache.hadoop.net.NetUtils;
+import org.apache.hadoop.security.UserGroupInformation;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+/**
+ * Reconfigure subcommand utils.
+ */
+final class ReconfigureSubCommandUtil {
+
+ private ReconfigureSubCommandUtil() {
+ }
+
+ public static ReconfigureProtocol getSingleNodeReconfigureProxy(
+ String address) throws IOException {
+ OzoneConfiguration ozoneConf = new OzoneConfiguration();
+ UserGroupInformation user = UserGroupInformation.getCurrentUser();
+ InetSocketAddress nodeAddr = NetUtils.createSocketAddr(address);
+ return new ReconfigureProtocolClientSideTranslatorPB(
+ nodeAddr, user, ozoneConf);
+ }
+
+}
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/package-info.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/package-info.java
new file mode 100644
index 0000000000..fa2d33830a
--- /dev/null
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/reconfig/package-info.java
@@ -0,0 +1,23 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ * <p>
+ */
+
+/**
+ * Reconfigure related Admin tools.
+ */
+package org.apache.hadoop.ozone.admin.reconfig;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org