Skip to content

Commit da03b66

Browse files
fix: use SlotSize as VDisk size limit if AvailableSize is 0 (#2996)
1 parent 74c6dd1 commit da03b66

File tree

10 files changed

+153
-33
lines changed

10 files changed

+153
-33
lines changed

src/components/DiskStateProgressBar/DiskStateProgressBar.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ export function DiskStateProgressBar({
4444
return <div className={b('fill-bar', mods)} style={{width: '100%'}} />;
4545
}
4646

47-
const fillWidth = inverted ? 100 - diskAllocatedPercent : diskAllocatedPercent;
47+
// diskAllocatedPercent could be more than 100
48+
let fillWidth = Math.min(diskAllocatedPercent, 100);
49+
if (inverted) {
50+
fillWidth = Math.max(100 - diskAllocatedPercent, 0);
51+
}
4852

4953
if (diskAllocatedPercent >= 0) {
5054
return <div className={b('fill-bar', mods)} style={{width: `${fillWidth}%`}} />;

src/components/VDiskInfo/VDiskInfo.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export function VDiskInfo<T extends PreparedVDisk>({
4949

5050
const {
5151
AllocatedSize,
52+
SizeLimit,
5253
DiskSpace,
5354
FrontQueues,
5455
Guid,
@@ -60,7 +61,6 @@ export function VDiskInfo<T extends PreparedVDisk>({
6061
VDiskSlotId,
6162
Kind,
6263
SatisfactionRank,
63-
AvailableSize,
6464
HasUnreadableBlobs,
6565
IncarnationGuid,
6666
InstanceGuid,
@@ -83,13 +83,14 @@ export function VDiskInfo<T extends PreparedVDisk>({
8383
value: VDiskState,
8484
});
8585
}
86-
if (Number(AllocatedSize) >= 0 && Number(AvailableSize) >= 0) {
86+
87+
if (Number(AllocatedSize) >= 0 && Number(SizeLimit) >= 0) {
8788
leftColumn.push({
8889
label: vDiskInfoKeyset('size'),
8990
value: (
9091
<ProgressViewer
9192
value={AllocatedSize}
92-
capacity={Number(AllocatedSize) + Number(AvailableSize)}
93+
capacity={SizeLimit}
9394
formatValues={formatStorageValuesToGb}
9495
colorizeProgress={true}
9596
/>

src/store/reducers/pdisk/__tests__/preparePDiskDataResponse.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,4 +255,38 @@ describe('preparePDiskDataResponse', () => {
255255
1,
256256
);
257257
});
258+
259+
test('Should use used size as total for VDisk slot when used size exceeds size limit', () => {
260+
const dataWithExceededVDiskUsage: TPDiskInfoResponse = {
261+
...rawData,
262+
Whiteboard: {
263+
...rawData.Whiteboard,
264+
PDisk: {
265+
...rawData.Whiteboard?.PDisk,
266+
EnforcedDynamicSlotSize: '15000000000', // 15GB slot size
267+
},
268+
VDisks: [
269+
{
270+
...rawData.Whiteboard?.VDisks?.[0],
271+
AllocatedSize: '20000000000', // 20GB used (exceeds 15GB slot size)
272+
AvailableSize: '0', // 0 available, so slot size should be used as limit
273+
},
274+
],
275+
},
276+
BSC: {
277+
...rawData.BSC,
278+
PDisk: {
279+
...rawData.BSC?.PDisk,
280+
EnforcedDynamicSlotSize: '15000000000', // 15GB slot size
281+
},
282+
},
283+
};
284+
const preparedData = preparePDiskDataResponse([dataWithExceededVDiskUsage, {}]);
285+
286+
const vDiskSlot = preparedData.SlotItems?.find((slot) => slot.SlotType === 'vDisk');
287+
288+
expect(vDiskSlot?.Used).toEqual(20_000_000_000); // 20GB used
289+
// Since used (20GB) > sizeLimit (15GB), total should be set to used size
290+
expect(vDiskSlot?.Total).toEqual(20_000_000_000); // Total equals used when used exceeds limit
291+
});
258292
});

src/store/reducers/pdisk/utils.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,22 @@ export function preparePDiskDataResponse([pdiskResponse = {}, nodeResponse]: [
7070
// VDisks with their full statuses can be seen in popup on hover, in Storage table and on vdisks pages
7171
const slotSeverity = getSpaceSeverity(preparedVDisk.AllocatedPercent);
7272

73+
const used = Number(preparedVDisk.AllocatedSize);
74+
let total = Number(preparedVDisk.SizeLimit);
75+
76+
// In case used size is more than limit
77+
// use used size as total to show correct slot relative size
78+
if (used > total) {
79+
total = used;
80+
}
81+
7382
return {
7483
SlotType: 'vDisk',
7584
Id: preparedVDisk.VDiskId?.GroupID,
7685
Title: preparedVDisk.StoragePoolName,
7786
Severity: slotSeverity,
78-
Used: Number(preparedVDisk.AllocatedSize),
79-
Total: Number(preparedVDisk.TotalSize),
87+
Used: used,
88+
Total: total,
8089
UsagePercent: preparedVDisk.AllocatedPercent,
8190

8291
SlotData: preparedVDisk,

src/store/reducers/storage/__tests__/prepareGroupsDisks.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ describe('prepareGroupsVDisk', () => {
9191

9292
AllocatedSize: 30943477760,
9393
AvailableSize: 234461593600,
94-
TotalSize: 265405071360,
94+
SizeLimit: 265405071360,
9595
AllocatedPercent: 11,
9696

9797
Donors: undefined,
@@ -134,7 +134,7 @@ describe('prepareGroupsVDisk', () => {
134134

135135
AllocatedSize: 30943477760,
136136
AvailableSize: 234461593600,
137-
TotalSize: 265405071360,
137+
SizeLimit: 265405071360,
138138
AllocatedPercent: 11,
139139

140140
PDisk: {
@@ -236,7 +236,7 @@ describe('prepareGroupsVDisk', () => {
236236

237237
AllocatedSize: 30943477760,
238238
AvailableSize: 234461593600,
239-
TotalSize: 265405071360,
239+
SizeLimit: 265405071360,
240240
AllocatedPercent: 11,
241241

242242
Donors: undefined,

src/store/reducers/storage/prepareGroupsDisks.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ export function prepareGroupsVDisk(data: TStorageVDisk = {}): PreparedVDisk {
2525
const Severity = calculateVDiskSeverity(mergedVDiskData);
2626

2727
const vDiskSizeFields = prepareVDiskSizeFields({
28-
AvailableSize: mergedVDiskData.AvailableSize ?? PDisk?.AvailableSize,
28+
AvailableSize: mergedVDiskData.AvailableSize,
2929
AllocatedSize: mergedVDiskData.AllocatedSize,
30+
SlotSize: PDisk?.SlotSize,
3031
});
3132

3233
const preparedDonors = bscVDisk.Donors?.map((donor) => {

src/store/reducers/vdisk/utils.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import type {StorageGroupsResponse} from '../../../types/api/storage';
22
import type {TEvSystemStateResponse} from '../../../types/api/systemState';
3-
import {
4-
prepareWhiteboardPDiskData,
5-
prepareWhiteboardVDiskData,
6-
} from '../../../utils/disks/prepareDisks';
73
import {prepareNodeSystemState} from '../../../utils/nodes';
4+
import {prepareGroupsVDisk} from '../storage/prepareGroupsDisks';
85

96
import type {VDiskData} from './types';
107

@@ -18,21 +15,20 @@ export function prepareVDiskDataResponse(
1815
const rawVDisk = storageGroupResponse?.StorageGroups?.[0].VDisks?.find(
1916
({VDiskId}) => VDiskId === vDiskId,
2017
);
21-
const preparedVDisk = prepareWhiteboardVDiskData(rawVDisk?.Whiteboard);
2218

23-
const rawPDisk = rawVDisk?.PDisk?.Whiteboard;
24-
const preparedPDisk = prepareWhiteboardPDiskData(rawPDisk);
19+
const preparedVDisk = prepareGroupsVDisk(rawVDisk);
20+
const preparedPDisk = preparedVDisk.PDisk;
2521

2622
const rawNode = nodeResponse?.SystemStateInfo?.[0];
2723
const preparedNode = prepareNodeSystemState(rawNode);
2824

29-
const NodeId = preparedVDisk.NodeId ?? preparedPDisk.NodeId ?? preparedNode.NodeId;
25+
const NodeId = preparedVDisk.NodeId ?? preparedPDisk?.NodeId ?? preparedNode.NodeId;
3026
const NodeHost = preparedNode.Host;
3127
const NodeType = preparedNode.Roles?.[0];
3228
const NodeDC = preparedNode.DC;
3329

34-
const PDiskId = preparedVDisk.PDiskId ?? preparedPDisk.PDiskId;
35-
const PDiskType = preparedPDisk.Type;
30+
const PDiskId = preparedVDisk.PDiskId ?? preparedPDisk?.PDiskId;
31+
const PDiskType = preparedPDisk?.Type;
3632

3733
return {
3834
...preparedVDisk,

src/utils/disks/__test__/prepareDisks.test.ts

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ describe('prepareWhiteboardVDiskData', () => {
9090

9191
AvailableSize: 188523479040,
9292
AllocatedSize: 8996782080,
93-
TotalSize: 197520261120,
93+
SizeLimit: 197520261120,
9494
AllocatedPercent: 4,
9595
};
9696

@@ -180,29 +180,92 @@ describe('prepareWhiteboardPDiskData', () => {
180180
});
181181

182182
describe('prepareVDiskSizeFields', () => {
183-
test('Should prepare VDisk size fields', () => {
183+
test('Should prepare VDisk size fields with allocated + available as size limit', () => {
184184
expect(
185185
prepareVDiskSizeFields({
186186
AvailableSize: '400',
187187
AllocatedSize: '100',
188+
SlotSize: '500',
188189
}),
189190
).toEqual({
190191
AvailableSize: 400,
191192
AllocatedSize: 100,
192-
TotalSize: 500,
193-
AllocatedPercent: 20,
193+
SizeLimit: 500, // allocated (100) + available (400) = 500
194+
AllocatedPercent: 20, // 100 / 500 * 100 = 20%
194195
});
195196
});
196-
test('Returns NaN if on undefined data', () => {
197+
198+
test('Should use SlotSize as size limit when AvailableSize is 0', () => {
199+
expect(
200+
prepareVDiskSizeFields({
201+
AvailableSize: '0',
202+
AllocatedSize: '500',
203+
SlotSize: '500',
204+
}),
205+
).toEqual({
206+
AvailableSize: 0,
207+
AllocatedSize: 500,
208+
SizeLimit: 500, // SlotSize is used when available is 0
209+
AllocatedPercent: 100, // 500 / 500 * 100 = 100%
210+
});
211+
});
212+
213+
test('Should use SlotSize as size limit when AvailableSize is undefined', () => {
214+
expect(
215+
prepareVDiskSizeFields({
216+
AvailableSize: undefined,
217+
AllocatedSize: '300',
218+
SlotSize: '500',
219+
}),
220+
).toEqual({
221+
AvailableSize: 0,
222+
AllocatedSize: 300,
223+
SizeLimit: 500, // SlotSize is used when available is undefined
224+
AllocatedPercent: 60, // 300 / 500 * 100 = 60%
225+
});
226+
});
227+
228+
test('Should use allocated when SlotSize is undefined and available is 0', () => {
229+
expect(
230+
prepareVDiskSizeFields({
231+
AvailableSize: '0',
232+
AllocatedSize: '500',
233+
SlotSize: undefined,
234+
}),
235+
).toEqual({
236+
AvailableSize: 0,
237+
AllocatedSize: 500,
238+
SizeLimit: 500, // allocated (500)
239+
AllocatedPercent: 100, // 500 / 500 * 100 = 100%
240+
});
241+
});
242+
243+
test('Should handle case when used size exceeds slot size', () => {
244+
expect(
245+
prepareVDiskSizeFields({
246+
AvailableSize: '0',
247+
AllocatedSize: '800',
248+
SlotSize: '500',
249+
}),
250+
).toEqual({
251+
AvailableSize: 0,
252+
AllocatedSize: 800,
253+
SizeLimit: 500, // SlotSize is used as limit
254+
AllocatedPercent: 160, // 800 / 500 * 100 = 160%
255+
});
256+
});
257+
258+
test('Should return NaN for undefined data', () => {
197259
expect(
198260
prepareVDiskSizeFields({
199261
AvailableSize: undefined,
200262
AllocatedSize: undefined,
263+
SlotSize: undefined,
201264
}),
202265
).toEqual({
203-
AvailableSize: NaN,
266+
AvailableSize: 0,
204267
AllocatedSize: NaN,
205-
TotalSize: NaN,
268+
SizeLimit: NaN,
206269
AllocatedPercent: NaN,
207270
});
208271
});

src/utils/disks/prepareDisks.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ export function prepareWhiteboardVDiskData(
5656
const actualPDiskId = PDiskId ?? preparedPDisk?.PDiskId;
5757

5858
const vDiskSizeFields = prepareVDiskSizeFields({
59-
AvailableSize: AvailableSize ?? PDisk?.AvailableSize,
59+
AvailableSize: AvailableSize,
6060
AllocatedSize: AllocatedSize,
61+
SlotSize: PDisk?.EnforcedDynamicSlotSize,
6162
});
6263

6364
const Severity = calculateVDiskSeverity(vDiskState);
@@ -145,19 +146,30 @@ export function prepareWhiteboardPDiskData(pdiskState: TPDiskStateInfo = {}): Pr
145146
export function prepareVDiskSizeFields({
146147
AvailableSize,
147148
AllocatedSize,
149+
SlotSize,
148150
}: {
149151
AvailableSize: string | number | undefined;
150152
AllocatedSize: string | number | undefined;
153+
SlotSize: string | number | undefined;
151154
}) {
152-
const available = Number(AvailableSize);
155+
const available = Number(AvailableSize ?? 0);
156+
// Unlike available, allocated is displayed in UI, it is incorrect to fallback it to 0
153157
const allocated = Number(AllocatedSize);
154-
const total = allocated + available;
155-
const allocatedPercent = Math.floor((allocated * 100) / total);
158+
const slotSize = Number(SlotSize);
159+
160+
let sizeLimit = allocated + available;
161+
162+
// If no available size or available size is 0, slot size should be used as limit
163+
if (!available && slotSize) {
164+
sizeLimit = slotSize;
165+
}
166+
167+
const allocatedPercent = sizeLimit > 0 ? Math.floor((allocated * 100) / sizeLimit) : NaN;
156168

157169
return {
158170
AvailableSize: available,
159171
AllocatedSize: allocated,
160-
TotalSize: total,
172+
SizeLimit: sizeLimit,
161173
AllocatedPercent: allocatedPercent,
162174
};
163175
}

src/utils/disks/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ export interface PreparedVDisk
2828
StringifiedId?: string;
2929

3030
AvailableSize?: number;
31-
TotalSize?: number;
3231
AllocatedSize?: number;
3332
AllocatedPercent?: number;
33+
SizeLimit?: number;
3434

3535
Donors?: PreparedVDisk[];
3636
}

0 commit comments

Comments
 (0)