Skip to content

Commit cb9430d

Browse files
HDDS-15587. [Recon] Show 0 for offline DN pending deletion instead of -1 (#10585).
1 parent 2076d7f commit cb9430d

2 files changed

Lines changed: 49 additions & 5 deletions

File tree

hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/__tests__/capacity/Capacity.test.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,50 @@ describe('Capacity Page', () => {
9595
expect(datanodeCard).toHaveTextContent(/FREE SPACE\s*3\s*KB/i);
9696
});
9797

98+
test('clamps pendingBlockSize to 0 when selected datanode reports -1 (offline/unreachable)', async () => {
99+
capacityServer.use(
100+
rest.get('api/v1/pendingDeletion', (req, res, ctx) => {
101+
const component = req.url.searchParams.get('component');
102+
if (component === 'dn') {
103+
return res(
104+
ctx.status(200),
105+
ctx.json({
106+
...mockResponses.DnPendingDeletion,
107+
pendingDeletionPerDataNode: [
108+
{ hostName: 'dn-1', datanodeUuid: 'uuid-1', pendingBlockSize: -1 },
109+
{ hostName: 'dn-2', datanodeUuid: 'uuid-2', pendingBlockSize: 2048 }
110+
]
111+
})
112+
);
113+
}
114+
const map: Record<string, object> = {
115+
scm: mockResponses.ScmPendingDeletion,
116+
om: mockResponses.OmPendingDeletion
117+
};
118+
const body = component ? map[component] : undefined;
119+
return body
120+
? res(ctx.status(200), ctx.json(body))
121+
: res(ctx.status(400), ctx.json({ message: 'Unsupported pending deletion component.' }));
122+
})
123+
);
124+
125+
render(<Capacity />);
126+
127+
const downloadLink = await screen.findByText('Download Insights');
128+
const datanodeCard = downloadLink.closest('.ant-card');
129+
expect(datanodeCard).not.toBeNull();
130+
if (!datanodeCard) {
131+
return;
132+
}
133+
// dn-1 is selected by default; its pendingBlockSize is -1 (offline sentinel).
134+
// PENDING DELETION should show 0 B, not a negative value.
135+
await waitFor(() =>
136+
expect(datanodeCard).toHaveTextContent(/PENDING DELETION\s*0\s*B/i)
137+
);
138+
// USED SPACE = used (4096) + clamped pendingBlockSize (0) = 4 KB
139+
expect(datanodeCard).toHaveTextContent(/USED SPACE\s*4\s*KB/i);
140+
});
141+
98142
test('shows scm-only error state when SCM pending deletion returns sentinel failure values', async () => {
99143
capacityServer.use(
100144
rest.get('api/v1/pendingDeletion', (req, res, ctx) => {

hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/pages/capacity/capacity.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ const Capacity: React.FC<object> = () => {
127127
const selectedDNDetails: DataNodeUsage & { pendingBlockSize: number } = React.useMemo(() => {
128128
const selected = storageDistribution.data.dataNodeUsage.find(datanode => datanode.hostName === selectedDatanode)
129129
?? storageDistribution.data.dataNodeUsage[0];
130+
const dnPendingEntry = dnPendingDeletes.data.pendingDeletionPerDataNode?.find(
131+
dn => dn.hostName === (selected?.hostName ?? selectedDatanode)
132+
) ?? { hostName: "unknown-host", datanodeUuid: "unknown-uuid", pendingBlockSize: 0 };
130133
return {
131134
...(selected ?? {
132135
datanodeUuid: "unknown-uuid",
@@ -138,11 +141,8 @@ const Capacity: React.FC<object> = () => {
138141
minimumFreeSpace: 0,
139142
reserved: 0
140143
}),
141-
...dnPendingDeletes.data.pendingDeletionPerDataNode?.find(dn => dn.hostName === (selected?.hostName ?? selectedDatanode)) ?? {
142-
hostName: "unknown-host",
143-
datanodeUuid: "unknown-uuid",
144-
pendingBlockSize: 0
145-
}
144+
...dnPendingEntry,
145+
pendingBlockSize: Math.max(0, dnPendingEntry.pendingBlockSize)
146146
}
147147
}, [selectedDatanode, storageDistribution.data.dataNodeUsage, dnPendingDeletes.data.pendingDeletionPerDataNode]);
148148

0 commit comments

Comments
 (0)