fix: storage api alignment
This commit is contained in:
@@ -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
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user