1717
1818package org .apache .hadoop .hdds .scm .cli .datanode ;
1919
20+ import com .fasterxml .jackson .annotation .JsonInclude ;
2021import com .google .common .base .Strings ;
2122import java .io .IOException ;
2223import java .util .Collections ;
2324import java .util .List ;
25+ import java .util .Objects ;
2426import java .util .UUID ;
2527import java .util .stream .Collectors ;
2628import java .util .stream .Stream ;
@@ -63,6 +65,9 @@ public class ListInfoSubcommand extends ScmSubcommand {
6365 defaultValue = "false" )
6466 private boolean json ;
6567
68+ @ CommandLine .ArgGroup (exclusive = true , multiplicity = "0..1" )
69+ private UsageSortingOptions usageSortingOptions ;
70+
6671 @ CommandLine .Mixin
6772 private ListLimitOptions listLimitOptions ;
6873
@@ -71,6 +76,16 @@ public class ListInfoSubcommand extends ScmSubcommand {
7176
7277 private List <Pipeline > pipelines ;
7378
79+ static class UsageSortingOptions {
80+ @ CommandLine .Option (names = {"--most-used" },
81+ description = "Show datanodes sorted by Utilization (most to least)." )
82+ private boolean mostUsed ;
83+
84+ @ CommandLine .Option (names = {"--least-used" },
85+ description = "Show datanodes sorted by Utilization (least to most)." )
86+ private boolean leastUsed ;
87+ }
88+
7489 @ Override
7590 public void execute (ScmClient scmClient ) throws IOException {
7691 pipelines = scmClient .listPipelines ();
@@ -123,6 +138,38 @@ public void execute(ScmClient scmClient) throws IOException {
123138
124139 private List <DatanodeWithAttributes > getAllNodes (ScmClient scmClient )
125140 throws IOException {
141+
142+ // If sorting is requested
143+ if (usageSortingOptions != null && (usageSortingOptions .mostUsed || usageSortingOptions .leastUsed )) {
144+ boolean sortByMostUsed = usageSortingOptions .mostUsed ;
145+ List <HddsProtos .DatanodeUsageInfoProto > usageInfos = scmClient .getDatanodeUsageInfo (sortByMostUsed ,
146+ Integer .MAX_VALUE );
147+
148+ return usageInfos .stream ()
149+ .map (p -> {
150+ String uuidStr = p .getNode ().getUuid ();
151+ UUID parsedUuid = UUID .fromString (uuidStr );
152+
153+ try {
154+ HddsProtos .Node node = scmClient .queryNode (parsedUuid );
155+ long capacity = p .getCapacity ();
156+ long used = capacity - p .getRemaining ();
157+ double percentUsed = (capacity > 0 ) ? (used * 100.0 ) / capacity : 0.0 ;
158+ return new DatanodeWithAttributes (
159+ DatanodeDetails .getFromProtoBuf (node .getNodeID ()),
160+ node .getNodeOperationalStates (0 ),
161+ node .getNodeStates (0 ),
162+ used ,
163+ capacity ,
164+ percentUsed );
165+ } catch (IOException e ) {
166+ return null ;
167+ }
168+ })
169+ .filter (Objects ::nonNull )
170+ .collect (Collectors .toList ());
171+ }
172+
126173 List <HddsProtos .Node > nodes = scmClient .queryNode (null ,
127174 null , HddsProtos .QueryScope .CLUSTER , "" );
128175
@@ -165,12 +212,24 @@ private void printDatanodeInfo(DatanodeWithAttributes dna) {
165212 System .out .println ("Operational State: " + dna .getOpState ());
166213 System .out .println ("Health State: " + dna .getHealthState ());
167214 System .out .println ("Related pipelines:\n " + pipelineListInfo );
215+
216+ if (dna .getUsed () != null && dna .getCapacity () != null && dna .getUsed () >= 0 && dna .getCapacity () > 0 ) {
217+ System .out .println ("Capacity: " + dna .getCapacity ());
218+ System .out .println ("Used: " + dna .getUsed ());
219+ System .out .printf ("Percentage Used : %.2f%%%n%n" , dna .getPercentUsed ());
220+ }
168221 }
169222
170223 private static class DatanodeWithAttributes {
171224 private DatanodeDetails datanodeDetails ;
172225 private HddsProtos .NodeOperationalState operationalState ;
173226 private HddsProtos .NodeState healthState ;
227+ @ JsonInclude (JsonInclude .Include .NON_NULL )
228+ private Long used = null ;
229+ @ JsonInclude (JsonInclude .Include .NON_NULL )
230+ private Long capacity = null ;
231+ @ JsonInclude (JsonInclude .Include .NON_NULL )
232+ private Double percentUsed = null ;
174233
175234 DatanodeWithAttributes (DatanodeDetails dn ,
176235 HddsProtos .NodeOperationalState opState ,
@@ -180,6 +239,20 @@ private static class DatanodeWithAttributes {
180239 this .healthState = healthState ;
181240 }
182241
242+ DatanodeWithAttributes (DatanodeDetails dn ,
243+ HddsProtos .NodeOperationalState opState ,
244+ HddsProtos .NodeState healthState ,
245+ long used ,
246+ long capacity ,
247+ double percentUsed ) {
248+ this .datanodeDetails = dn ;
249+ this .operationalState = opState ;
250+ this .healthState = healthState ;
251+ this .used = used ;
252+ this .capacity = capacity ;
253+ this .percentUsed = percentUsed ;
254+ }
255+
183256 public DatanodeDetails getDatanodeDetails () {
184257 return datanodeDetails ;
185258 }
@@ -191,5 +264,17 @@ public HddsProtos.NodeOperationalState getOpState() {
191264 public HddsProtos .NodeState getHealthState () {
192265 return healthState ;
193266 }
267+
268+ public Long getUsed () {
269+ return used ;
270+ }
271+
272+ public Long getCapacity () {
273+ return capacity ;
274+ }
275+
276+ public Double getPercentUsed () {
277+ return percentUsed ;
278+ }
194279 }
195280}
0 commit comments