fix: storage api alignment

This commit is contained in:
jialin
2026-05-11 19:49:21 +08:00
committed by jialin
parent 7fa44644fd
commit 7d0cfeff77
34 changed files with 881 additions and 324 deletions
+40 -4
View File
@@ -1,11 +1,15 @@
import { request } from '@umijs/max';
import { mockInstanceData } from '../config/mock-data';
import { FormData, ListItem } from '../config/types';
import { FormData, InstanceTypeItem, ListItem } from '../config/types';
export const GPU_SERVICE_INSTANCES_API = '/gpu-service-instances';
export const GPU_SERVICE_INSTANCES_API = (namespace: string) =>
`/proxy/apis/worker.gpustack.ai/v1/namespaces/${namespace}/instances`;
export const GPU_SERVICE_INSTANCES_TYPE_API =
'/proxy/apis/worker.gpustack.ai/v1/instancetypes';
export async function queryGPUServiceInstances(
params: Global.SearchParams,
params: Global.K8sSearchParams,
options?: any
) {
// return request<Global.PageResponse<ListItem>>(GPU_SERVICE_INSTANCES_API, {
@@ -35,7 +39,7 @@ export async function queryGPUServiceInstances(
page,
perPage
}
} as Global.PageResponse<ListItem>;
} as Global.K8sPageResponse<ListItem>;
}
export async function createGPUServiceInstance(params: { data: FormData }) {
@@ -62,3 +66,35 @@ export async function deleteGPUServiceInstance(id: number) {
method: 'DELETE'
});
}
// =========== Instance Types ===========
export async function queryGPUServiceInstanceTypes(
params: Global.K8sSearchParams,
options?: any
) {
return request<Global.K8sPageResponse<InstanceTypeItem>>(
GPU_SERVICE_INSTANCES_TYPE_API,
{
method: 'GET',
params,
cancelToken: options?.token
}
);
}
export async function queryGPUServiceInstanceTypeItems(
params: {
name: string;
},
options?: any
) {
return request<InstanceTypeItem>(
`${GPU_SERVICE_INSTANCES_TYPE_API}/${params.name}`,
{
method: 'GET',
params,
cancelToken: options?.token
}
);
}
+87 -14
View File
@@ -1,23 +1,57 @@
export interface FormData {
export type ImagePullPolicy = 'Always' | 'IfNotPresent' | 'Never';
export interface InstanceEnvVar {
name: string;
description?: string;
image?: string;
instance_type?: string;
instance_type_id?: number;
template_id?: number;
gpu_count?: number;
replicas?: number;
storage_mode?: string;
storage_id?: number;
local_storage_size_gb?: number;
cluster_id?: number;
mount_path?: string;
value?: string;
}
export interface InstancePort {
port: number;
protocol?: string;
}
export interface InstanceResources {
cpu?: string;
ram?: string;
localStorage?: string;
accelerator?: string;
}
export interface InstanceVolume {
ephemeral?: {
capacity?: string;
};
persistent?: {
name: string;
};
}
// instance form data
export interface FormData {
metadata: {
name: string;
namespace: string;
};
spec: {
image: string;
displayName: string;
command: string[];
ports: InstancePort[];
env: InstanceEnvVar[];
volumeMount: string;
resources: InstanceResources;
description: string;
volume: InstanceVolume;
sshPublicKey: {
name: string;
};
};
}
// instance list item
export interface ListItem extends FormData {
id: number;
status?: string;
endpoint?: string;
created_at?: string;
updated_at?: string;
}
@@ -31,3 +65,42 @@ export interface InstanceItem {
gpu_count: number;
status: string; // available, unavailable
}
export interface InstanceTypeSpec {
acceleratable: boolean;
computeCapability?: string;
family?: string;
group: string;
manufacturer?: string;
memory?: string;
product?: string;
sliced?: number;
}
export interface InstanceTypeResource {
capacity?: string;
onceMaxRequest?: string;
remaining?: string;
}
export interface InstanceTypeStatus {
accelerator: InstanceTypeResource;
cpu: InstanceTypeResource;
localStorage: InstanceTypeResource;
phase: string;
phaseMessage?: string;
ram: InstanceTypeResource;
}
export interface InstanceTypeItem {
apiVersion: string;
kind: string;
metadata: {
name: string;
namespace: string;
};
id: number;
name: string;
spec: InstanceTypeSpec;
status: InstanceTypeStatus;
}
@@ -1,6 +1,8 @@
import { PageAction } from '@/config';
import { PageActionType } from '@/config/types';
import {
CheckboxField,
Input as CInput,
CollapsePanel,
IconFont,
ScrollSpyTabs,
@@ -206,6 +208,20 @@ const GPUServiceInstanceForm: React.FC<InstanceFormProps> = forwardRef(
}
]}
/>
<Form.Item<FormData>
name="enable_ssh"
valuePropName="checked"
style={{ marginBottom: 8 }}
>
<CheckboxField label={'SSH Terminal Access'}></CheckboxField>
</Form.Item>
<Form.Item<FormData>
data-field="name"
hidden
name={['spec', 'sshPublicKey', 'name']}
>
<CInput.Input />
</Form.Item>
</Form>
</ScrollSpyTabs>
);
@@ -1,7 +1,6 @@
import { InputNumber as CInputNumber, Input, Select } from '@gpustack/core-ui';
import { InputNumber as CInputNumber, Select } from '@gpustack/core-ui';
import { Button, Flex, Form, Radio } from 'antd';
import styled from 'styled-components';
import { StorageStatusValueMap } from '../../storage/config';
import { mockStorageData } from '../../storage/config/mock-data';
import { StorageModeValueMap } from '../config';
import { FormData } from '../config/types';
@@ -57,29 +56,24 @@ const StorageVolume = () => {
</Flex>
{storageMode === StorageModeValueMap.Existing && (
<div style={{ display: 'flex', alignItems: 'flex-start', gap: 12 }}>
<div style={{ flex: 1 }}>
<Form.Item<FormData>
name="storage_id"
rules={[
{
required: true,
message: '请选择预存储卷'
}
]}
>
<Select
label="持久卷"
required
options={mockStorageData.map((item) => ({
label: `${item.name} / ${item.capacity_gb ?? '-'} GB`,
value: item.id,
disabled: item.status !== StorageStatusValueMap.Available
}))}
/>
</Form.Item>
</div>
</div>
<Form.Item<FormData>
name="storage_id"
rules={[
{
required: true,
message: '请选择预存储卷'
}
]}
>
<Select
label="持久卷"
required
options={mockStorageData.map((item) => ({
label: `${item.metadata?.name} / ${item.spec?.capacity ?? '-'}`,
value: item.id
}))}
/>
</Form.Item>
)}
{storageMode === StorageModeValueMap.Temporary && (
@@ -95,22 +89,6 @@ const StorageVolume = () => {
<CInputNumber min={1} precision={0} label="存储容量 (GB)" required />
</Form.Item>
)}
{/* 挂载路径 */}
<Form.Item<FormData>
name="mount_path"
rules={[
{
required: true,
message: '请输入存储挂载路径'
}
]}
>
<Input.Input
label="挂载路径"
required
placeholder="挂载路径须以 / 开头"
/>
</Form.Item>
</FieldBlock>
);
};