Skip to content

feat(Storage): group disks by DC #1823

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions src/components/PDiskPopup/PDiskPopup.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';

import {selectIsUserAllowedToMakeChanges} from '../../store/reducers/authentication/authentication';
import {selectNodeHostsMap} from '../../store/reducers/nodesList';
import {selectNodesMap} from '../../store/reducers/nodesList';
import {EFlag} from '../../types/api/enums';
import {valueIsDefined} from '../../utils';
import {EMPTY_DATA_PLACEHOLDER} from '../../utils/constants';
Expand All @@ -17,7 +17,7 @@ const errorColors = [EFlag.Orange, EFlag.Red, EFlag.Yellow];

export const preparePDiskData = (
data: PreparedPDisk,
nodeHost?: string,
nodeData?: {Host?: string; DC?: string},
withDeveloperUILink?: boolean,
) => {
const {
Expand Down Expand Up @@ -46,8 +46,11 @@ export const preparePDiskData = (
pdiskData.push({label: 'Node Id', value: NodeId});
}

if (nodeHost) {
pdiskData.push({label: 'Host', value: nodeHost});
if (nodeData?.Host) {
pdiskData.push({label: 'Host', value: nodeData.Host});
}
if (nodeData?.DC) {
pdiskData.push({label: 'DC', value: nodeData.DC});
}

if (Path) {
Expand Down Expand Up @@ -90,11 +93,11 @@ interface PDiskPopupProps {

export const PDiskPopup = ({data}: PDiskPopupProps) => {
const isUserAllowedToMakeChanges = useTypedSelector(selectIsUserAllowedToMakeChanges);
const nodeHostsMap = useTypedSelector(selectNodeHostsMap);
const nodeHost = valueIsDefined(data.NodeId) ? nodeHostsMap?.get(data.NodeId) : undefined;
const nodesMap = useTypedSelector(selectNodesMap);
const nodeData = valueIsDefined(data.NodeId) ? nodesMap?.get(data.NodeId) : undefined;
const info = React.useMemo(
() => preparePDiskData(data, nodeHost, isUserAllowedToMakeChanges),
[data, nodeHost, isUserAllowedToMakeChanges],
() => preparePDiskData(data, nodeData, isUserAllowedToMakeChanges),
[data, nodeData, isUserAllowedToMakeChanges],
);

return <InfoViewer title="PDisk" info={info} size="s" />;
Expand Down
10 changes: 5 additions & 5 deletions src/components/VDiskPopup/VDiskPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import {Label} from '@gravity-ui/uikit';

import {selectIsUserAllowedToMakeChanges} from '../../store/reducers/authentication/authentication';
import {selectNodeHostsMap} from '../../store/reducers/nodesList';
import {selectNodesMap} from '../../store/reducers/nodesList';
import {EFlag} from '../../types/api/enums';
import {valueIsDefined} from '../../utils';
import {cn} from '../../utils/cn';
Expand Down Expand Up @@ -188,14 +188,14 @@ export const VDiskPopup = ({data}: VDiskPopupProps) => {
[data, isFullData, isUserAllowedToMakeChanges],
);

const nodeHostsMap = useTypedSelector(selectNodeHostsMap);
const nodeHost = valueIsDefined(data.NodeId) ? nodeHostsMap?.get(data.NodeId) : undefined;
const nodesMap = useTypedSelector(selectNodesMap);
const nodeData = valueIsDefined(data.NodeId) ? nodesMap?.get(data.NodeId) : undefined;
const pdiskInfo = React.useMemo(
() =>
isFullData &&
data.PDisk &&
preparePDiskData(data.PDisk, nodeHost, isUserAllowedToMakeChanges),
[data, nodeHost, isFullData, isUserAllowedToMakeChanges],
preparePDiskData(data.PDisk, nodeData, isUserAllowedToMakeChanges),
[data, nodeData, isFullData, isUserAllowedToMakeChanges],
);

const donorsInfo: InfoViewerItem[] = [];
Expand Down
10 changes: 9 additions & 1 deletion src/containers/Storage/Disks/Disks.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
display: flex;
flex-direction: row;
justify-content: left;
gap: 6px;

width: max-content;
}
Expand All @@ -27,6 +26,15 @@

&__pdisk-item {
min-width: 80px;
margin-right: 4px;

&_with-dc-margin {
margin-right: 12px;
}

&:last-child {
margin-right: 0;
}
}
&__pdisk-progress-bar {
--progress-bar-full-height: 20px;
Expand Down
12 changes: 8 additions & 4 deletions src/containers/Storage/Disks/Disks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {cn} from '../../../utils/cn';
import type {PreparedVDisk} from '../../../utils/disks/types';
import {PDisk} from '../PDisk';
import type {StorageViewContext} from '../types';
import {isVdiskActive} from '../utils';
import {isVdiskActive, useVDisksWithDCMargins} from '../utils';

import './Disks.scss';

Expand All @@ -24,6 +24,8 @@ interface DisksProps {
export function Disks({vDisks = [], viewContext}: DisksProps) {
const [highlightedVDisk, setHighlightedVDisk] = React.useState<string | undefined>();

const vDisksWithDCMargins = useVDisksWithDCMargins(vDisks);

const {
theme: {spaceBaseSize},
} = useLayoutContext();
Expand Down Expand Up @@ -51,12 +53,13 @@ export function Disks({vDisks = [], viewContext}: DisksProps) {
</Flex>

<div className={b('pdisks-wrapper')}>
{vDisks?.map((vDisk) => (
{vDisks?.map((vDisk, index) => (
<PDiskItem
key={vDisk?.PDisk?.StringifiedId}
vDisk={vDisk}
highlightedVDisk={highlightedVDisk}
setHighlightedVDisk={setHighlightedVDisk}
withDCMargin={vDisksWithDCMargins.includes(index)}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is grouping only for PDisks here. This is done to keep VDisks relative sizes

/>
))}
</div>
Expand All @@ -70,6 +73,7 @@ interface DisksItemProps {
highlightedVDisk: string | undefined;
setHighlightedVDisk: (id: string | undefined) => void;
unavailableVDiskWidth?: number;
withDCMargin?: boolean;
}

function VDiskItem({
Expand Down Expand Up @@ -103,7 +107,7 @@ function VDiskItem({
);
}

function PDiskItem({vDisk, highlightedVDisk, setHighlightedVDisk}: DisksItemProps) {
function PDiskItem({vDisk, highlightedVDisk, setHighlightedVDisk, withDCMargin}: DisksItemProps) {
const vDiskId = vDisk.StringifiedId;

if (!vDisk.PDisk) {
Expand All @@ -112,7 +116,7 @@ function PDiskItem({vDisk, highlightedVDisk, setHighlightedVDisk}: DisksItemProp

return (
<PDisk
className={b('pdisk-item')}
className={b('pdisk-item', {['with-dc-margin']: withDCMargin})}
progressBarClassName={b('pdisk-progress-bar')}
data={vDisk.PDisk}
showPopup={highlightedVDisk === vDiskId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,6 @@
overflow: visible; // to enable stacked disks overflow the row
}

&__vdisks-wrapper {
display: flex;
justify-content: center;
gap: 10px;

min-width: 500px;
}
&__vdisks-item {
flex-grow: 1;

max-width: 200px;

.stack__layer {
.data-table__row:hover & {
background: var(--ydb-data-table-color-hover);
}
}
}

&__pool-name-wrapper {
overflow: hidden;

Expand Down
17 changes: 3 additions & 14 deletions src/containers/Storage/StorageGroups/columns/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {CellWithPopover} from '../../../../components/CellWithPopover/CellWithPo
import {InternalLink} from '../../../../components/InternalLink';
import {StatusIcon} from '../../../../components/StatusIcon/StatusIcon';
import {UsageLabel} from '../../../../components/UsageLabel/UsageLabel';
import {VDiskWithDonorsStack} from '../../../../components/VDisk/VDiskWithDonorsStack';
import {getStorageGroupPath} from '../../../../routes';
import {valueIsDefined} from '../../../../utils';
import {cn} from '../../../../utils/cn';
Expand All @@ -18,7 +17,8 @@ import {getUsageSeverity} from '../../../../utils/generateEvaluator';
import {formatToMs} from '../../../../utils/timeParsers';
import {bytesToGB, bytesToSpeed} from '../../../../utils/utils';
import {Disks} from '../../Disks/Disks';
import {getDegradedSeverity, isVdiskActive} from '../../utils';
import {VDisks} from '../../VDisks/VDisks';
import {getDegradedSeverity} from '../../utils';
import i18n from '../i18n';

import {
Expand Down Expand Up @@ -230,18 +230,7 @@ const getVDisksColumn = (data?: GetStorageColumnsData): StorageGroupsColumn => (
name: STORAGE_GROUPS_COLUMNS_IDS.VDisks,
header: STORAGE_GROUPS_COLUMNS_TITLES.VDisks,
className: b('vdisks-column'),
render: ({row}) => (
<div className={b('vdisks-wrapper')}>
{row.VDisks?.map((vDisk) => (
<VDiskWithDonorsStack
key={vDisk.StringifiedId}
data={vDisk}
inactive={!isVdiskActive(vDisk, data?.viewContext)}
className={b('vdisks-item')}
/>
))}
</div>
),
render: ({row}) => <VDisks vDisks={row.VDisks} viewContext={data?.viewContext} />,
align: DataTable.CENTER,
width: 900,
resizeable: false,
Expand Down
29 changes: 29 additions & 0 deletions src/containers/Storage/VDisks/VDisks.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.ydb-storage-vdisks {
&__wrapper {
display: flex;
justify-content: center;

min-width: 500px;
}

&__item {
flex-grow: 1;

max-width: 200px;
margin-right: 6px;

&_with-dc-margin {
margin-right: 12px;
}

&:last-child {
margin-right: 0px;
}

.stack__layer {
.data-table__row:hover & {
background: var(--ydb-data-table-color-hover);
}
}
}
}
33 changes: 33 additions & 0 deletions src/containers/Storage/VDisks/VDisks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {VDiskWithDonorsStack} from '../../../components/VDisk/VDiskWithDonorsStack';
import {cn} from '../../../utils/cn';
import type {PreparedVDisk} from '../../../utils/disks/types';
import type {StorageViewContext} from '../types';
import {isVdiskActive, useVDisksWithDCMargins} from '../utils';

import './VDisks.scss';

const b = cn('ydb-storage-vdisks');

interface VDisksProps {
vDisks?: PreparedVDisk[];
viewContext?: StorageViewContext;
}

export function VDisks({vDisks, viewContext}: VDisksProps) {
const vDisksWithDCMargins = useVDisksWithDCMargins(vDisks);

return (
<div className={b('wrapper')}>
{vDisks?.map((vDisk, index) => (
<VDiskWithDonorsStack
key={vDisk.StringifiedId}
data={vDisk}
inactive={!isVdiskActive(vDisk, viewContext)}
className={b('item', {
'with-dc-margin': vDisksWithDCMargins.includes(index),
})}
/>
))}
</div>
);
}
24 changes: 24 additions & 0 deletions src/containers/Storage/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React from 'react';

import {selectNodesMap} from '../../../store/reducers/nodesList';
import type {PreparedStorageGroup} from '../../../store/reducers/storage/types';
import {valueIsDefined} from '../../../utils';
import type {PreparedVDisk} from '../../../utils/disks/types';
import {generateEvaluator} from '../../../utils/generateEvaluator';
import {useTypedSelector} from '../../../utils/hooks';
import type {StorageViewContext} from '../types';

const defaultDegradationEvaluator = generateEvaluator(['success', 'warning', 'danger'], 1, 2);
Expand Down Expand Up @@ -79,3 +83,23 @@ export function getStorageGroupsInitialEntitiesCount(

return DEFAULT_ENTITIES_COUNT;
}

export function useVDisksWithDCMargins(vDisks: PreparedVDisk[] = []) {
const nodesMap = useTypedSelector(selectNodesMap);

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

// Backend returns disks sorted by DC, so we don't need to apply any additional sorting
vDisks.forEach((disk, index) => {
const dc1 = nodesMap?.get(Number(disk?.NodeId))?.DC;
const dc2 = nodesMap?.get(Number(vDisks[index + 1]?.NodeId))?.DC;

if (dc1 !== dc2) {
disksWithMargins.push(index);
}
});

return disksWithMargins;
}, [vDisks, nodesMap]);
}
4 changes: 2 additions & 2 deletions src/containers/Tenant/Diagnostics/Partitions/Partitions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {skipToken} from '@reduxjs/toolkit/query';
import {ResponseError} from '../../../../components/Errors/ResponseError';
import {ResizeableDataTable} from '../../../../components/ResizeableDataTable/ResizeableDataTable';
import {TableSkeleton} from '../../../../components/TableSkeleton/TableSkeleton';
import {nodesListApi, selectNodeHostsMap} from '../../../../store/reducers/nodesList';
import {nodesListApi, selectNodesMap} from '../../../../store/reducers/nodesList';
import {partitionsApi, setSelectedConsumer} from '../../../../store/reducers/partitions/partitions';
import {selectConsumersNames, topicApi} from '../../../../store/reducers/topic';
import {cn} from '../../../../utils/cn';
Expand Down Expand Up @@ -55,7 +55,7 @@ export const Partitions = ({path, database}: PartitionsProps) => {
error: nodesError,
} = nodesListApi.useGetNodesListQuery(undefined);
const nodesLoading = nodesIsFetching && nodesData === undefined;
const nodeHostsMap = useTypedSelector(selectNodeHostsMap);
const nodeHostsMap = useTypedSelector(selectNodesMap);

const [hiddenColumns, setHiddenColumns] = useSetting<string[]>(PARTITIONS_HIDDEN_COLUMNS_KEY);

Expand Down
8 changes: 4 additions & 4 deletions src/containers/Tenant/Diagnostics/Partitions/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import type {PreparedPartitionData} from '../../../../../store/reducers/partitions/types';
import type {NodeHostsMap} from '../../../../../types/store/nodesList';
import type {NodesMap} from '../../../../../types/store/nodesList';

import type {PreparedPartitionDataWithHosts} from './types';

export const addHostToPartitions = (
partitions: PreparedPartitionData[] = [],
nodeHosts?: NodeHostsMap,
nodeHosts?: NodesMap,
): PreparedPartitionDataWithHosts[] => {
return partitions?.map((partition) => {
const partitionHost =
partition.partitionNodeId && nodeHosts
? nodeHosts.get(partition.partitionNodeId)
? nodeHosts.get(partition.partitionNodeId)?.Host
: undefined;

const connectionHost =
partition.connectionNodeId && nodeHosts
? nodeHosts.get(partition.connectionNodeId)
? nodeHosts.get(partition.connectionNodeId)?.Host
: undefined;

return {
Expand Down
7 changes: 4 additions & 3 deletions src/store/reducers/cluster/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {CLUSTER_DEFAULT_TITLE, DEFAULT_CLUSTER_TAB_KEY} from '../../../utils/con
import {isQueryErrorResponse} from '../../../utils/query';
import type {RootState} from '../../defaultStore';
import {api} from '../api';
import {selectNodeHostsMap} from '../nodesList';
import {selectNodesMap} from '../nodesList';

import type {ClusterGroupsStats, ClusterState} from './types';
import {
Expand Down Expand Up @@ -181,7 +181,7 @@ export const selectClusterTitle = createSelector(

export const selectClusterTabletsWithFqdn = createSelector(
(state: RootState, clusterName?: string) => selectClusterInfo(state, clusterName),
(state: RootState) => selectNodeHostsMap(state),
(state: RootState) => selectNodesMap(state),
(data, nodeHostsMap): (TTabletStateInfo & {fqdn?: string})[] => {
const tablets = data?.clusterData?.SystemTablets;
if (!tablets) {
Expand All @@ -191,7 +191,8 @@ export const selectClusterTabletsWithFqdn = createSelector(
return tablets;
}
return tablets.map((tablet) => {
const fqdn = tablet.NodeId === undefined ? undefined : nodeHostsMap.get(tablet.NodeId);
const fqdn =
tablet.NodeId === undefined ? undefined : nodeHostsMap.get(tablet.NodeId)?.Host;
return {...tablet, fqdn};
});
},
Expand Down
Loading
Loading