Skip to content

Commit a2b7d1c

Browse files
fix(Storage): fix disks view for degraded group (#1930)
1 parent 267c445 commit a2b7d1c

File tree

9 files changed

+87
-23
lines changed

9 files changed

+87
-23
lines changed

src/containers/Storage/Disks/Disks.tsx

+9-7
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import React from 'react';
33
import {Flex, useLayoutContext} from '@gravity-ui/uikit';
44

55
import {VDisk} from '../../../components/VDisk/VDisk';
6-
import {valueIsDefined} from '../../../utils';
6+
import type {Erasure} from '../../../types/api/storage';
77
import {cn} from '../../../utils/cn';
88
import type {PreparedVDisk} from '../../../utils/disks/types';
9+
import {isNumeric} from '../../../utils/utils';
910
import {PDisk} from '../PDisk';
1011
import type {StorageViewContext} from '../types';
1112
import {isVdiskActive, useVDisksWithDCMargins} from '../utils';
@@ -19,12 +20,13 @@ const VDISKS_CONTAINER_WIDTH = 300;
1920
interface DisksProps {
2021
vDisks?: PreparedVDisk[];
2122
viewContext?: StorageViewContext;
23+
erasure?: Erasure;
2224
}
2325

24-
export function Disks({vDisks = [], viewContext}: DisksProps) {
26+
export function Disks({vDisks = [], viewContext, erasure}: DisksProps) {
2527
const [highlightedVDisk, setHighlightedVDisk] = React.useState<string | undefined>();
2628

27-
const vDisksWithDCMargins = useVDisksWithDCMargins(vDisks);
29+
const vDisksWithDCMargins = useVDisksWithDCMargins(vDisks, erasure);
2830

2931
const {
3032
theme: {spaceBaseSize},
@@ -40,9 +42,9 @@ export function Disks({vDisks = [], viewContext}: DisksProps) {
4042
return (
4143
<div className={b(null)}>
4244
<Flex direction={'row'} gap={1} grow style={{width: VDISKS_CONTAINER_WIDTH}}>
43-
{vDisks?.map((vDisk) => (
45+
{vDisks?.map((vDisk, index) => (
4446
<VDiskItem
45-
key={vDisk.StringifiedId}
47+
key={vDisk.StringifiedId || index}
4648
vDisk={vDisk}
4749
inactive={!isVdiskActive(vDisk, viewContext)}
4850
highlightedVDisk={highlightedVDisk}
@@ -55,7 +57,7 @@ export function Disks({vDisks = [], viewContext}: DisksProps) {
5557
<div className={b('pdisks-wrapper')}>
5658
{vDisks?.map((vDisk, index) => (
5759
<PDiskItem
58-
key={vDisk?.PDisk?.StringifiedId}
60+
key={vDisk?.PDisk?.StringifiedId || index}
5961
vDisk={vDisk}
6062
highlightedVDisk={highlightedVDisk}
6163
setHighlightedVDisk={setHighlightedVDisk}
@@ -89,7 +91,7 @@ function VDiskItem({
8991
const vDiskId = vDisk.StringifiedId;
9092

9193
// show vdisks without AllocatedSize as having average width (#1433)
92-
const minWidth = valueIsDefined(vDiskToShow.AllocatedSize) ? undefined : unavailableVDiskWidth;
94+
const minWidth = isNumeric(vDiskToShow.AllocatedSize) ? undefined : unavailableVDiskWidth;
9395
const flexGrow = Number(vDiskToShow.AllocatedSize) || 1;
9496

9597
return (

src/containers/Storage/StorageGroups/columns/columns.tsx

+10-2
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,9 @@ const getVDisksColumn = (data?: GetStorageColumnsData): StorageGroupsColumn => (
236236
name: STORAGE_GROUPS_COLUMNS_IDS.VDisks,
237237
header: STORAGE_GROUPS_COLUMNS_TITLES.VDisks,
238238
className: b('vdisks-column'),
239-
render: ({row}) => <VDisks vDisks={row.VDisks} viewContext={data?.viewContext} />,
239+
render: ({row}) => (
240+
<VDisks vDisks={row.VDisks} viewContext={data?.viewContext} erasure={row.ErasureSpecies} />
241+
),
240242
align: DataTable.CENTER,
241243
width: 780, // usually 8-9 vdisks, this width corresponds to 8 vdisks, column is expanded if more
242244
resizeable: false,
@@ -248,7 +250,13 @@ const getDisksColumn = (data?: GetStorageColumnsData): StorageGroupsColumn => ({
248250
header: STORAGE_GROUPS_COLUMNS_TITLES.VDisksPDisks,
249251
className: b('disks-column'),
250252
render: ({row}) => {
251-
return <Disks vDisks={row.VDisks} viewContext={data?.viewContext} />;
253+
return (
254+
<Disks
255+
vDisks={row.VDisks}
256+
viewContext={data?.viewContext}
257+
erasure={row.ErasureSpecies}
258+
/>
259+
);
252260
},
253261
align: DataTable.CENTER,
254262
width: 900,

src/containers/Storage/VDisks/VDisks.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {VDiskWithDonorsStack} from '../../../components/VDisk/VDiskWithDonorsStack';
2+
import type {Erasure} from '../../../types/api/storage';
23
import {cn} from '../../../utils/cn';
34
import type {PreparedVDisk} from '../../../utils/disks/types';
45
import type {StorageViewContext} from '../types';
@@ -11,10 +12,11 @@ const b = cn('ydb-storage-vdisks');
1112
interface VDisksProps {
1213
vDisks?: PreparedVDisk[];
1314
viewContext?: StorageViewContext;
15+
erasure?: Erasure;
1416
}
1517

16-
export function VDisks({vDisks, viewContext}: VDisksProps) {
17-
const vDisksWithDCMargins = useVDisksWithDCMargins(vDisks);
18+
export function VDisks({vDisks, viewContext, erasure}: VDisksProps) {
19+
const vDisksWithDCMargins = useVDisksWithDCMargins(vDisks, erasure);
1820

1921
return (
2022
<div className={b('wrapper')}>

src/containers/Storage/utils/index.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22

33
import {selectNodesMap} from '../../../store/reducers/nodesList';
44
import type {PreparedStorageGroup} from '../../../store/reducers/storage/types';
5+
import type {Erasure} from '../../../types/api/storage';
56
import {valueIsDefined} from '../../../utils';
67
import type {PreparedVDisk} from '../../../utils/disks/types';
78
import {generateEvaluator} from '../../../utils/generateEvaluator';
@@ -84,12 +85,22 @@ export function getStorageGroupsInitialEntitiesCount(
8485
return DEFAULT_ENTITIES_COUNT;
8586
}
8687

87-
export function useVDisksWithDCMargins(vDisks: PreparedVDisk[] = []) {
88+
function isErasureWithDifferentDC(erasure?: Erasure) {
89+
// These erasure types suppose the data distributed across 3 different DC
90+
return erasure === 'mirror-3-dc' || erasure === 'mirror-3of4';
91+
}
92+
93+
export function useVDisksWithDCMargins(vDisks: PreparedVDisk[] = [], erasure?: Erasure) {
8894
const nodesMap = useTypedSelector(selectNodesMap);
8995

9096
return React.useMemo(() => {
9197
const disksWithMargins: number[] = [];
9298

99+
// If single-dc erasure, all disks are in the same DC
100+
if (!isErasureWithDifferentDC(erasure)) {
101+
return disksWithMargins;
102+
}
103+
93104
// Backend returns disks sorted by DC, so we don't need to apply any additional sorting
94105
vDisks.forEach((disk, index) => {
95106
const dc1 = nodesMap?.get(Number(disk?.NodeId))?.DC;
@@ -101,5 +112,5 @@ export function useVDisksWithDCMargins(vDisks: PreparedVDisk[] = []) {
101112
});
102113

103114
return disksWithMargins;
104-
}, [vDisks, nodesMap]);
115+
}, [erasure, vDisks, nodesMap]);
105116
}

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

+39-2
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,19 @@ describe('prepareGroupsVDisk', () => {
9595
AllocatedPercent: 12,
9696

9797
Donors: undefined,
98-
PDisk: undefined,
98+
99+
PDisk: {
100+
AllocatedPercent: NaN,
101+
AllocatedSize: NaN,
102+
AvailableSize: NaN,
103+
NodeId: 224,
104+
PDiskId: undefined,
105+
Severity: 0,
106+
SlotSize: undefined,
107+
StringifiedId: undefined,
108+
TotalSize: NaN,
109+
Type: undefined,
110+
},
99111
};
100112

101113
const preparedData = prepareGroupsVDisk(vDiksDataWithoutPDisk);
@@ -124,6 +136,19 @@ describe('prepareGroupsVDisk', () => {
124136
AvailableSize: 234461593600,
125137
TotalSize: 265405071360,
126138
AllocatedPercent: 12,
139+
140+
PDisk: {
141+
AllocatedPercent: NaN,
142+
AllocatedSize: NaN,
143+
AvailableSize: NaN,
144+
NodeId: 224,
145+
PDiskId: undefined,
146+
Severity: 0,
147+
SlotSize: undefined,
148+
StringifiedId: undefined,
149+
TotalSize: NaN,
150+
Type: undefined,
151+
},
127152
};
128153

129154
const preparedData = prepareGroupsVDisk(vDiksDataWithoutPDisk);
@@ -215,7 +240,19 @@ describe('prepareGroupsVDisk', () => {
215240
AllocatedPercent: 12,
216241

217242
Donors: undefined,
218-
PDisk: undefined,
243+
244+
PDisk: {
245+
AllocatedPercent: NaN,
246+
AllocatedSize: NaN,
247+
AvailableSize: NaN,
248+
NodeId: undefined,
249+
PDiskId: undefined,
250+
Severity: 0,
251+
SlotSize: undefined,
252+
StringifiedId: undefined,
253+
TotalSize: NaN,
254+
Type: undefined,
255+
},
219256
};
220257

221258
const preparedData = prepareGroupsVDisk(vDiksDataWithoutPDisk);

src/store/reducers/storage/prepareGroupsDisks.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ export function prepareGroupsVDisk(data: TStorageVDisk = {}): PreparedVDisk {
1616
VDiskId: whiteboardVDisk.VDiskId,
1717
};
1818

19-
const preparedPDisk = PDisk
20-
? prepareGroupsPDisk({...PDisk, NodeId: mergedVDiskData.NodeId})
21-
: undefined;
19+
const preparedPDisk = prepareGroupsPDisk({...PDisk, NodeId: mergedVDiskData.NodeId});
2220

2321
const PDiskId = preparedPDisk?.PDiskId ?? whiteboardVDisk?.PDiskId;
2422

src/store/reducers/storage/types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {z} from 'zod';
22

33
import type {EFlag} from '../../../types/api/enums';
44
import type {NodesGroupByField} from '../../../types/api/nodes';
5-
import type {GroupsGroupByField} from '../../../types/api/storage';
5+
import type {Erasure, GroupsGroupByField} from '../../../types/api/storage';
66
import type {PreparedPDisk, PreparedVDisk} from '../../../utils/disks/types';
77
import type {NodesUptimeFilterValues, PreparedNodeSystemState} from '../../../utils/nodes';
88

@@ -56,7 +56,7 @@ export interface PreparedStorageGroup {
5656
PoolName?: string;
5757
MediaType?: string;
5858
Encryption?: boolean;
59-
ErasureSpecies?: string;
59+
ErasureSpecies?: Erasure;
6060
Degraded: number;
6161
Overall?: EFlag;
6262

src/types/api/cluster.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type {EFlag} from './enums';
2+
import type {Erasure} from './storage';
23
import type {TTabletStateInfo} from './tablet';
34

45
/**
@@ -38,7 +39,7 @@ export interface TClusterInfoV1 {
3839

3940
export interface TStorageStats {
4041
PDiskFilter?: string;
41-
ErasureSpecies?: string;
42+
ErasureSpecies?: Erasure;
4243
CurrentAvailableSize?: string;
4344
/** uint64 */
4445
CurrentAllocatedSize?: string;

src/types/api/storage.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export type TStorageGroupInfo = TBSGroupStateInfo &
6666

6767
interface TBSGroupStateInfo {
6868
GroupID?: number;
69-
ErasureSpecies?: string;
69+
ErasureSpecies?: Erasure;
7070
VDisks?: TVDiskStateInfo[];
7171
/** uint64 */
7272
ChangeTime?: string;
@@ -137,7 +137,7 @@ export interface TGroupsStorageGroupInfo {
137137
DiskSpace?: EFlag;
138138
Kind?: string;
139139
MediaType?: string;
140-
ErasureSpecies?: string;
140+
ErasureSpecies?: Erasure;
141141
/** uint64 */
142142
AllocationUnits?: string;
143143
/**
@@ -228,6 +228,11 @@ export interface TStoragePDisk {
228228
Whiteboard?: TPDiskStateInfo;
229229
}
230230

231+
/**
232+
* https://ydb.tech/docs/en/concepts/topology#cluster-config
233+
*/
234+
export type Erasure = 'none' | 'block-4-2' | 'mirror-3-dc' | 'mirror-3of4';
235+
231236
// ==== Request types ====
232237

233238
export type EVersion = 'v1' | 'v2'; // only v2 versions works with sorting

0 commit comments

Comments
 (0)