fix: gpu service issues

This commit is contained in:
jialin
2026-05-26 14:21:52 +08:00
committed by jialin
parent 88ab927755
commit 95e03d11c1
20 changed files with 187 additions and 256 deletions
@@ -2,7 +2,6 @@ import { PageAction } from '@/config';
import {
Input as CInput,
InputNumber as CInputNumber,
CheckboxField,
LabelInfo,
Select,
useAppUtils
@@ -14,21 +13,17 @@ import { useEffect, useMemo, useState } from 'react';
import { FormData as StorageFormData } from '../../storage/config/types';
import useCreateStorage from '../../storage/services/use-create-storage';
import useQueryStorage from '../../storage/services/use-query-storage';
import useQueryStorageTypes from '../../storage-types/services/use-query-storage-types';
import { DEFAULT_PV_CAPACITY_GB, StorageModeValueMap } from '../config';
import { StorageModeValueMap } from '../config';
import { FormData } from '../config/types';
import StorageOverlay from './storage-overlay';
const DEFAULT_TEMP_CAPACITY_GB = 50;
const detectMode = (volume?: FormData['spec']['volume']) => {
if (volume?.persistentTemplate) {
return { mode: StorageModeValueMap.Persistent, releaseWithInstance: true };
if (volume?.persistent || volume?.persistentTemplate) {
return StorageModeValueMap.Persistent;
}
if (volume?.persistent) {
return { mode: StorageModeValueMap.Persistent, releaseWithInstance: false };
}
return { mode: StorageModeValueMap.Temporary, releaseWithInstance: false };
return StorageModeValueMap.Temporary;
};
const StorageVolume = ({
@@ -45,25 +40,19 @@ const StorageVolume = ({
const [storageMode, setStorageMode] = useState<string>(
StorageModeValueMap.Temporary
);
const [releaseWithInstance, setReleaseWithInstance] = useState<boolean>(false);
useEffect(() => {
if (!currentVolume) return;
const detected = detectMode(currentVolume);
setStorageMode(detected.mode);
setReleaseWithInstance(detected.releaseWithInstance);
setStorageMode(detectMode(currentVolume));
}, [currentVolume]);
const { fetchData: createStorage } = useCreateStorage();
const { detailData: storageData, fetchData: fetchStorage } =
useQueryStorage();
const { detailData: storageTypesData, fetchData: fetchStorageTypes } =
useQueryStorageTypes();
const [overlayOpen, setOverlayOpen] = useState(false);
useEffect(() => {
fetchStorage({ page: 1, perPage: 100 });
fetchStorageTypes({ page: 1, perPage: 100 });
}, []);
const storageOptions = useMemo(
@@ -75,43 +64,19 @@ const StorageVolume = ({
[storageData]
);
const storageTypeOptions = useMemo(
() =>
(storageTypesData?.items || []).map((item) => ({
label: item.displayName || item.name,
value: item.name
})),
[storageTypesData]
);
const applyMode = (mode: string, release: boolean) => {
const applyMode = (mode: string) => {
if (mode === StorageModeValueMap.Temporary) {
form.setFieldValue(['spec', 'volume'], {
ephemeral: { capacity: `${DEFAULT_TEMP_CAPACITY_GB}Gi` }
});
return;
}
if (release) {
form.setFieldValue(['spec', 'volume'], {
persistentTemplate: {
spec: { type: '', capacity: `${DEFAULT_PV_CAPACITY_GB}Gi` },
releaseWithInstance: true
}
});
return;
}
form.setFieldValue(['spec', 'volume'], { persistent: { name: '' } });
};
const handleModeChange = (mode: string) => {
setStorageMode(mode);
applyMode(mode, releaseWithInstance);
};
const handleReleaseChange = (e: any) => {
const next = !!e?.target?.checked;
setReleaseWithInstance(next);
applyMode(storageMode, next);
applyMode(mode);
};
const handleCreateStorage = async (values: StorageFormData) => {
@@ -130,48 +95,60 @@ const StorageVolume = ({
return (
<>
<div data-field="storage"></div>
<Radio.Group
disabled={disabled}
style={{ marginBottom: 12 }}
value={storageMode}
onChange={(e) => handleModeChange(e.target.value)}
options={[
{
label: (
<LabelInfo
description={intl.formatMessage({
id: 'gpuservice.storage.temporary.tips'
})}
label={
<span className="text-primary">
{intl.formatMessage({
id: 'gpuservice.storage.temporary'
})}
</span>
}
/>
),
value: StorageModeValueMap.Temporary
},
{
label: (
<LabelInfo
description={intl.formatMessage({
id: 'gpuservice.storage.persistentVolume.tips'
})}
label={
<span className="text-primary">
{intl.formatMessage({
id: 'gpuservice.storage.persistentVolume'
})}
</span>
}
/>
),
value: StorageModeValueMap.Persistent
}
]}
/>
<Flex align="center" justify="space-between" style={{ marginBlock: 16 }}>
<Radio.Group
disabled={disabled}
value={storageMode}
style={{ display: 'flex', gap: 12 }}
onChange={(e) => handleModeChange(e.target.value)}
options={[
{
label: (
<LabelInfo
description={intl.formatMessage({
id: 'gpuservice.storage.temporary.tips'
})}
label={
<span className="text-primary">
{intl.formatMessage({
id: 'gpuservice.storage.temporary'
})}
</span>
}
/>
),
value: StorageModeValueMap.Temporary
},
{
label: (
<LabelInfo
description={intl.formatMessage({
id: 'gpuservice.storage.persistentVolume.tips'
})}
label={
<span className="text-primary">
{intl.formatMessage({
id: 'gpuservice.storage.persistentVolume'
})}
</span>
}
/>
),
value: StorageModeValueMap.Persistent
}
]}
/>
{action === PageAction.CREATE &&
storageMode === StorageModeValueMap.Persistent && (
<Button
type="link"
size="small"
onClick={() => setOverlayOpen(true)}
>
{intl.formatMessage({ id: 'gpuservice.storage.add' })}
</Button>
)}
</Flex>
{storageMode === StorageModeValueMap.Temporary && (
<Form.Item
@@ -205,106 +182,26 @@ const StorageVolume = ({
{storageMode === StorageModeValueMap.Persistent && (
<>
<Flex
style={{
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 12
}}
<Form.Item
name={['spec', 'volume', 'persistent', 'name']}
rules={[
{
required: true,
message: intl.formatMessage({
id: 'gpuservice.storage.persistentVolume.required'
})
}
]}
>
<CheckboxField
<Select
disabled={disabled}
checked={releaseWithInstance}
onChange={handleReleaseChange}
label={intl.formatMessage({
id: 'gpuservice.storage.persistentVolume.releaseWithInstance'
id: 'gpuservice.storage.persistentVolume'
})}
required
options={storageOptions}
/>
{action === PageAction.CREATE && !releaseWithInstance && (
<Button
type="link"
size="small"
onClick={() => setOverlayOpen(true)}
>
{intl.formatMessage({ id: 'gpuservice.storage.add' })}
</Button>
)}
</Flex>
{releaseWithInstance ? (
<>
<Form.Item
name={['spec', 'volume', 'persistentTemplate', 'spec', 'type']}
rules={[
{
required: true,
message: getRuleMessage('select', 'gpuservice.storageType')
}
]}
>
<Select
required
disabled={disabled}
label={intl.formatMessage({ id: 'gpuservice.storageType' })}
options={storageTypeOptions}
/>
</Form.Item>
<Form.Item
name={[
'spec',
'volume',
'persistentTemplate',
'spec',
'capacity'
]}
getValueProps={(val) => ({
value: val
? Number(String(val).replace(/Gi$/i, '')) || undefined
: undefined
})}
normalize={(val) => (val ? `${val}Gi` : '')}
rules={[
{
required: true,
message: intl.formatMessage({
id: 'gpuservice.storage.persistentVolume.capacity.required'
})
}
]}
>
<CInputNumber
required
disabled={disabled}
min={1}
precision={0}
label={intl.formatMessage({
id: 'gpuservice.storage.persistentVolume.capacity'
})}
/>
</Form.Item>
</>
) : (
<Form.Item
name={['spec', 'volume', 'persistent', 'name']}
rules={[
{
required: true,
message: intl.formatMessage({
id: 'gpuservice.storage.persistentVolume.required'
})
}
]}
>
<Select
disabled={disabled}
label={intl.formatMessage({
id: 'gpuservice.storage.persistentVolume'
})}
required
options={storageOptions}
/>
</Form.Item>
)}
</Form.Item>
</>
)}