Skip to content

Commit 410d4d4

Browse files
authored
feat(vDisk): allow evict vDisk by id (#2267)
1 parent f8c52a6 commit 410d4d4

File tree

8 files changed

+90
-54
lines changed

8 files changed

+90
-54
lines changed

src/components/VDisk/utils.ts

+14-19
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,26 @@
1-
import {getDefaultNodePath} from '../../containers/Node/NodePages';
21
import {getVDiskPagePath} from '../../routes';
3-
import type {TVDiskStateInfo, TVSlotId} from '../../types/api/vdisk';
42
import {valueIsDefined} from '../../utils';
5-
import {stringifyVdiskId} from '../../utils/dataFormatters/dataFormatters';
6-
import {isFullVDiskData} from '../../utils/disks/helpers';
3+
import type {PreparedVDisk} from '../../utils/disks/types';
74

8-
export function getVDiskLink(data: TVDiskStateInfo | TVSlotId) {
5+
export function getVDiskLink(data: PreparedVDisk) {
96
let vDiskPath: string | undefined;
107

11-
const isFullData = isFullVDiskData(data);
12-
const VDiskSlotId = isFullData ? data.VDiskSlotId : data.VSlotId;
13-
148
if (
15-
valueIsDefined(VDiskSlotId) &&
9+
valueIsDefined(data.VDiskSlotId) &&
1610
valueIsDefined(data.PDiskId) &&
1711
valueIsDefined(data.NodeId)
1812
) {
19-
vDiskPath = getVDiskPagePath(VDiskSlotId, data.PDiskId, data.NodeId);
20-
} else if (valueIsDefined(data.NodeId) && isFullVDiskData(data)) {
21-
vDiskPath = getDefaultNodePath(
22-
data.NodeId,
23-
{
24-
pdiskId: data.PDiskId?.toString(),
25-
vdiskId: stringifyVdiskId(data.VDiskId),
26-
},
27-
'structure',
28-
);
13+
vDiskPath = getVDiskPagePath({
14+
vDiskSlotId: data.VDiskSlotId,
15+
pDiskId: data.PDiskId,
16+
nodeId: data.NodeId,
17+
});
18+
} else if (valueIsDefined(data.StringifiedId)) {
19+
vDiskPath = getVDiskPagePath({
20+
vDiskId: data.StringifiedId,
21+
pDiskId: data.PDiskId,
22+
nodeId: data.NodeId,
23+
});
2924
}
3025

3126
return vDiskPath;

src/components/VDiskInfo/VDiskInfo.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,11 @@ export function VDiskInfo<T extends PreparedVDisk>({
154154
const links: React.ReactNode[] = [];
155155

156156
if (withVDiskPageLink) {
157-
const vDiskPagePath = getVDiskPagePath(VDiskSlotId, PDiskId, NodeId);
157+
const vDiskPagePath = getVDiskPagePath({
158+
vDiskSlotId: VDiskSlotId,
159+
pDiskId: PDiskId,
160+
nodeId: NodeId,
161+
});
158162
links.push(
159163
<LinkWithIcon
160164
key={vDiskPagePath}

src/components/VDiskPopup/VDiskPopup.tsx

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

33
import {Flex, Label} from '@gravity-ui/uikit';
44

5-
import {getVDiskPagePath} from '../../routes';
65
import {selectNodesMap} from '../../store/reducers/nodesList';
76
import {EFlag} from '../../types/api/enums';
87
import {valueIsDefined} from '../../utils';
@@ -156,32 +155,38 @@ const prepareVDiskData = (data: PreparedVDisk, withDeveloperUILink?: boolean) =>
156155
withDeveloperUILink &&
157156
valueIsDefined(NodeId) &&
158157
valueIsDefined(PDiskId) &&
159-
valueIsDefined(VDiskSlotId)
158+
(valueIsDefined(VDiskSlotId) || valueIsDefined(StringifiedId))
160159
) {
161-
const vDiskInternalViewerPath = createVDiskDeveloperUILink({
162-
nodeId: NodeId,
163-
pDiskId: PDiskId,
164-
vDiskSlotId: VDiskSlotId,
165-
});
166-
167-
const vDiskPagePath = getVDiskPagePath(VDiskSlotId, PDiskId, NodeId);
168-
vdiskData.push({
169-
label: 'Links',
170-
value: (
171-
<Flex wrap="wrap" gap={2}>
172-
<LinkWithIcon
173-
key={vDiskPagePath}
174-
title={vDiskInfoKeyset('vdisk-page')}
175-
url={vDiskPagePath}
176-
external={false}
177-
/>
178-
<LinkWithIcon
179-
title={vDiskInfoKeyset('developer-ui')}
180-
url={vDiskInternalViewerPath}
181-
/>
182-
</Flex>
183-
),
184-
});
160+
const vDiskInternalViewerPath = valueIsDefined(VDiskSlotId)
161+
? createVDiskDeveloperUILink({
162+
nodeId: NodeId,
163+
pDiskId: PDiskId,
164+
vDiskSlotId: VDiskSlotId,
165+
})
166+
: undefined;
167+
168+
const vDiskPagePath = getVDiskLink({VDiskSlotId, PDiskId, NodeId, StringifiedId});
169+
if (vDiskPagePath) {
170+
vdiskData.push({
171+
label: 'Links',
172+
value: (
173+
<Flex wrap="wrap" gap={2}>
174+
<LinkWithIcon
175+
key={vDiskPagePath}
176+
title={vDiskInfoKeyset('vdisk-page')}
177+
url={vDiskPagePath}
178+
external={false}
179+
/>
180+
{vDiskInternalViewerPath ? (
181+
<LinkWithIcon
182+
title={vDiskInfoKeyset('developer-ui')}
183+
url={vDiskInternalViewerPath}
184+
/>
185+
) : null}
186+
</Flex>
187+
),
188+
});
189+
}
185190
}
186191

187192
return vdiskData;

src/containers/PDiskPage/PDiskSpaceDistribution/PDiskSpaceDistribution.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ function Slot<T extends SlotItemType>({item, pDiskId, nodeId}: SlotProps<T>) {
8181
valueIsDefined(item.SlotData?.VDiskSlotId) &&
8282
valueIsDefined(pDiskId) &&
8383
valueIsDefined(nodeId)
84-
? getVDiskPagePath(item.SlotData.VDiskSlotId, pDiskId, nodeId)
84+
? getVDiskPagePath({vDiskSlotId: item.SlotData.VDiskSlotId, pDiskId, nodeId})
8585
: undefined;
8686

8787
return (

src/containers/VDiskPage/VDiskPage.tsx

+23-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {useDiskPagesAvailable} from '../../store/reducers/capabilities/hooks';
1717
import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
1818
import {vDiskApi} from '../../store/reducers/vdisk/vdisk';
1919
import type {ModifyDiskResponse} from '../../types/api/modifyDisk';
20+
import type {TVDiskID} from '../../types/api/vdisk';
2021
import {valueIsDefined} from '../../utils';
2122
import {cn} from '../../utils/cn';
2223
import {getSeverityColor, getVDiskSlotBasedId} from '../../utils/disks/helpers';
@@ -37,10 +38,11 @@ export function VDiskPage() {
3738
const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges();
3839
const newDiskApiAvailable = useDiskPagesAvailable();
3940

40-
const [{nodeId, pDiskId, vDiskSlotId}] = useQueryParams({
41+
const [{nodeId, pDiskId, vDiskSlotId, vDiskId: vDiskIdParam}] = useQueryParams({
4142
nodeId: StringParam,
4243
pDiskId: StringParam,
4344
vDiskSlotId: StringParam,
45+
vDiskId: StringParam,
4446
});
4547

4648
React.useEffect(() => {
@@ -61,7 +63,9 @@ export function VDiskPage() {
6163
});
6264
const loading = isFetching && vDiskData === undefined;
6365
const {NodeHost, NodeId, NodeType, NodeDC, PDiskId, PDiskType, Severity, VDiskId} = vDiskData;
64-
const {GroupID, GroupGeneration, Ring, Domain, VDisk} = VDiskId || {};
66+
67+
const {GroupID, GroupGeneration, Ring, Domain, VDisk} =
68+
VDiskId || getVDiskIdFromString(vDiskIdParam) || {};
6569
const vDiskIdParamsDefined =
6670
valueIsDefined(GroupID) &&
6771
valueIsDefined(GroupGeneration) &&
@@ -149,7 +153,7 @@ export function VDiskPage() {
149153
className={vDiskPageCn('title')}
150154
entityName={vDiskPageKeyset('vdisk')}
151155
status={getSeverityColor(Severity)}
152-
id={vDiskData?.StringifiedId}
156+
id={vDiskData?.StringifiedId ?? vDiskIdParam}
153157
/>
154158
);
155159
};
@@ -228,3 +232,19 @@ export function VDiskPage() {
228232
</div>
229233
);
230234
}
235+
236+
function getVDiskIdFromString(input: string | null | undefined): TVDiskID | undefined {
237+
const match = /^(\d+)-(\d+)-(\d+)-(\d+)-(\d+)$/.exec(input ?? '');
238+
if (!match) {
239+
return undefined;
240+
}
241+
242+
const [, GroupID, GroupGeneration, Ring, Domain, VDisk] = match;
243+
return {
244+
GroupID: Number(GroupID),
245+
GroupGeneration: Number(GroupGeneration),
246+
Ring: Number(Ring),
247+
Domain: Number(Domain),
248+
VDisk: Number(VDisk),
249+
};
250+
}

src/routes.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,16 @@ export function getPDiskPagePath(
121121
}
122122

123123
export function getVDiskPagePath(
124-
vDiskSlotId: string | number,
125-
pDiskId: string | number,
126-
nodeId: string | number,
124+
params:
125+
| {
126+
vDiskSlotId: string | number;
127+
pDiskId: string | number;
128+
nodeId: string | number;
129+
}
130+
| {vDiskId: string; pDiskId?: string | number; nodeId?: string | number},
127131
query: Query = {},
128132
) {
129-
return createHref(routes.vDisk, undefined, {...query, nodeId, pDiskId, vDiskSlotId});
133+
return createHref(routes.vDisk, undefined, {...query, ...params});
130134
}
131135

132136
export function getStorageGroupPath(groupId: string | number, query: Query = {}) {

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

+1
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ describe('prepareGroupsPDisk', () => {
359359

360360
const expectedResult = {
361361
NodeId: 224,
362+
PDiskId: 1001,
362363
StringifiedId: '224-1001',
363364

364365
Path: '/dev/disk/by-partlabel/kikimr_nvme_04',

src/store/reducers/storage/prepareGroupsDisks.ts

+7
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ export function prepareGroupsPDisk(data: TStoragePDisk & {NodeId?: number} = {})
5656
PDiskId: whiteboardPDisk?.PDiskId,
5757
};
5858

59+
if (mergedPDiskData.PDiskId === undefined && bscPDisk.PDiskId) {
60+
const id = Number(bscPDisk.PDiskId.split('-')[1]);
61+
if (!isNaN(id)) {
62+
mergedPDiskData.PDiskId = id;
63+
}
64+
}
65+
5966
const StringifiedId =
6067
bscPDisk.PDiskId ||
6168
getPDiskId({nodeId: mergedPDiskData.NodeId, pDiskId: mergedPDiskData.PDiskId});

0 commit comments

Comments
 (0)