blob: bb442e00b50a12506ae95583b1c26b234bc0586d [file] [log] [blame]
/*
* 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.hdds.scm.cli;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.TreeSet;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.cli.OzoneAdmin;
import org.apache.hadoop.hdds.cli.SubcommandWithParent;
import org.apache.hadoop.hdds.protocol.DatanodeDetails;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.scm.client.ScmClient;
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.kohsuke.MetaInfServices;
import picocli.CommandLine;
/**
* Handler of printTopology command.
*/
@CommandLine.Command(
name = "printTopology",
description = "Print a tree of the network topology as reported by SCM",
mixinStandardHelpOptions = true,
versionProvider = HddsVersionProvider.class)
@MetaInfServices(SubcommandWithParent.class)
public class TopologySubcommand extends ScmSubcommand
implements SubcommandWithParent {
private static final List<HddsProtos.NodeState> STATES = new ArrayList<>();
static {
STATES.add(HEALTHY);
STATES.add(STALE);
STATES.add(DEAD);
}
@CommandLine.Option(names = {"-o", "--order"},
description = "Print Topology ordered by network location")
private boolean order;
@CommandLine.Option(names = {"-f", "--full"},
description = "Print Topology with full node infos")
private boolean fullInfo;
@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 (order) {
printOrderedByLocation(nodes);
} else {
printNodesWithLocation(nodes);
}
}
}
}
public Class<?> getParentType() {
return OzoneAdmin.class;
}
// 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 =
new HashMap<>();
for (HddsProtos.Node node : nodes) {
String location = node.getNodeID().getNetworkLocation();
if (location != null && !tree.containsKey(location)) {
tree.put(location, new TreeSet<>());
}
DatanodeDetails dn = DatanodeDetails.getFromProtoBuf(node.getNodeID());
tree.get(location).add(dn);
state.put(dn, node.getNodeOperationalStates(0));
}
ArrayList<String> locations = new ArrayList<>(tree.keySet());
Collections.sort(locations);
locations.forEach(location -> {
System.out.println("Location: " + location);
tree.get(location).forEach(n -> {
System.out.println(" " + n.getIpAddress() + "(" + n.getHostName()
+ ") "+state.get(n));
});
});
}
private String formatPortOutput(List<HddsProtos.Port> ports) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ports.size(); i++) {
HddsProtos.Port port = ports.get(i);
sb.append(port.getName()).append("=").append(port.getValue());
if (i < ports.size() - 1) {
sb.append(",");
}
}
return sb.toString();
}
private String getAdditionNodeOutput(HddsProtos.Node node) {
return fullInfo ? node.getNodeID().getUuid() + "/" : "";
}
// Format "ipAddress(hostName):PortName1=PortValue1 OperationalState
// networkLocation
private void printNodesWithLocation(Collection<HddsProtos.Node> nodes) {
nodes.forEach(node -> {
System.out.print(" " + getAdditionNodeOutput(node) +
node.getNodeID().getIpAddress() + "(" +
node.getNodeID().getHostName() + ")" +
":" + formatPortOutput(node.getNodeID().getPortsList()));
System.out.println(" "
+ node.getNodeOperationalStates(0) + " " +
(node.getNodeID().getNetworkLocation() != null ?
node.getNodeID().getNetworkLocation() : "NA"));
});
}
}