This is an automated email from the ASF dual-hosted git repository.
agupta 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 22a40b6c40 HDDS-8212. ozone admin printTopology command should have
json output (#5099)
22a40b6c40 is described below
commit 22a40b6c40bd02183b6e4459b1887abd48039712
Author: Tejaskriya <[email protected]>
AuthorDate: Sun Aug 13 13:37:00 2023 +0530
HDDS-8212. ozone admin printTopology command should have json output (#5099)
---
.../hadoop/hdds/scm/cli/TopologySubcommand.java | 150 +++++++++++++++++++--
.../main/smoketest/admincli/printTopology.robot | 32 +++++
2 files changed, 171 insertions(+), 11 deletions(-)
diff --git
a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/TopologySubcommand.java
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/TopologySubcommand.java
index babcabe592..9ac275fd5c 100644
---
a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/TopologySubcommand.java
+++
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/TopologySubcommand.java
@@ -22,12 +22,17 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Map;
import java.util.HashMap;
import java.util.InvalidPropertiesFormatException;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.cli.OzoneAdmin;
import org.apache.hadoop.hdds.cli.SubcommandWithParent;
@@ -39,6 +44,7 @@ import static
org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState.DEAD;
import static
org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState.HEALTHY;
import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState.STALE;
+import org.apache.hadoop.hdds.server.JsonUtils;
import org.kohsuke.MetaInfServices;
import picocli.CommandLine;
@@ -82,14 +88,17 @@ public class TopologySubcommand extends ScmSubcommand
" HEALTHY, STALE, DEAD)")
private String nodeState;
+ @CommandLine.Option(names = { "--json" },
+ defaultValue = "false",
+ description = "Format output as JSON")
+ private boolean json;
+
@Override
public void execute(ScmClient scmClient) throws IOException {
for (HddsProtos.NodeState state : STATES) {
List<HddsProtos.Node> nodes = scmClient.queryNode(null, state,
HddsProtos.QueryScope.CLUSTER, "");
if (nodes != null && nodes.size() > 0) {
- // show node state
- System.out.println("State = " + state.toString());
if (nodeOperationalState != null) {
if (nodeOperationalState.equals("IN_SERVICE") ||
nodeOperationalState.equals("DECOMMISSIONING") ||
@@ -120,9 +129,9 @@ public class TopologySubcommand extends ScmSubcommand
}
}
if (order) {
- printOrderedByLocation(nodes);
+ printOrderedByLocation(nodes, state.toString());
} else {
- printNodesWithLocation(nodes);
+ printNodesWithLocation(nodes, state.toString());
}
}
}
@@ -136,10 +145,10 @@ public class TopologySubcommand extends ScmSubcommand
// Format
// Location: rack1
// ipAddress(hostName) OperationalState
- private void printOrderedByLocation(List<HddsProtos.Node> nodes) {
- HashMap<String, TreeSet<DatanodeDetails>> tree =
- new HashMap<>();
- HashMap<DatanodeDetails, HddsProtos.NodeOperationalState> state =
+ private void printOrderedByLocation(List<HddsProtos.Node> nodes,
+ String state) throws IOException {
+ Map<String, TreeSet<DatanodeDetails>> tree = new HashMap<>();
+ Map<DatanodeDetails, HddsProtos.NodeOperationalState> operationalState =
new HashMap<>();
for (HddsProtos.Node node : nodes) {
String location = node.getNodeID().getNetworkLocation();
@@ -148,16 +157,31 @@ public class TopologySubcommand extends ScmSubcommand
}
DatanodeDetails dn = DatanodeDetails.getFromProtoBuf(node.getNodeID());
tree.get(location).add(dn);
- state.put(dn, node.getNodeOperationalStates(0));
+ operationalState.put(dn, node.getNodeOperationalStates(0));
}
ArrayList<String> locations = new ArrayList<>(tree.keySet());
Collections.sort(locations);
+ if (json) {
+ List<NodeTopologyOrder> nodesJson = new ArrayList<>();
+ locations.forEach(location -> {
+ tree.get(location).forEach(n -> {
+ NodeTopologyOrder nodeJson = new NodeTopologyOrder(n, state,
+ operationalState.get(n).toString());
+ nodesJson.add(nodeJson);
+ });
+ });
+ System.out.println(
+ JsonUtils.toJsonStringWithDefaultPrettyPrinter(nodesJson));
+ return;
+ }
+ // show node state
+ System.out.println("State = " + state);
locations.forEach(location -> {
System.out.println("Location: " + location);
tree.get(location).forEach(n -> {
System.out.println(" " + n.getIpAddress() + "(" + n.getHostName()
- + ") " + state.get(n));
+ + ") " + operationalState.get(n));
});
});
}
@@ -180,7 +204,33 @@ public class TopologySubcommand extends ScmSubcommand
// Format "ipAddress(hostName):PortName1=PortValue1 OperationalState
// networkLocation
- private void printNodesWithLocation(Collection<HddsProtos.Node> nodes) {
+ private void printNodesWithLocation(Collection<HddsProtos.Node> nodes,
+ String state) throws IOException {
+ if (json) {
+ if (fullInfo) {
+ List<NodeTopologyFull> nodesJson = new ArrayList<>();
+ nodes.forEach(node -> {
+ NodeTopologyFull nodeJson =
+ new NodeTopologyFull(
+ DatanodeDetails.getFromProtoBuf(node.getNodeID()), state);
+ nodesJson.add(nodeJson);
+ });
+ System.out.println(
+ JsonUtils.toJsonStringWithDefaultPrettyPrinter(nodesJson));
+ return;
+ }
+ List<NodeTopologyDefault> nodesJson = new ArrayList<>();
+ nodes.forEach(node -> {
+ NodeTopologyDefault nodeJson = new NodeTopologyDefault(
+ DatanodeDetails.getFromProtoBuf(node.getNodeID()), state);
+ nodesJson.add(nodeJson);
+ });
+ System.out.println(
+ JsonUtils.toJsonStringWithDefaultPrettyPrinter(nodesJson));
+ return;
+ }
+ // show node state
+ System.out.println("State = " + state);
nodes.forEach(node -> {
System.out.print(" " + getAdditionNodeOutput(node) +
node.getNodeID().getIpAddress() + "(" +
@@ -192,4 +242,82 @@ public class TopologySubcommand extends ScmSubcommand
node.getNodeID().getNetworkLocation() : "NA"));
});
}
+
+ private static class ListJsonSerializer extends
+ JsonSerializer<List<DatanodeDetails.Port>> {
+ @Override
+ public void serialize(List<DatanodeDetails.Port> value, JsonGenerator jgen,
+ SerializerProvider provider)
+ throws IOException {
+ jgen.writeStartObject();
+ for (DatanodeDetails.Port port : value) {
+ jgen.writeNumberField(port.getName().toString(), port.getValue());
+ }
+ jgen.writeEndObject();
+ }
+ }
+
+ private static class NodeTopologyOrder {
+ private String ipAddress;
+ private String hostName;
+ private String nodeState;
+ private String operationalState;
+ private String networkLocation;
+
+ NodeTopologyOrder(DatanodeDetails node, String state, String opState) {
+ ipAddress = node.getIpAddress();
+ hostName = node.getHostName();
+ nodeState = state;
+ operationalState = opState;
+ networkLocation = (node.getNetworkLocation() != null ?
+ node.getNetworkLocation() : "NA");
+ }
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public String getHostName() {
+ return hostName;
+ }
+
+ public String getNodeState() {
+ return nodeState;
+ }
+
+ public String getOperationalState() {
+ return operationalState;
+ }
+
+ public String getNetworkLocation() {
+ return networkLocation;
+ }
+ }
+
+ private static class NodeTopologyDefault extends NodeTopologyOrder {
+ private List<DatanodeDetails.Port> ports;
+
+ NodeTopologyDefault(DatanodeDetails node, String state) {
+ super(node, state, node.getPersistedOpState().toString());
+ ports = node.getPorts();
+ }
+
+ @JsonSerialize(using = ListJsonSerializer.class)
+ public List<DatanodeDetails.Port> getPorts() {
+ return ports;
+ }
+ }
+
+ private static class NodeTopologyFull extends NodeTopologyDefault {
+ private String uuid;
+
+ NodeTopologyFull(DatanodeDetails node, String state) {
+ super(node, state);
+ uuid = node.getUuid().toString();
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+ }
}
diff --git a/hadoop-ozone/dist/src/main/smoketest/admincli/printTopology.robot
b/hadoop-ozone/dist/src/main/smoketest/admincli/printTopology.robot
new file mode 100644
index 0000000000..50cce5652b
--- /dev/null
+++ b/hadoop-ozone/dist/src/main/smoketest/admincli/printTopology.robot
@@ -0,0 +1,32 @@
+# 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.
+
+*** Settings ***
+Documentation Test ozone admin printTopology command
+Library OperatingSystem
+Library BuiltIn
+Resource ../commonlib.robot
+Test Timeout 5 minutes
+
+
+*** Test Cases ***
+Run printTopology
+ ${output} = Execute ozone admin printTopology
+ Should Match Regexp ${output} State =
+
+Run printTopology as JSON
+ ${output} = Execute ozone admin printTopology --json
+ ${keys} = Execute echo '${output}' | jq -r '.[0] |
keys'
+ Should Contain ${output} ipAddress
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]