diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java index 1b8f5bb68843..3773915d3e17 100644 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java +++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java @@ -42,6 +42,7 @@ import org.apache.hadoop.ozone.om.helpers.OzoneFileStatus; import org.apache.hadoop.ozone.om.helpers.S3SecretValue; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRoleInfo; import org.apache.hadoop.ozone.security.OzoneTokenIdentifier; import org.apache.hadoop.ozone.security.acl.OzoneObj; import org.apache.hadoop.security.KerberosInfo; @@ -58,6 +59,13 @@ @KerberosInfo(serverPrincipal = OMConfigKeys.OZONE_OM_KERBEROS_PRINCIPAL_KEY) public interface ClientProtocol { + /** + * List of OM node Ids and their Ratis server roles. + * @return List of OM server roles + * @throws IOException + */ + List getOmRoleInfos() throws IOException; + /** * Creates a new Volume. * @param volumeName Name of the Volume diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java index 06351ab2c3d0..a9d221b8a4f1 100644 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java +++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java @@ -64,6 +64,7 @@ import org.apache.hadoop.ozone.om.helpers.OzoneAclUtil; import org.apache.hadoop.ozone.om.helpers.OzoneFileStatus; import org.apache.hadoop.ozone.om.helpers.S3SecretValue; +import org.apache.hadoop.ozone.om.helpers.ServiceInfo; import org.apache.hadoop.ozone.om.helpers.ServiceInfoEx; import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol; import org.apache.hadoop.ozone.om.protocolPB @@ -72,6 +73,7 @@ import org.apache.hadoop.hdds.protocol.proto.HddsProtos; import org.apache.hadoop.hdds.scm.ScmConfigKeys; import org.apache.hadoop.hdds.scm.XceiverClientManager; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRoleInfo; import org.apache.hadoop.ozone.security.GDPRSymmetricKey; import org.apache.hadoop.ozone.security.OzoneTokenIdentifier; import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLIdentityType; @@ -223,6 +225,23 @@ public RpcClient(Configuration conf, String omServiceId) throws IOException { OzoneConfigKeys.OZONE_NETWORK_TOPOLOGY_AWARE_READ_DEFAULT); } + @Override + public List getOmRoleInfos() throws IOException { + + List serviceList = ozoneManagerClient.getServiceList(); + List roleInfos = new ArrayList<>(); + + for (ServiceInfo serviceInfo : serviceList) { + if (serviceInfo.getNodeType().equals(HddsProtos.NodeType.OM)) { + OMRoleInfo omRoleInfo = serviceInfo.getOmRoleInfo(); + if (omRoleInfo != null) { + roleInfos.add(omRoleInfo); + } + } + } + return roleInfos; + } + @Override public void createVolume(String volumeName) throws IOException { createVolume(volumeName, VolumeArgs.newBuilder().build()); diff --git a/hadoop-ozone/common/src/main/bin/ozone b/hadoop-ozone/common/src/main/bin/ozone index 9c13b941a6aa..987e118d769d 100755 --- a/hadoop-ozone/common/src/main/bin/ozone +++ b/hadoop-ozone/common/src/main/bin/ozone @@ -55,6 +55,7 @@ function hadoop_usage hadoop_add_subcommand "version" client "print the version" hadoop_add_subcommand "dtutil" client "operations related to delegation tokens" hadoop_add_subcommand "upgrade" client "HDFS to Ozone in-place upgrade tool" + hadoop_add_subcommand "admin" client "Ozone admin tool" hadoop_generate_usage "${HADOOP_SHELL_EXECNAME}" false } @@ -207,6 +208,10 @@ function ozonecmd_case HADOOP_CLASSNAME=org.apache.hadoop.ozone.upgrade.InPlaceUpgrade OZONE_RUN_ARTIFACT_NAME="hadoop-ozone-upgrade" ;; + admin) + HADOOP_CLASSNAME=org.apache.hadoop.ozone.admin.OzoneAdmin + OZONE_RUN_ARTIFACT_NAME="hadoop-ozone-tools" + ;; *) HADOOP_CLASSNAME="${subcmd}" if ! hadoop_validate_classname "${HADOOP_CLASSNAME}"; then diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/ServiceInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/ServiceInfo.java index dce4f8e20d27..e569db887086 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/ServiceInfo.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/ServiceInfo.java @@ -25,6 +25,8 @@ import com.fasterxml.jackson.databind.ObjectWriter; import com.google.common.base.Preconditions; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos + .OMRoleInfo; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos .ServicePort; import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType; @@ -58,6 +60,8 @@ public final class ServiceInfo { * List of ports the service listens to. */ private Map ports; + + private OMRoleInfo omRoleInfo; /** * Default constructor for JSON deserialization. @@ -70,8 +74,8 @@ public ServiceInfo() {} * @param hostname hostname of the service * @param portList list of ports the service listens to */ - private ServiceInfo( - NodeType nodeType, String hostname, List portList) { + private ServiceInfo(NodeType nodeType, String hostname, + List portList, OMRoleInfo omRole) { Preconditions.checkNotNull(nodeType); Preconditions.checkNotNull(hostname); this.nodeType = nodeType; @@ -80,6 +84,7 @@ private ServiceInfo( for (ServicePort port : portList) { ports.put(port.getType(), port.getValue()); } + this.omRoleInfo = omRole; } /** @@ -128,6 +133,15 @@ public String getServiceAddress(ServicePort.Type portType) { return hostname + ":" + getPort(portType); } + /** + * Returns the OM role info - node id and ratis server role. + * @return OmRoleInfo + */ + @JsonIgnore + public OMRoleInfo getOmRoleInfo() { + return omRoleInfo; + } + /** * Converts {@link ServiceInfo} to OzoneManagerProtocolProtos.ServiceInfo. * @@ -147,6 +161,9 @@ public OzoneManagerProtocolProtos.ServiceInfo getProtobuf() { .setType(entry.getKey()) .setValue(entry.getValue()).build()) .collect(Collectors.toList())); + if (nodeType == NodeType.OM && omRoleInfo != null) { + builder.setOmRole(omRoleInfo); + } return builder.build(); } @@ -160,7 +177,8 @@ public static ServiceInfo getFromProtobuf( OzoneManagerProtocolProtos.ServiceInfo serviceInfo) { return new ServiceInfo(serviceInfo.getNodeType(), serviceInfo.getHostname(), - serviceInfo.getServicePortsList()); + serviceInfo.getServicePortsList(), + serviceInfo.hasOmRole() ? serviceInfo.getOmRole() : null); } /** @@ -179,7 +197,7 @@ public static class Builder { private NodeType node; private String host; private List portList = new ArrayList<>(); - + private OMRoleInfo omRoleInfo; /** * Sets the node/service type. @@ -211,13 +229,17 @@ public Builder addServicePort(ServicePort servicePort) { return this; } + public Builder setOmRoleInfo(OMRoleInfo omRole) { + omRoleInfo = omRole; + return this; + } /** * Builds and returns {@link ServiceInfo} with the set values. * @return {@link ServiceInfo} */ public ServiceInfo build() { - return new ServiceInfo(node, host, portList); + return new ServiceInfo(node, host, portList, omRoleInfo); } } diff --git a/hadoop-ozone/common/src/main/proto/OzoneManagerProtocol.proto b/hadoop-ozone/common/src/main/proto/OzoneManagerProtocol.proto index ba53bd0edde7..5d1f1817f0ae 100644 --- a/hadoop-ozone/common/src/main/proto/OzoneManagerProtocol.proto +++ b/hadoop-ozone/common/src/main/proto/OzoneManagerProtocol.proto @@ -903,10 +903,16 @@ message ServicePort { required uint32 value = 2; } +message OMRoleInfo { + required string nodeId = 1; + required string serverRole = 2; +} + message ServiceInfo { required hadoop.hdds.NodeType nodeType = 1; required string hostname = 2; repeated ServicePort servicePorts = 3; + optional OMRoleInfo omRole = 4; } message S3CreateBucketRequest { 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 294b74eeb36f..fb965a12bab1 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 @@ -86,6 +86,7 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DBUpdatesRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos .KeyArgs; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRoleInfo; import org.apache.hadoop.ozone.protocolPB.ProtocolMessageMetrics; import org.apache.hadoop.ozone.security.OzoneSecurityException; import org.apache.hadoop.ozone.security.OzoneTokenIdentifier; @@ -154,6 +155,7 @@ import org.apache.hadoop.hdds.utils.db.DBCheckpoint; import org.apache.hadoop.hdds.utils.db.DBStore; +import org.apache.ratis.proto.RaftProtos.RaftPeerRole; import org.apache.ratis.server.protocol.TermIndex; import org.apache.ratis.util.FileUtils; import org.apache.ratis.util.LifeCycle; @@ -2384,6 +2386,43 @@ public List getServiceList() throws IOException { .setValue(httpServer.getHttpsAddress().getPort()) .build()); } + + // Since this OM is processing the request, we can assume it to be the + // leader OM + + OMRoleInfo omRole = OMRoleInfo.newBuilder() + .setNodeId(getOMNodeId()) + .setServerRole(RaftPeerRole.LEADER.name()) + .build(); + omServiceInfoBuilder.setOmRoleInfo(omRole); + + if (isRatisEnabled) { + if (omRatisServer != null) { + omServiceInfoBuilder.addServicePort(ServicePort.newBuilder() + .setType(ServicePort.Type.RATIS) + .setValue(omNodeDetails.getRatisPort()) + .build()); + } + + for (OMNodeDetails peerNode : peerNodes) { + ServiceInfo.Builder peerOmServiceInfoBuilder = ServiceInfo.newBuilder() + .setNodeType(HddsProtos.NodeType.OM) + .setHostname(peerNode.getAddress().getHostName()) + .addServicePort(ServicePort.newBuilder() + .setType(ServicePort.Type.RPC) + .setValue(peerNode.getRpcPort()) + .build()); + + OMRoleInfo peerOmRole = OMRoleInfo.newBuilder() + .setNodeId(peerNode.getOMNodeId()) + .setServerRole(RaftPeerRole.FOLLOWER.name()) + .build(); + peerOmServiceInfoBuilder.setOmRoleInfo(peerOmRole); + + services.add(peerOmServiceInfoBuilder.build()); + } + } + services.add(omServiceInfoBuilder.build()); // For client we have to return SCM with container protocol port, diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/OzoneAdmin.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/OzoneAdmin.java new file mode 100644 index 000000000000..85142f5bba42 --- /dev/null +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/OzoneAdmin.java @@ -0,0 +1,68 @@ +/** + * 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.ozone.admin; + +import org.apache.hadoop.hdds.cli.GenericCli; +import org.apache.hadoop.hdds.cli.HddsVersionProvider; +import org.apache.hadoop.hdds.conf.OzoneConfiguration; +import org.apache.hadoop.ozone.admin.om.OMAdmin; +import org.apache.hadoop.util.NativeCodeLoader; +import org.apache.log4j.ConsoleAppender; +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.apache.log4j.PatternLayout; +import picocli.CommandLine; + +/** + * Ozone Admin Command line tool. + */ +@CommandLine.Command(name = "ozone admin", + hidden = true, + description = "Developer tools for Ozone Admin operations", + versionProvider = HddsVersionProvider.class, + subcommands = { + OMAdmin.class + }, + mixinStandardHelpOptions = true) +public class OzoneAdmin extends GenericCli { + private OzoneConfiguration ozoneConf; + + public OzoneConfiguration getOzoneConf() { + if (ozoneConf == null) { + ozoneConf = createOzoneConfiguration(); + } + return ozoneConf; + } + + /** + * Main for the Ozone Admin shell Command handling. + * + * @param argv - System Args Strings[] + * @throws Exception + */ + public static void main(String[] argv) throws Exception { + LogManager.resetConfiguration(); + Logger.getRootLogger().setLevel(Level.WARN); + Logger.getRootLogger() + .addAppender(new ConsoleAppender(new PatternLayout("%m%n"))); + Logger.getLogger(NativeCodeLoader.class).setLevel(Level.ERROR); + + new OzoneAdmin().run(argv); + } +} diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/GetServiceRolesSubcommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/GetServiceRolesSubcommand.java new file mode 100644 index 000000000000..4df4cd5df8eb --- /dev/null +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/GetServiceRolesSubcommand.java @@ -0,0 +1,60 @@ +/* + * 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.ozone.admin.om; + +import org.apache.hadoop.hdds.cli.HddsVersionProvider; +import org.apache.hadoop.ozone.client.protocol.ClientProtocol; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRoleInfo; +import picocli.CommandLine; + +import java.util.List; +import java.util.concurrent.Callable; + +/** + * Handler of om get-service-roles command. + */ +@CommandLine.Command( + name = "getserviceroles", + description = "List all OMs and their respective Ratis server roles", + mixinStandardHelpOptions = true, + versionProvider = HddsVersionProvider.class) +public class GetServiceRolesSubcommand implements Callable { + + @CommandLine.ParentCommand + private OMAdmin parent; + + @CommandLine.Option(names = {"-id", "--service-id"}, + description = "OM Service ID", + required = true) + private String omServiceId; + + @Override + public Void call() throws Exception { + ClientProtocol client = parent.createClient(omServiceId); + getOmServerRoles(client.getOmRoleInfos()); + return null; + } + + private void getOmServerRoles(List roleInfos) { + for (OMRoleInfo roleInfo : roleInfos) { + System.out.println( + roleInfo.getNodeId() + " : " + roleInfo.getServerRole()); + } + } +} diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/OMAdmin.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/OMAdmin.java new file mode 100644 index 000000000000..3a109ac51979 --- /dev/null +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/OMAdmin.java @@ -0,0 +1,63 @@ +/** + * 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.ozone.admin.om; + +import org.apache.hadoop.hdds.cli.GenericCli; +import org.apache.hadoop.hdds.cli.HddsVersionProvider; +import org.apache.hadoop.hdds.cli.MissingSubcommandException; +import org.apache.hadoop.hdds.conf.OzoneConfiguration; +import org.apache.hadoop.ozone.admin.OzoneAdmin; +import org.apache.hadoop.ozone.client.OzoneClientFactory; +import org.apache.hadoop.ozone.client.protocol.ClientProtocol; +import picocli.CommandLine; + +import java.io.IOException; + +/** + * Subcommand for admin operations related to OM. + */ +@CommandLine.Command( + name = "om", + description = "Ozone Manager specific admin operations", + mixinStandardHelpOptions = true, + versionProvider = HddsVersionProvider.class, + subcommands = { + GetServiceRolesSubcommand.class + }) +public class OMAdmin extends GenericCli { + + @CommandLine.ParentCommand + private OzoneAdmin parent; + + public OzoneAdmin getParent() { + return parent; + } + + @Override + public Void call() throws Exception { + throw new MissingSubcommandException( + this.parent.getCmd().getSubcommands().get("om")); + } + + public ClientProtocol createClient(String omServiceId) throws IOException { + OzoneConfiguration conf = parent.getOzoneConf(); + return OzoneClientFactory.getRpcClient(omServiceId, conf).getObjectStore() + .getClientProxy(); + + } +} diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/package-info.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/package-info.java new file mode 100644 index 000000000000..934ffd98db95 --- /dev/null +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/package-info.java @@ -0,0 +1,24 @@ +/** + * 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. + *

+ * SCM related cli tools. + */ + +/** + * OM related Admin tools. + */ +package org.apache.hadoop.ozone.admin.om; diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/package-info.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/package-info.java new file mode 100644 index 000000000000..c25c2225737f --- /dev/null +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/package-info.java @@ -0,0 +1,24 @@ +/** + * 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. + *

+ * SCM related cli tools. + */ + +/** + * Ozone Admin tools. + */ +package org.apache.hadoop.ozone.admin;