This is an automated email from the ASF dual-hosted git repository.
smengcl 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 afad5a13de2 HDDS-14560. Show open containers per disk in Recon
datanode view (#10820)
afad5a13de2 is described below
commit afad5a13de270a9a50798f45ba3091003e705b17
Author: Chi-Hsuan Huang <[email protected]>
AuthorDate: Sat Oct 10 12:44:34 2026 +0800
HDDS-14560. Show open containers per disk in Recon datanode view (#10820)
---
.../ozone/container/common/impl/ContainerSet.java | 24 ++++
.../ozone/container/ozoneimpl/OzoneContainer.java | 6 +-
.../container/common/impl/TestContainerSet.java | 29 +++++
.../proto/ScmServerDatanodeHeartbeatProtocol.proto | 2 +
.../hadoop/ozone/recon/api/NodeEndpoint.java | 21 ++++
.../ozone/recon/api/types/DatanodeDiskInfo.java | 128 +++++++++++++++++++++
.../ozone/recon/api/types/DatanodeMetadata.java | 16 +++
.../__tests__/datanodes/DatanodesTable.test.tsx | 37 +++++-
.../src/v2/components/tables/datanodesTable.tsx | 41 +++++++
.../src/v2/pages/datanodes/datanodes.tsx | 3 +-
.../ozone-recon-web/src/v2/types/datanode.types.ts | 12 ++
.../hadoop/ozone/recon/api/TestEndpoints.java | 13 +++
12 files changed, 329 insertions(+), 3 deletions(-)
diff --git
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerSet.java
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerSet.java
index 752fdaf9fd1..99d7358ff2a 100644
---
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerSet.java
+++
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerSet.java
@@ -29,6 +29,7 @@
import java.time.Clock;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -520,6 +521,29 @@ public long containerCount(HddsVolume volume) {
return volume.getContainerCount();
}
+ /**
+ * Count the OPEN containers on each storage volume, keyed by volume
storageID.
+ * Used by the node report so Recon can show open-container distribution per
disk.
+ *
+ * @return map of volume storageID to its OPEN container count
+ */
+ public Map<String, Long> getOpenContainerCountsByVolume() {
+ Map<String, Long> counts = new HashMap<>();
+ Iterator<Map.Entry<Long, Container<?>>> iterator =
getContainerMapIterator();
+ while (iterator.hasNext()) {
+ Container<?> container = iterator.next().getValue();
+ if (container.getContainerState() != State.OPEN) {
+ continue;
+ }
+ HddsVolume volume = container.getContainerData().getVolume();
+ if (volume == null) {
+ continue;
+ }
+ counts.merge(volume.getStorageID(), 1L, Long::sum);
+ }
+ return counts;
+ }
+
/**
* Return an containerMap iterator over {@link ContainerSet#containerMap}.
* @return containerMap Iterator
diff --git
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/OzoneContainer.java
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/OzoneContainer.java
index 93aa878759b..67b7d0b6213 100644
---
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/OzoneContainer.java
+++
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ozoneimpl/OzoneContainer.java
@@ -800,8 +800,12 @@ public
StorageContainerDatanodeProtocolProtos.NodeReportProto getNodeReport()
= StorageContainerDatanodeProtocolProtos.
NodeReportProto.newBuilder();
+ Map<String, Long> openCounts =
getContainerSet().getOpenContainerCountsByVolume();
for (StorageLocationReport report : reports) {
- nrb.addStorageReport(report.getProtoBufMessage());
+ StorageContainerDatanodeProtocolProtos.StorageReportProto proto =
report.getProtoBufMessage();
+ nrb.addStorageReport(proto.toBuilder()
+
.setOpenContainerCount(openCounts.getOrDefault(proto.getStorageUuid(), 0L))
+ .build());
}
StorageLocationReport[] metaReports = metaVolumeSet.getStorageReport();
diff --git
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerSet.java
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerSet.java
index 33b87f220ed..5d8a8854473 100644
---
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerSet.java
+++
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/impl/TestContainerSet.java
@@ -52,6 +52,7 @@
import org.apache.hadoop.conf.StorageUnit;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
+import
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerDataProto.State;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
import
org.apache.hadoop.hdds.scm.container.common.helpers.StorageContainerException;
import org.apache.hadoop.ozone.container.common.interfaces.Container;
@@ -546,6 +547,34 @@ public void
testContainerCountPerVolume(ContainerLayoutVersion layout)
assertEquals(49, containerSet.containerCount(vol2));
}
+ private static KeyValueContainer newContainerOnVolume(long id, HddsVolume
volume, State state) {
+ KeyValueContainerData kvData = new KeyValueContainerData(id,
+ ContainerLayoutVersion.FILE_PER_BLOCK,
+ (long) StorageUnit.GB.toBytes(5), UUID.randomUUID().toString(),
+ UUID.randomUUID().toString());
+ kvData.setVolume(volume);
+ kvData.setState(state);
+ return new KeyValueContainer(kvData, new OzoneConfiguration());
+ }
+
+ @Test
+ public void testGetOpenContainerCountsByVolume() throws
StorageContainerException {
+ ContainerSet containerSet = newContainerSet();
+ HddsVolume volume1 = mockHddsVolume("vol-1");
+ HddsVolume volume2 = mockHddsVolume("vol-2");
+
+ containerSet.addContainer(newContainerOnVolume(1L, volume1, State.OPEN));
+ containerSet.addContainer(newContainerOnVolume(2L, volume1, State.OPEN));
+ containerSet.addContainer(newContainerOnVolume(3L, volume2, State.OPEN));
+ containerSet.addContainer(newContainerOnVolume(4L, volume2, State.CLOSED));
+
+ Map<String, Long> counts = containerSet.getOpenContainerCountsByVolume();
+
+ assertEquals(2, counts.size());
+ assertEquals(2L, counts.get("vol-1"));
+ assertEquals(1L, counts.get("vol-2"));
+ }
+
/**
* Test that per-volume iterator only returns containers from that volume.
*/
diff --git
a/hadoop-hdds/interface-server/src/main/proto/ScmServerDatanodeHeartbeatProtocol.proto
b/hadoop-hdds/interface-server/src/main/proto/ScmServerDatanodeHeartbeatProtocol.proto
index dc06699f4c0..50cf899e823 100644
---
a/hadoop-hdds/interface-server/src/main/proto/ScmServerDatanodeHeartbeatProtocol.proto
+++
b/hadoop-hdds/interface-server/src/main/proto/ScmServerDatanodeHeartbeatProtocol.proto
@@ -203,6 +203,8 @@ message StorageReportProto {
*/
optional uint64 fsCapacity = 11 [default = 0];
optional uint64 fsAvailable = 12 [default = 0];
+ // Number of OPEN containers currently on this storage volume.
+ optional uint64 openContainerCount = 13 [default = 0];
}
message MetadataStorageReportProto {
diff --git
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/NodeEndpoint.java
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/NodeEndpoint.java
index 35397723d25..40ece8b9151 100644
---
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/NodeEndpoint.java
+++
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/NodeEndpoint.java
@@ -51,6 +51,7 @@
import org.apache.hadoop.hdds.protocol.DatanodeID;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState;
+import
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.StorageReportProto;
import org.apache.hadoop.hdds.scm.container.ContainerID;
import org.apache.hadoop.hdds.scm.container.ContainerInfo;
import org.apache.hadoop.hdds.scm.container.ContainerNotFoundException;
@@ -64,6 +65,7 @@
import org.apache.hadoop.hdds.scm.protocol.StorageContainerLocationProtocol;
import org.apache.hadoop.hdds.scm.server.OzoneStorageContainerManager;
import org.apache.hadoop.ozone.ClientVersion;
+import org.apache.hadoop.ozone.recon.api.types.DatanodeDiskInfo;
import org.apache.hadoop.ozone.recon.api.types.DatanodeMetadata;
import org.apache.hadoop.ozone.recon.api.types.DatanodePipeline;
import org.apache.hadoop.ozone.recon.api.types.DatanodeStorageReport;
@@ -161,6 +163,7 @@ public Response getDatanodes() {
.setState(nodeState)
.setPipelines(pipelines)
.setLeaderCount(leaderCount.get())
+ .setDisks(getDisks(datanode))
.build());
});
@@ -192,6 +195,24 @@ private DatanodeStorageReport
getStorageReport(DatanodeDetails datanode) {
return builder.build();
}
+ private List<DatanodeDiskInfo> getDisks(DatanodeInfo datanode) {
+ List<DatanodeDiskInfo> disks = new ArrayList<>();
+ for (StorageReportProto report : datanode.getStorageReports()) {
+ DatanodeDiskInfo.Builder builder = DatanodeDiskInfo.newBuilder()
+ .setStorageUuid(report.getStorageUuid())
+ .setStorageLocation(report.getStorageLocation())
+ .setCapacity(report.getCapacity())
+ .setUsed(report.getScmUsed())
+ .setRemaining(report.getRemaining())
+ .setCommitted(report.getCommitted());
+ if (report.hasOpenContainerCount()) {
+ builder.setOpenContainerCount(report.getOpenContainerCount());
+ }
+ disks.add(builder.build());
+ }
+ return disks;
+ }
+
/**
* Removes datanodes from Recon's memory and nodes table in Recon DB.
* @param uuids the list of datanode uuid's
diff --git
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/types/DatanodeDiskInfo.java
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/types/DatanodeDiskInfo.java
new file mode 100644
index 00000000000..6522570c4ac
--- /dev/null
+++
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/types/DatanodeDiskInfo.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+
+package org.apache.hadoop.ozone.recon.api.types;
+
+/**
+ * Metadata object that contains per-disk storage information for a Datanode.
+ */
+public final class DatanodeDiskInfo {
+ private String storageUuid;
+ private String storageLocation;
+ private long capacity;
+ private long used;
+ private long remaining;
+ private long committed;
+ private Long openContainerCount;
+
+ private DatanodeDiskInfo(Builder builder) {
+ this.storageUuid = builder.storageUuid;
+ this.storageLocation = builder.storageLocation;
+ this.capacity = builder.capacity;
+ this.used = builder.used;
+ this.remaining = builder.remaining;
+ this.committed = builder.committed;
+ this.openContainerCount = builder.openContainerCount;
+ }
+
+ public String getStorageUuid() {
+ return storageUuid;
+ }
+
+ public String getStorageLocation() {
+ return storageLocation;
+ }
+
+ public long getCapacity() {
+ return capacity;
+ }
+
+ public long getUsed() {
+ return used;
+ }
+
+ public long getRemaining() {
+ return remaining;
+ }
+
+ public long getCommitted() {
+ return committed;
+ }
+
+ public Long getOpenContainerCount() {
+ return openContainerCount;
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder class for DatanodeDiskInfo.
+ */
+ public static final class Builder {
+ private String storageUuid = "";
+ private String storageLocation = "";
+ private long capacity = 0;
+ private long used = 0;
+ private long remaining = 0;
+ private long committed = 0;
+ private Long openContainerCount;
+
+ private Builder() {
+ }
+
+ public Builder setStorageUuid(String storageUuid) {
+ this.storageUuid = storageUuid;
+ return this;
+ }
+
+ public Builder setStorageLocation(String storageLocation) {
+ this.storageLocation = storageLocation;
+ return this;
+ }
+
+ public Builder setCapacity(long capacity) {
+ this.capacity = capacity;
+ return this;
+ }
+
+ public Builder setUsed(long used) {
+ this.used = used;
+ return this;
+ }
+
+ public Builder setRemaining(long remaining) {
+ this.remaining = remaining;
+ return this;
+ }
+
+ public Builder setCommitted(long committed) {
+ this.committed = committed;
+ return this;
+ }
+
+ public Builder setOpenContainerCount(long openContainerCount) {
+ this.openContainerCount = openContainerCount;
+ return this;
+ }
+
+ public DatanodeDiskInfo build() {
+ return new DatanodeDiskInfo(this);
+ }
+ }
+}
diff --git
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/types/DatanodeMetadata.java
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/types/DatanodeMetadata.java
index b8fb46d294d..485239a7984 100644
---
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/types/DatanodeMetadata.java
+++
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/types/DatanodeMetadata.java
@@ -18,6 +18,7 @@
package org.apache.hadoop.ozone.recon.api.types;
import com.fasterxml.jackson.annotation.JsonInclude;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
import javax.xml.bind.annotation.XmlAccessType;
@@ -92,6 +93,9 @@ public final class DatanodeMetadata {
@JsonInclude(JsonInclude.Include.NON_NULL)
private String networkLocation;
+ @XmlElement(name = "disks")
+ private List<DatanodeDiskInfo> disks;
+
private DatanodeMetadata(Builder builder) {
this.hostname = builder.hostname;
this.uuid = builder.uuid;
@@ -108,6 +112,7 @@ private DatanodeMetadata(Builder builder) {
this.revision = builder.revision;
this.apparentVersion = builder.apparentVersion;
this.networkLocation = builder.networkLocation;
+ this.disks = builder.disks;
}
public String getHostname() {
@@ -170,6 +175,10 @@ public String getNetworkLocation() {
return networkLocation;
}
+ public List<DatanodeDiskInfo> getDisks() {
+ return disks;
+ }
+
/**
* Returns new builder class that builds a DatanodeMetadata.
*
@@ -198,11 +207,13 @@ public static final class Builder {
private String revision;
private int apparentVersion;
private String networkLocation;
+ private List<DatanodeDiskInfo> disks;
public Builder() {
this.containers = 0;
this.openContainers = 0;
this.leaderCount = 0;
+ this.disks = Collections.emptyList();
}
public Builder setHostname(String hostname) {
@@ -266,6 +277,11 @@ public Builder setDatanode(DatanodeInfo datanode) {
return this;
}
+ public Builder setDisks(List<DatanodeDiskInfo> disks) {
+ this.disks = disks;
+ return this;
+ }
+
/**
* Constructs DatanodeMetadata.
*
diff --git
a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/__tests__/datanodes/DatanodesTable.test.tsx
b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/__tests__/datanodes/DatanodesTable.test.tsx
index 5a5addd38f5..22e8f935383 100644
---
a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/__tests__/datanodes/DatanodesTable.test.tsx
+++
b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/__tests__/datanodes/DatanodesTable.test.tsx
@@ -18,7 +18,7 @@
import React from 'react';
import {vi} from 'vitest';
-import {fireEvent, render, screen} from '@testing-library/react';
+import {fireEvent, render, screen, within} from '@testing-library/react';
import {DatanodeTableProps} from '@/v2/types/datanode.types';
import DatanodesTable from '@/v2/components/tables/datanodesTable';
@@ -155,6 +155,41 @@ describe('DatanodesTable Component', () => {
expect(checkboxes[2]).not.toBeDisabled(); // DEAD node
});
+ test('distinguishes unreported and zero open container counts', () => {
+ const datanode = {
+ ...getDataWith('ozone-datanode-1', 'HEALTHY', 1),
+ disks: [
+ {
+ storageUuid: 'disk-1',
+ storageLocation: '/disk1',
+ capacity: 1000,
+ used: 100,
+ remaining: 900,
+ committed: 0,
+ openContainerCount: null
+ },
+ {
+ storageUuid: 'disk-2',
+ storageLocation: '/disk2',
+ capacity: 1000,
+ used: 100,
+ remaining: 900,
+ committed: 0,
+ openContainerCount: 0
+ }
+ ]
+ };
+ render(<DatanodesTable {...defaultProps} data={[datanode]} />);
+
+ const expandButton = document.querySelector('.ant-table-row-expand-icon');
+ expect(expandButton).not.toBeNull();
+ fireEvent.click(expandButton as HTMLElement);
+
+ const diskTable = screen.getByTestId('dn-disks-1');
+ expect(within(diskTable).getByText('N/A')).toBeInTheDocument();
+ expect(within(diskTable).getByText('0')).toBeInTheDocument();
+ });
+
test('shows filesystem rows in storage tooltip when provided', async () => {
render(
<DatanodesTable
diff --git
a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/tables/datanodesTable.tsx
b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/tables/datanodesTable.tsx
index e5ba3950bf1..1a56ec4f061 100644
---
a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/tables/datanodesTable.tsx
+++
b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/components/tables/datanodesTable.tsx
@@ -40,6 +40,7 @@ import { getTimeDiffFromTimestamp } from
'@/v2/utils/momentUtils';
import {
Datanode,
+ DatanodeDiskInfo,
DatanodeOpState,
DatanodeOpStateList,
DatanodeState,
@@ -294,6 +295,41 @@ const DatanodesTable: React.FC<DatanodeTableProps> = ({
decommissioningUuids = decommissionUuids;
}, [decommissionUuids])
+ function expandedDiskRowRender(record: Datanode) {
+ const diskColumns: ColumnsType<DatanodeDiskInfo> = [
+ { title: 'Disk Location', dataIndex: 'storageLocation', key:
'storageLocation' },
+ {
+ title: 'Open Containers',
+ dataIndex: 'openContainerCount',
+ key: 'openContainerCount',
+ sorter: (a: DatanodeDiskInfo, b: DatanodeDiskInfo) =>
+ (a.openContainerCount ?? Number.MAX_SAFE_INTEGER) -
+ (b.openContainerCount ?? Number.MAX_SAFE_INTEGER),
+ render: (openContainerCount: number | null) => openContainerCount ??
'N/A'
+ },
+ {
+ title: 'Capacity',
+ key: 'capacity',
+ render: (_: unknown, disk: DatanodeDiskInfo) => (
+ <StorageBar
+ capacity={disk.capacity}
+ used={disk.used}
+ remaining={disk.remaining}
+ committed={disk.committed} />
+ )
+ }
+ ];
+ return (
+ <Table
+ rowKey={(disk: DatanodeDiskInfo) => disk.storageUuid}
+ dataSource={record.disks ?? []}
+ columns={diskColumns}
+ pagination={false}
+ size='small'
+ data-testid={`dn-disks-${record.uuid}`} />
+ );
+ }
+
return (
<div>
<Table
@@ -305,6 +341,11 @@ const DatanodesTable: React.FC<DatanodeTableProps> = ({
pagination={paginationConfig}
scroll={{ x: 'max-content', scrollToFirstRowOnChange: true }}
locale={{ filterTitle: '' }}
+ expandable={{
+ expandRowByClick: false,
+ rowExpandable: (record: Datanode) => (record.disks?.length ?? 0) > 0,
+ expandedRowRender: expandedDiskRowRender
+ }}
onRow={(record: Datanode) => ({
'data-testid': `dntable-${record.uuid}`
} as HTMLAttributes<HTMLElement>)}
diff --git
a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/datanodes/datanodes.tsx
b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/datanodes/datanodes.tsx
index 0598bee8dfb..8920988fc4f 100644
---
a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/datanodes/datanodes.tsx
+++
b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/datanodes/datanodes.tsx
@@ -178,7 +178,8 @@ const Datanodes: React.FC<{}> = () => {
setupTime: datanode.setupTime,
revision: datanode.revision,
buildDate: datanode.buildDate,
- networkLocation: datanode.networkLocation
+ networkLocation: datanode.networkLocation,
+ disks: datanode.disks
})
);
diff --git
a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/types/datanode.types.ts
b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/types/datanode.types.ts
index 809c0424962..22499d4d6e3 100644
---
a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/types/datanode.types.ts
+++
b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/types/datanode.types.ts
@@ -35,6 +35,16 @@ export const DatanodeOpStateList = [
] as const;
export type DatanodeOpState = typeof DatanodeOpStateList[number];
+export type DatanodeDiskInfo = {
+ storageUuid: string;
+ storageLocation: string;
+ capacity: number;
+ used: number;
+ remaining: number;
+ committed: number;
+ openContainerCount: number | null;
+}
+
export type DatanodeResponse = {
hostname: string;
state: DatanodeState;
@@ -51,6 +61,7 @@ export type DatanodeResponse = {
revision: string;
buildDate: string;
networkLocation: string;
+ disks?: DatanodeDiskInfo[];
}
export type DatanodesResponse = {
@@ -78,6 +89,7 @@ export type Datanode = {
revision: string;
buildDate: string;
networkLocation: string;
+ disks?: DatanodeDiskInfo[];
}
export type DatanodeDetails = {
diff --git
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestEndpoints.java
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestEndpoints.java
index d58d63c983f..a8a8cab6403 100644
---
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestEndpoints.java
+++
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestEndpoints.java
@@ -116,6 +116,7 @@
import org.apache.hadoop.ozone.recon.api.types.BucketObjectDBInfo;
import org.apache.hadoop.ozone.recon.api.types.BucketsResponse;
import org.apache.hadoop.ozone.recon.api.types.ClusterStateResponse;
+import org.apache.hadoop.ozone.recon.api.types.DatanodeDiskInfo;
import org.apache.hadoop.ozone.recon.api.types.DatanodeMetadata;
import org.apache.hadoop.ozone.recon.api.types.DatanodesResponse;
import org.apache.hadoop.ozone.recon.api.types.PipelineMetadata;
@@ -382,6 +383,7 @@ public void setUp() throws Exception {
.setFsCapacity(40000)
.setFsAvailable(15000)
.setStorageUuid(UUID.randomUUID().toString())
+ .setOpenContainerCount(3)
.setFailed(false).build();
StorageReportProto storageReportProto2 =
StorageReportProto.newBuilder().setStorageType(StorageTypeProto.DISK)
@@ -617,6 +619,17 @@ private void testDatanodeResponse(DatanodeMetadata
datanodeMetadata)
assertEquals(pipeline.getLeaderNode().getHostName(),
datanodeMetadata.getPipelines().get(0).getLeaderNode());
assertEquals(1, datanodeMetadata.getLeaderCount());
+ assertEquals(2, datanodeMetadata.getDisks().size());
+ DatanodeDiskInfo disk1 = datanodeMetadata.getDisks().stream()
+ .filter(d -> "/disk1".equals(d.getStorageLocation()))
+ .findFirst().orElse(null);
+ assertNotNull(disk1);
+ assertEquals(3L, disk1.getOpenContainerCount());
+ DatanodeDiskInfo disk2 = datanodeMetadata.getDisks().stream()
+ .filter(d -> "/disk2".equals(d.getStorageLocation()))
+ .findFirst().orElse(null);
+ assertNotNull(disk2);
+ assertNull(disk2.getOpenContainerCount());
break;
case HOST2:
assertEquals(130000,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]