Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -745,8 +745,9 @@ public static List<VolumeReportProto> buildVolumeReportProto(List<VolumeFixedUsa
HddsVolume volume = v.getVolume();
VolumeReportProto.Builder builder = VolumeReportProto.newBuilder()
.setStorageId(volume.getStorageID())
.setTotalCapacity(v.getUsage().getCapacity())
.setUsedSpace(v.getUsage().getUsedSpace())
.setOzoneCapacity(v.getUsage().getCapacity())
.setOzoneAvailable(v.getUsage().getAvailable())
.setOzoneUsedSpace(v.getUsage().getUsedSpace())
.setCommittedBytes(volume.getCommittedBytes())
.setEffectiveUsedSpace(v.getEffectiveUsed())
.setUtilization(v.getUtilization());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,19 @@ void setup() throws IOException {
.setStoragePath(TEST_STORAGE_PATH_1)
.setUtilization(TEST_UTILIZATION_1)
.setCommittedBytes(TEST_COMMITTED_BYTES_1)
.setTotalCapacity(TEST_TOTAL_CAPACITY)
.setUsedSpace(TEST_USED_SPACE_1)
.setOzoneCapacity(TEST_TOTAL_CAPACITY)
.setOzoneAvailable(TEST_TOTAL_CAPACITY - TEST_USED_SPACE_1)
.setOzoneUsedSpace(TEST_USED_SPACE_1)
.setEffectiveUsedSpace(TEST_EFFECTIVE_USED_SPACE_1)
.build(),
VolumeReportProto.newBuilder()
.setStorageId(TEST_STORAGE_ID_2)
.setStoragePath(TEST_STORAGE_PATH_2)
.setUtilization(TEST_UTILIZATION_2)
.setCommittedBytes(TEST_COMMITTED_BYTES_2)
.setTotalCapacity(TEST_TOTAL_CAPACITY)
.setUsedSpace(TEST_USED_SPACE_2)
.setOzoneCapacity(TEST_TOTAL_CAPACITY)
.setOzoneAvailable(TEST_TOTAL_CAPACITY - TEST_USED_SPACE_2)
.setOzoneUsedSpace(TEST_USED_SPACE_2)
.setEffectiveUsedSpace(TEST_EFFECTIVE_USED_SPACE_2)
.build()));

Expand Down Expand Up @@ -156,15 +158,17 @@ void testGetDiskBalancerInfoReport() throws IOException {
assertEquals(TEST_STORAGE_PATH_1, volReport0.getStoragePath());
assertEquals(TEST_UTILIZATION_1, volReport0.getUtilization());
assertEquals(TEST_COMMITTED_BYTES_1, volReport0.getCommittedBytes());
assertEquals(TEST_TOTAL_CAPACITY, volReport0.getTotalCapacity());
assertEquals(TEST_USED_SPACE_1, volReport0.getUsedSpace());
assertEquals(TEST_TOTAL_CAPACITY, volReport0.getOzoneCapacity());
assertEquals(TEST_TOTAL_CAPACITY - TEST_USED_SPACE_1, volReport0.getOzoneAvailable());
assertEquals(TEST_USED_SPACE_1, volReport0.getOzoneUsedSpace());
assertEquals(TEST_EFFECTIVE_USED_SPACE_1, volReport0.getEffectiveUsedSpace());
assertEquals(TEST_STORAGE_ID_2, volReport1.getStorageId());
assertEquals(TEST_STORAGE_PATH_2, volReport1.getStoragePath());
assertEquals(TEST_UTILIZATION_2, volReport1.getUtilization());
assertEquals(TEST_COMMITTED_BYTES_2, volReport1.getCommittedBytes());
assertEquals(TEST_TOTAL_CAPACITY, volReport1.getTotalCapacity());
assertEquals(TEST_USED_SPACE_2, volReport1.getUsedSpace());
assertEquals(TEST_TOTAL_CAPACITY, volReport1.getOzoneCapacity());
assertEquals(TEST_TOTAL_CAPACITY - TEST_USED_SPACE_2, volReport1.getOzoneAvailable());
assertEquals(TEST_USED_SPACE_2, volReport1.getOzoneUsedSpace());
assertEquals(TEST_EFFECTIVE_USED_SPACE_2, volReport1.getEffectiveUsedSpace());
}

Expand Down
5 changes: 3 additions & 2 deletions hadoop-hdds/interface-client/src/main/proto/hdds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -586,11 +586,12 @@ enum DiskBalancerRunningStatus {
message VolumeReportProto {
optional string storageId = 1;
optional string storagePath = 2;
optional uint64 totalCapacity = 3;
optional uint64 usedSpace = 4;
optional uint64 ozoneCapacity = 3;
optional uint64 ozoneUsedSpace = 4;
optional uint64 committedBytes = 5;
optional uint64 effectiveUsedSpace = 6;
optional double utilization = 7;
optional uint64 ozoneAvailable = 8;
}

message DatanodeDiskBalancerInfoProto {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,22 @@ public class DatanodeParameters extends ItemsFromStdin {
@CommandLine.Spec
private CommandLine.Model.CommandSpec spec;

@CommandLine.Parameters(description = "Datanode addresses: one or more, separated by spaces." +
" To read from stdin, specify '-' and supply one item per line." +
"Port is optional and defaults to 19864 (CLIENT_RPC port). " +
"Examples: 'DN-1', 'DN-1:19864', '192.168.1.10'. ",
@CommandLine.Parameters(
description = {
"Datanode addresses: one or more on the command line, OR read from stdin with '-'.",
"Stdin usage:",
" ozone admin datanode diskbalancer <subcommand> -",
" Then type one datanode per line and end input:",
" - Linux/macOS: Ctrl-D",
" - Windows: Ctrl-Z, then Enter",
"Examples:",
" # Piped (recommended for scripts)",
" echo -e \"DN-1\\nDN-2\" | ozone admin datanode diskbalancer status -",
" # From file having list of dns to balance",
" ozone admin datanode diskbalancer report - < datanode-lists.txt",
"Port is optional and defaults to 19864 (CLIENT_RPC port).",
"Address examples: 'DN-1', 'DN-1:19864', '192.168.1.10'."
},
arity = "0..*",
paramLabel = "<datanode address>")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.apache.hadoop.hdds.scm.cli.datanode;

import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_DATANODE_DISK_BALANCER_ENABLED_KEY;

import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import picocli.CommandLine.Command;

Expand Down Expand Up @@ -155,11 +157,10 @@

@Command(
name = "diskbalancer",
description = "DiskBalancer specific operations. It is disabled by default." +
" To enable it, set 'hdds.datanode.disk.balancer.enabled' as true",
description = "DiskBalancer specific operations to ensure even disk utilization." +
" It is disabled by default. To enable it, set " + HDDS_DATANODE_DISK_BALANCER_ENABLED_KEY + " as true.",
mixinStandardHelpOptions = true,
versionProvider = HddsVersionProvider.class,
hidden = true,
subcommands = {
DiskBalancerStartSubcommand.class,
DiskBalancerStopSubcommand.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
Expand All @@ -46,6 +47,8 @@ public class DiskBalancerReportSubcommand extends AbstractDiskBalancerSubCommand
private final Map<String, DatanodeDiskBalancerInfoProto> reports =
new ConcurrentHashMap<>();

private static final String PERCENT_FORMAT = "%.2f%%";

@Override
protected Object executeCommand(String hostName) throws IOException {
DiskBalancerProtocol diskBalancerProxy = DiskBalancerSubCommandUtil
Expand Down Expand Up @@ -101,7 +104,8 @@ private String generateReport(List<DatanodeDiskBalancerInfoProto> protos) {

StringBuilder header = new StringBuilder();
header.append("Datanode: ").append(dn).append(System.lineSeparator())
.append("Aggregate VolumeDataDensity: ").append(p.getCurrentVolumeDensitySum())
.append("Aggregate VolumeDataDensity: ")
.append(formatPercent(p.getCurrentVolumeDensitySum()))
.append(System.lineSeparator());

if (p.hasIdealUsage() && p.hasDiskBalancerConf()
Expand All @@ -110,10 +114,11 @@ private String generateReport(List<DatanodeDiskBalancerInfoProto> protos) {
double threshold = p.getDiskBalancerConf().getThreshold();
double lt = idealUsage - threshold / 100.0;
double ut = idealUsage + threshold / 100.0;
header.append("IdealUsage: ").append(String.format("%.8f", idealUsage))
.append(" | Threshold: ").append(threshold).append('%')
.append(" | ThresholdRange: (").append(String.format("%.8f", lt))
.append(", ").append(String.format("%.8f", ut)).append(')')
header.append("IdealUsage: ").append(formatPercent(idealUsage))
.append(" | Threshold: ")
.append(String.format(Locale.ROOT, PERCENT_FORMAT, threshold))
.append(" | ThresholdRange: (").append(formatPercent(lt))
.append(", ").append(formatPercent(ut)).append(')')
.append(System.lineSeparator())
.append(System.lineSeparator())
.append("Volume Details:").append(System.lineSeparator());
Expand All @@ -122,27 +127,29 @@ private String generateReport(List<DatanodeDiskBalancerInfoProto> protos) {
contentList.add(header.toString());

if (p.getVolumeInfoCount() > 0 && p.hasIdealUsage()) {
formatBuilder.append("%-45s %-40s %15s %15s %30s %20s %15s %15s%n");
formatBuilder.append("%-45s %-40s %15s %15s %15s %30s %20s %15s %15s%n");
contentList.add("StorageID");
contentList.add("StoragePath");
contentList.add("TotalCapacity");
contentList.add("UsedSpace");
contentList.add("Container Pre-AllocatedSpace");
contentList.add("OzoneCapacity");
contentList.add("OzoneAvailable");
contentList.add("OzoneUsed");
contentList.add("ContainerPreAllocatedSpace");
contentList.add("EffectiveUsedSpace");
contentList.add("Utilization");
contentList.add("VolumeDensity");

double ideal = p.getIdealUsage();
for (VolumeReportProto v : p.getVolumeInfoList()) {
formatBuilder.append("%-45s %-40s %15s %15s %30s %20s %15s %15s%n");
formatBuilder.append("%-45s %-40s %15s %15s %15s %30s %20s %15s %15s%n");
contentList.add(v.hasStorageId() ? v.getStorageId() : "-");
Comment thread
Gargi-jais11 marked this conversation as resolved.
contentList.add(v.hasStoragePath() ? v.getStoragePath() : "-");
contentList.add(v.hasTotalCapacity() ? StringUtils.byteDesc(v.getTotalCapacity()) : "-");
contentList.add(v.hasUsedSpace() ? StringUtils.byteDesc(v.getUsedSpace()) : "-");
contentList.add(v.hasOzoneCapacity() ? StringUtils.byteDesc(v.getOzoneCapacity()) : "-");
contentList.add(v.hasOzoneAvailable() ? StringUtils.byteDesc(v.getOzoneAvailable()) : "-");
contentList.add(v.hasOzoneUsedSpace() ? StringUtils.byteDesc(v.getOzoneUsedSpace()) : "-");
contentList.add(StringUtils.byteDesc(v.getCommittedBytes()));
contentList.add(v.hasEffectiveUsedSpace() ? StringUtils.byteDesc(v.getEffectiveUsedSpace()) : "-");
contentList.add(String.format("%.8f", v.getUtilization()));
contentList.add(String.format("%.8f", Math.abs(v.getUtilization() - ideal)));
contentList.add(formatPercent(v.getUtilization()));
contentList.add(formatPercent(Math.abs(v.getUtilization() - ideal)));
}
formatBuilder.append("%n");
}
Expand All @@ -155,17 +162,21 @@ private String generateReport(List<DatanodeDiskBalancerInfoProto> protos) {
formatBuilder.append("%nNote:%n")
.append(" - Aggregate VolumeDataDensity: Sum of per-volume density (deviation from ideal);")
.append(" higher means more imbalance.%n")
.append(" - IdealUsage: Target utilization ratio (0-1) when volumes are evenly balanced.%n")
.append(" - IdealUsage: Target utilization (0-100%%) when volumes are evenly balanced.%n")
.append(" - ThresholdRange: Acceptable deviation (percent); volumes within")
.append(" IdealUsage +/- Threshold are considered balanced.%n")
.append(" - VolumeDensity: Deviation of a particular volume's utilization from IdealUsage.%n")
.append(" - Utilization: Ratio of actual used space to capacity (0-1) for a particular volume.%n")
.append(" - TotalCapacity: Total volume capacity.%n")
.append(" - UsedSpace: Ozone used space.%n")
.append(" - Container Pre-AllocatedSpace: Space reserved for containers not yet written to disk.%n")
.append(" - Utilization: how much a particular volume is utilized ")
.append("effectiveUsedSpace / ozoneCapacity) in %%.%n")
.append(" - OzoneCapacity: Ozone volume capacity.%n")
.append(" - OzoneAvailable: Ozone available space.%n")
.append(" - OzoneUsed: Ozone used space.%n")
.append(" - ContainerPreAllocatedSpace: Space reserved for containers not yet written to disk.%n")
.append(" - EffectiveUsedSpace: This is the actual used space of volume which is visible")
.append(" to the diskBalancer : (ozoneCapacity minus ozoneAvailable) + containerPreAllocatedSpace + ")
.append("move delta for source volume.%n");
.append("move delta.%n")
.append(" - move delta: source volume space to be reclaimed after move completion;" +
" this value is reflected only when diskBalancer is running else it is 0.%n");

return String.format(formatBuilder.toString(), contentList.toArray(new String[0]));
}
Expand All @@ -175,6 +186,10 @@ protected String getActionName() {
return "report";
}

private static String formatPercent(double ratio) {
return String.format(Locale.US, PERCENT_FORMAT, ratio * 100.0);
}

/**
* Create a JSON result map for a report.
*
Expand All @@ -186,17 +201,18 @@ private Map<String, Object> toJson(DatanodeDiskBalancerInfoProto report) {
result.put("datanode", DiskBalancerSubCommandUtil.getDatanodeHostAndIp(report.getNode()));
result.put("action", "report");
result.put("status", "success");
result.put("volumeDensity", report.getCurrentVolumeDensitySum());
result.put("volumeDensity", formatPercent(report.getCurrentVolumeDensitySum()));

if (report.hasIdealUsage() && report.hasDiskBalancerConf()
&& report.getDiskBalancerConf().hasThreshold()) {
double idealUsage = report.getIdealUsage();
double threshold = report.getDiskBalancerConf().getThreshold();
double lt = idealUsage - threshold / 100.0;
double ut = idealUsage + threshold / 100.0;
result.put("idealUsage", String.format("%.8f", idealUsage));
result.put("threshold %", report.getDiskBalancerConf().getThreshold());
result.put("thresholdRange", String.format("(%.08f, %.08f)", lt, ut));
result.put("idealUsage", formatPercent(idealUsage));
result.put("threshold %", String.format(Locale.ROOT, PERCENT_FORMAT, threshold));
result.put("thresholdRange", String.format("(%s, %s)",
formatPercent(lt), formatPercent(ut)));
}

if (report.getVolumeInfoCount() > 0) {
Expand All @@ -206,13 +222,14 @@ private Map<String, Object> toJson(DatanodeDiskBalancerInfoProto report) {
Map<String, Object> vm = new LinkedHashMap<>();
vm.put("storageId", v.getStorageId());
vm.put("storagePath", v.hasStoragePath() ? v.getStoragePath() : "-");
vm.put("totalCapacity", v.hasTotalCapacity() ? StringUtils.byteDesc(v.getTotalCapacity()) : "-");
vm.put("usedSpace", v.hasUsedSpace() ? StringUtils.byteDesc(v.getUsedSpace()) : "-");
vm.put("ozoneCapacity", v.hasOzoneCapacity() ? StringUtils.byteDesc(v.getOzoneCapacity()) : "-");
vm.put("ozoneAvailable", v.hasOzoneAvailable() ? StringUtils.byteDesc(v.getOzoneAvailable()) : "-");
vm.put("ozoneUsed", v.hasOzoneUsedSpace() ? StringUtils.byteDesc(v.getOzoneUsedSpace()) : "-");
vm.put("containerPreAllocatedSpace", StringUtils.byteDesc(v.getCommittedBytes()));
vm.put("effectiveUsedSpace", v.hasEffectiveUsedSpace() ?
StringUtils.byteDesc(v.getEffectiveUsedSpace()) : "-");
vm.put("utilization", v.getUtilization());
vm.put("volumeDensity", Math.abs(v.getUtilization() - ideal));
vm.put("utilization", formatPercent(v.getUtilization()));
vm.put("volumeDensity", formatPercent(Math.abs(v.getUtilization() - ideal)));
vols.add(vm);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -638,8 +638,9 @@ public void testReportDiskBalancerWithJson() throws Exception {
assertTrue(output.contains("\"volumes\""));
assertTrue(output.contains("\"storageId\""));
assertTrue(output.contains("\"storagePath\""));
assertTrue(output.contains("\"totalCapacity\""));
assertTrue(output.contains("\"usedSpace\""));
assertTrue(output.contains("\"ozoneCapacity\""));
assertTrue(output.contains("\"ozoneAvailable\""));
assertTrue(output.contains("\"ozoneUsed\""));
assertTrue(output.contains("\"effectiveUsedSpace\""));
assertTrue(output.contains("\"utilization\""));
assertTrue(output.contains("\"volumeDensity\""));
Expand Down Expand Up @@ -791,6 +792,8 @@ private DatanodeDiskBalancerInfoProto generateRandomReportProto(String hostname)
double util2 = idealUsage - random.nextDouble() * 0.1;
long used1 = (long) (capacity1 * util1);
long used2 = (long) (capacity2 * util2);
long available1 = capacity1 - used1;
long available2 = capacity2 - used2;
long effective1 = used1 + committed1;
long effective2 = used2 + committed2;
String path1 = "/data/hdds-" + hostname + "-1";
Expand All @@ -800,17 +803,19 @@ private DatanodeDiskBalancerInfoProto generateRandomReportProto(String hostname)
.setStoragePath(path1)
.setUtilization(util1)
.setCommittedBytes(committed1)
.setTotalCapacity(capacity1)
.setUsedSpace(used1)
.setOzoneCapacity(capacity1)
.setOzoneAvailable(available1)
.setOzoneUsedSpace(used1)
.setEffectiveUsedSpace(effective1)
.build();
VolumeReportProto vol2 = VolumeReportProto.newBuilder()
.setStorageId("DISK-" + hostname + "-vol2")
.setStoragePath(path2)
.setUtilization(util2)
.setCommittedBytes(committed2)
.setTotalCapacity(capacity2)
.setUsedSpace(used2)
.setOzoneCapacity(capacity2)
.setOzoneAvailable(available2)
.setOzoneUsedSpace(used2)
.setEffectiveUsedSpace(effective2)
.build();

Expand Down