blob: 38ad390cb85da3ff9c8a6a5491a157a420c3bed7 [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.datanode;
import com.google.common.base.Strings;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.protocol.DatanodeDetails;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.scm.cli.ScmSubcommand;
import org.apache.hadoop.hdds.scm.client.ScmClient;
import org.apache.hadoop.hdds.scm.pipeline.Pipeline;
import picocli.CommandLine;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Handler of list datanodes info command.
*/
@CommandLine.Command(
name = "list",
description = "List info of datanodes",
mixinStandardHelpOptions = true,
versionProvider = HddsVersionProvider.class)
public class ListInfoSubcommand extends ScmSubcommand {
@CommandLine.Option(names = {"--ip"},
description = "Show info by ip address.",
defaultValue = "")
private String ipaddress;
@CommandLine.Option(names = {"--id"},
description = "Show info by datanode UUID.",
defaultValue = "")
private String uuid;
private List<Pipeline> pipelines;
@Override
public void execute(ScmClient scmClient) throws IOException {
pipelines = scmClient.listPipelines();
if (Strings.isNullOrEmpty(ipaddress) && Strings.isNullOrEmpty(uuid)) {
getAllNodes(scmClient).forEach(this::printDatanodeInfo);
} else {
Stream<DatanodeWithAttributes> allNodes = getAllNodes(scmClient).stream();
if (!Strings.isNullOrEmpty(ipaddress)) {
allNodes = allNodes.filter(p -> p.getDatanodeDetails().getIpAddress()
.compareToIgnoreCase(ipaddress) == 0);
}
if (!Strings.isNullOrEmpty(uuid)) {
allNodes = allNodes.filter(p ->
p.getDatanodeDetails().toString().equals(uuid));
}
allNodes.forEach(this::printDatanodeInfo);
}
}
private List<DatanodeWithAttributes> getAllNodes(ScmClient scmClient)
throws IOException {
List<HddsProtos.Node> nodes = scmClient.queryNode(null,
HddsProtos.NodeState.HEALTHY, HddsProtos.QueryScope.CLUSTER, "");
return nodes.stream()
.map(p -> new DatanodeWithAttributes(
DatanodeDetails.getFromProtoBuf(p.getNodeID()),
p.getNodeOperationalStates(0), p.getNodeStates(0)))
.collect(Collectors.toList());
}
private void printDatanodeInfo(DatanodeWithAttributes dna) {
StringBuilder pipelineListInfo = new StringBuilder();
DatanodeDetails datanode = dna.getDatanodeDetails();
int relatedPipelineNum = 0;
if (!pipelines.isEmpty()) {
List<Pipeline> relatedPipelines = pipelines.stream().filter(
p -> p.getNodes().contains(datanode)).collect(Collectors.toList());
if (relatedPipelines.isEmpty()) {
pipelineListInfo.append("No related pipelines" +
" or the node is not in Healthy state.");
} else {
relatedPipelineNum = relatedPipelines.size();
relatedPipelines.forEach(
p -> pipelineListInfo.append(p.getId().getId().toString())
.append("/").append(p.getFactor().toString()).append("/")
.append(p.getType().toString()).append("/")
.append(p.getPipelineState().toString()).append("/")
.append(datanode.getUuid().equals(p.getLeaderId()) ?
"Leader" : "Follower")
.append(System.getProperty("line.separator")));
}
} else {
pipelineListInfo.append("No pipelines in cluster.");
}
System.out.println("Datanode: " + datanode.getUuid().toString() +
" (" + datanode.getNetworkLocation() + "/" + datanode.getIpAddress()
+ "/" + datanode.getHostName() + "/" + relatedPipelineNum +
" pipelines)");
System.out.println("Operational State: " + dna.getOpState());
System.out.println("Related pipelines: \n" + pipelineListInfo);
}
private static class DatanodeWithAttributes {
private DatanodeDetails datanodeDetails;
private HddsProtos.NodeOperationalState operationalState;
private HddsProtos.NodeState healthState;
DatanodeWithAttributes(DatanodeDetails dn,
HddsProtos.NodeOperationalState opState,
HddsProtos.NodeState healthState) {
this.datanodeDetails = dn;
this.operationalState = opState;
this.healthState = healthState;
}
public DatanodeDetails getDatanodeDetails() {
return datanodeDetails;
}
public HddsProtos.NodeOperationalState getOpState() {
return operationalState;
}
public HddsProtos.NodeState getHealthState() {
return healthState;
}
}
}