fix: update onceMaxRequest field
This commit is contained in:
@@ -8,7 +8,7 @@ export default {
|
|||||||
'menu.playground.text2images': 'Image',
|
'menu.playground.text2images': 'Image',
|
||||||
'menu.playground.video': 'Video',
|
'menu.playground.video': 'Video',
|
||||||
'menu.compare': 'Compare',
|
'menu.compare': 'Compare',
|
||||||
'menu.models': 'Models',
|
'menu.models': 'Model Service',
|
||||||
'menu.models.modelList': 'Deploy & Manage',
|
'menu.models.modelList': 'Deploy & Manage',
|
||||||
'menu.models.modelCatalog': 'Catalog',
|
'menu.models.modelCatalog': 'Catalog',
|
||||||
'menu.models.catalog': 'Model Catalog',
|
'menu.models.catalog': 'Model Catalog',
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default {
|
|||||||
'menu.playground.text2images': '画像生成',
|
'menu.playground.text2images': '画像生成',
|
||||||
'menu.playground.video': '動画',
|
'menu.playground.video': '動画',
|
||||||
'menu.compare': '比較',
|
'menu.compare': '比較',
|
||||||
'menu.models': 'モデル',
|
'menu.models': 'モデルサービス',
|
||||||
'menu.models.modelList': 'デプロイと管理',
|
'menu.models.modelList': 'デプロイと管理',
|
||||||
'menu.models.modelCatalog': 'カタログ',
|
'menu.models.modelCatalog': 'カタログ',
|
||||||
'menu.models.catalog': 'モデルカタログ',
|
'menu.models.catalog': 'モデルカタログ',
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default {
|
|||||||
'menu.playground.text2images': 'Генерация изображений',
|
'menu.playground.text2images': 'Генерация изображений',
|
||||||
'menu.playground.video': 'Видео',
|
'menu.playground.video': 'Видео',
|
||||||
'menu.compare': 'Сравнение',
|
'menu.compare': 'Сравнение',
|
||||||
'menu.models': 'Модели',
|
'menu.models': 'Сервисы моделей',
|
||||||
'menu.models.modelList': 'Развертывание и управление',
|
'menu.models.modelList': 'Развертывание и управление',
|
||||||
'menu.models.modelCatalog': 'Каталог',
|
'menu.models.modelCatalog': 'Каталог',
|
||||||
'menu.models.catalog': 'Каталог моделей',
|
'menu.models.catalog': 'Каталог моделей',
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default {
|
|||||||
'menu.playground.text2images': 'Görsel',
|
'menu.playground.text2images': 'Görsel',
|
||||||
'menu.playground.video': 'Video',
|
'menu.playground.video': 'Video',
|
||||||
'menu.compare': 'Karşılaştır',
|
'menu.compare': 'Karşılaştır',
|
||||||
'menu.models': 'Modeller',
|
'menu.models': 'Model Hizmetleri',
|
||||||
'menu.models.modelList': 'Dağıt ve Yönet',
|
'menu.models.modelList': 'Dağıt ve Yönet',
|
||||||
'menu.models.modelCatalog': 'Katalog',
|
'menu.models.modelCatalog': 'Katalog',
|
||||||
'menu.models.catalog': 'Model Kataloğu',
|
'menu.models.catalog': 'Model Kataloğu',
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default {
|
|||||||
'menu.playground.text2images': '图像',
|
'menu.playground.text2images': '图像',
|
||||||
'menu.playground.video': '视频',
|
'menu.playground.video': '视频',
|
||||||
'menu.compare': '多模型对比',
|
'menu.compare': '多模型对比',
|
||||||
'menu.models': '模型',
|
'menu.models': '模型服务',
|
||||||
'menu.models.modelList': '部署与管理',
|
'menu.models.modelList': '部署与管理',
|
||||||
'menu.models.modelCatalog': '模型库',
|
'menu.models.modelCatalog': '模型库',
|
||||||
'menu.models.deployment': '部署',
|
'menu.models.deployment': '部署',
|
||||||
|
|||||||
@@ -86,8 +86,8 @@ const useClusterColumns = (
|
|||||||
// `clusterDetail.linkableName`. Without a plugin we render the
|
// `clusterDetail.linkableName`. Without a plugin we render the
|
||||||
// name as plain text (matches the pre-restore behaviour); with one
|
// name as plain text (matches the pre-restore behaviour); with one
|
||||||
// we use Typography.Link wired to the parent's `onCellClick`.
|
// we use Typography.Link wired to the parent's `onCellClick`.
|
||||||
const nameLinkable: boolean = !!getGPUStackPlugin()?.clusterDetail
|
const nameLinkable: boolean =
|
||||||
?.linkableName;
|
!!getGPUStackPlugin()?.clusterDetail?.linkableName;
|
||||||
|
|
||||||
const setActionsItems = (row: ClusterListItem) => {
|
const setActionsItems = (row: ClusterListItem) => {
|
||||||
return clusterActionList.filter((item) => {
|
return clusterActionList.filter((item) => {
|
||||||
@@ -112,9 +112,7 @@ const useClusterColumns = (
|
|||||||
<>
|
<>
|
||||||
<AutoTooltip ghost title={text}>
|
<AutoTooltip ghost title={text}>
|
||||||
{nameLinkable ? (
|
{nameLinkable ? (
|
||||||
<Typography.Link
|
<Typography.Link onClick={() => onCellClick?.(record, 'name')}>
|
||||||
onClick={() => onCellClick?.(record, 'name')}
|
|
||||||
>
|
|
||||||
{record.name}
|
{record.name}
|
||||||
</Typography.Link>
|
</Typography.Link>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -83,13 +83,11 @@ const InstanceTypeItem: React.FC<InstanceTypeItemProps> = ({ item }) => {
|
|||||||
const specData = item.spec || {};
|
const specData = item.spec || {};
|
||||||
const acceleratable = specData.acceleratable;
|
const acceleratable = specData.acceleratable;
|
||||||
|
|
||||||
const manufacturerKey = specData.manufacturer || (acceleratable ? '' : 'cpu');
|
const manufacturer = acceleratable ? specData.manufacturer || '' : 'cpu';
|
||||||
const manufacturer = manufacturerKey?.toUpperCase();
|
const manufacturerColor = manufactureColorMap[manufacturer] ?? 'purple';
|
||||||
const manufacturerColor =
|
|
||||||
(manufacturerKey && manufactureColorMap[manufacturerKey]) ?? 'purple';
|
|
||||||
|
|
||||||
// resource remaining status
|
// resource once-max-request status
|
||||||
const remainingData = item.status?.remaining || {};
|
const onceMaxRequestData = item.status?.onceMaxRequest || {};
|
||||||
|
|
||||||
const renderName = () => {
|
const renderName = () => {
|
||||||
const displayName = specData.acceleratable
|
const displayName = specData.acceleratable
|
||||||
@@ -113,7 +111,7 @@ const InstanceTypeItem: React.FC<InstanceTypeItemProps> = ({ item }) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ThemeTag color={manufacturerColor} disabled={false}>
|
<ThemeTag color={manufacturerColor} disabled={false}>
|
||||||
{manufacturer}
|
{manufacturer?.toUpperCase()}
|
||||||
</ThemeTag>
|
</ThemeTag>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@@ -157,14 +155,14 @@ const InstanceTypeItem: React.FC<InstanceTypeItemProps> = ({ item }) => {
|
|||||||
showDot={false}
|
showDot={false}
|
||||||
icon="icon-ram-02"
|
icon="icon-ram-02"
|
||||||
label={intl.formatMessage({ id: 'gpuservice.instance.ram' })}
|
label={intl.formatMessage({ id: 'gpuservice.instance.ram' })}
|
||||||
value={toDisplayUnit(convertKiToGi(remainingData.ram)) ?? '-'}
|
value={toDisplayUnit(convertKiToGi(onceMaxRequestData.ram)) ?? '-'}
|
||||||
></MetaItem>
|
></MetaItem>
|
||||||
<MetaItem
|
<MetaItem
|
||||||
show={!!remainingData.cpu}
|
show={!!onceMaxRequestData.cpu}
|
||||||
showDot={true}
|
showDot={true}
|
||||||
icon="icon-cpu"
|
icon="icon-cpu"
|
||||||
label="CPU"
|
label="CPU"
|
||||||
value={remainingData.cpu ?? '-'}
|
value={onceMaxRequestData.cpu ?? '-'}
|
||||||
></MetaItem>
|
></MetaItem>
|
||||||
</span>
|
</span>
|
||||||
</Meta>
|
</Meta>
|
||||||
|
|||||||
@@ -183,20 +183,20 @@ const parseQuantity = (value?: string | null): number => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Returns the slider max for the accelerator count: the largest
|
// Returns the slider max for the accelerator count: the largest
|
||||||
// tier.onceMaxRequest across all acceleratorTiers (not from candidates).
|
// tier.onceMaxRequest.accelerator across all acceleratorTiers (not from candidates).
|
||||||
export const getAcceleratorMax = (
|
export const getAcceleratorMax = (
|
||||||
tiers?: { onceMaxRequest: string }[] | null
|
tiers?: { onceMaxRequest: { accelerator?: string } }[] | null
|
||||||
) => {
|
) => {
|
||||||
if (!tiers?.length) return 0;
|
if (!tiers?.length) return 0;
|
||||||
return tiers.reduce((acc, tier) => {
|
return tiers.reduce((acc, tier) => {
|
||||||
const n = parseQuantity(tier.onceMaxRequest);
|
const n = parseQuantity(tier.onceMaxRequest?.accelerator);
|
||||||
return n > acc ? n : acc;
|
return n > acc ? n : acc;
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Picks the candidate (cluster + type name) that should fulfill a requested
|
// Picks the candidate (cluster + type name) that should fulfill a requested
|
||||||
// accelerator count: the first candidate of the smallest tier whose
|
// accelerator count: the first candidate of the smallest tier whose
|
||||||
// onceMaxRequest is >= the requested count and whose cpu/ram/localStorage
|
// onceMaxRequest.accelerator is >= the requested count and whose cpu/ram/localStorage
|
||||||
// remaining are all > 0.
|
// remaining are all > 0.
|
||||||
export const pickCandidateForAccelerator = <
|
export const pickCandidateForAccelerator = <
|
||||||
C extends {
|
C extends {
|
||||||
@@ -208,7 +208,10 @@ export const pickCandidateForAccelerator = <
|
|||||||
}
|
}
|
||||||
>(
|
>(
|
||||||
tiers:
|
tiers:
|
||||||
| { onceMaxRequest: string; candidates?: C[] | null }[]
|
| {
|
||||||
|
onceMaxRequest: { accelerator?: string };
|
||||||
|
candidates?: C[] | null;
|
||||||
|
}[]
|
||||||
| undefined
|
| undefined
|
||||||
| null,
|
| null,
|
||||||
count: number
|
count: number
|
||||||
@@ -221,12 +224,14 @@ export const pickCandidateForAccelerator = <
|
|||||||
parseQuantity(c.localStorage?.remaining) > 0;
|
parseQuantity(c.localStorage?.remaining) > 0;
|
||||||
|
|
||||||
const sorted = [...tiers].sort(
|
const sorted = [...tiers].sort(
|
||||||
(a, b) => parseQuantity(a.onceMaxRequest) - parseQuantity(b.onceMaxRequest)
|
(a, b) =>
|
||||||
|
parseQuantity(a.onceMaxRequest?.accelerator) -
|
||||||
|
parseQuantity(b.onceMaxRequest?.accelerator)
|
||||||
);
|
);
|
||||||
|
|
||||||
// count === 0 ? parseQuantity(tier.onceMaxRequest) > count; this is CPU-only case.
|
// count === 0 ? parseQuantity(tier.onceMaxRequest.accelerator) > count; this is CPU-only case.
|
||||||
for (const tier of sorted) {
|
for (const tier of sorted) {
|
||||||
const fits = parseQuantity(tier.onceMaxRequest) >= count;
|
const fits = parseQuantity(tier.onceMaxRequest?.accelerator) >= count;
|
||||||
if (!fits) continue;
|
if (!fits) continue;
|
||||||
const candidate = tier.candidates?.find(hasResources);
|
const candidate = tier.candidates?.find(hasResources);
|
||||||
if (candidate) return candidate;
|
if (candidate) return candidate;
|
||||||
|
|||||||
@@ -28,9 +28,6 @@ export interface FormData {
|
|||||||
cpu?: string;
|
cpu?: string;
|
||||||
ram?: string;
|
ram?: string;
|
||||||
localStorage?: string;
|
localStorage?: string;
|
||||||
// Stored in the form as a number so NumberSelection's strict
|
|
||||||
// equality picks up the active item. Serialized to a string at the
|
|
||||||
// API boundary in handleFinish.
|
|
||||||
accelerator?: number | string;
|
accelerator?: number | string;
|
||||||
};
|
};
|
||||||
volume: {
|
volume: {
|
||||||
@@ -101,12 +98,19 @@ export interface InstanceTypeCandidate {
|
|||||||
localStorage: InstanceTypeResource;
|
localStorage: InstanceTypeResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface InstanceTypeTierOnceMaxRequestResource {
|
||||||
|
accelerator?: string;
|
||||||
|
cpu: string;
|
||||||
|
ram: string;
|
||||||
|
localStorage: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface InstanceTypeTier {
|
export interface InstanceTypeTier {
|
||||||
onceMaxRequest: string;
|
onceMaxRequest: InstanceTypeTierOnceMaxRequestResource;
|
||||||
candidates?: InstanceTypeCandidate[] | null;
|
candidates?: InstanceTypeCandidate[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InstanceTypeRemainingResource {
|
export interface InstanceTypeOnceMaxRequestResource {
|
||||||
accelerator?: string | null;
|
accelerator?: string | null;
|
||||||
cpu: string;
|
cpu: string;
|
||||||
ram: string;
|
ram: string;
|
||||||
@@ -125,7 +129,7 @@ export interface InstanceTypeSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface InstanceTypeStatus {
|
export interface InstanceTypeStatus {
|
||||||
remaining: InstanceTypeRemainingResource;
|
onceMaxRequest: InstanceTypeOnceMaxRequestResource;
|
||||||
acceleratorTiers?: InstanceTypeTier[] | null;
|
acceleratorTiers?: InstanceTypeTier[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,11 +141,6 @@ export interface InstanceTypeItem {
|
|||||||
status: InstanceTypeStatus;
|
status: InstanceTypeStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========== Events / logs (placeholder) ===========
|
|
||||||
// The /v2/gpu-instances API does not yet expose log/event endpoints. These
|
|
||||||
// shapes are retained as minimal placeholders so disabled UI continues to
|
|
||||||
// compile until backend support lands.
|
|
||||||
|
|
||||||
export interface InstanceEventItem {
|
export interface InstanceEventItem {
|
||||||
type?: string;
|
type?: string;
|
||||||
reason?: string;
|
reason?: string;
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import {
|
|||||||
useState
|
useState
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { FormData as PublicKeyFormData } from '../../public-keys/config/types';
|
import { FormData as PublicKeyFormData } from '../../public-keys/config/types';
|
||||||
import useCreateSshkey from '../../public-keys/services/use-create-sshkey';
|
|
||||||
import useQuerySshkeys from '../../public-keys/services/use-query-sshkeys';
|
import useQuerySshkeys from '../../public-keys/services/use-query-sshkeys';
|
||||||
import { DefaultImagePullPolicy } from '../../templates/config';
|
import { DefaultImagePullPolicy } from '../../templates/config';
|
||||||
import TemplateBasicForm, {
|
import TemplateBasicForm, {
|
||||||
@@ -109,7 +108,11 @@ const requiredFields = {
|
|||||||
},
|
},
|
||||||
[TABKeysMap.STORAGE]: {
|
[TABKeysMap.STORAGE]: {
|
||||||
sort: 4,
|
sort: 4,
|
||||||
fields: ['spec.volume.persistent.name', 'spec.volume.ephemeral.capacity']
|
fields: [
|
||||||
|
'spec.volume.persistent.name',
|
||||||
|
'spec.volume.ephemeral.capacity',
|
||||||
|
'spec.sshPublicKeys'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -132,7 +135,6 @@ const GPUServiceInstanceForm: React.FC<InstanceFormProps> = forwardRef(
|
|||||||
realAction === PageAction.CREATE ? PageAction.CREATE : action;
|
realAction === PageAction.CREATE ? PageAction.CREATE : action;
|
||||||
const sshEnabled = Form.useWatch('enable_ssh', form);
|
const sshEnabled = Form.useWatch('enable_ssh', form);
|
||||||
const { sshkeyOptions, fetchData: fetchSSHData } = useQuerySshkeys();
|
const { sshkeyOptions, fetchData: fetchSSHData } = useQuerySshkeys();
|
||||||
const { fetchData: createSshkey } = useCreateSshkey();
|
|
||||||
const [sshOverlayOpen, setSshOverlayOpen] = useState(false);
|
const [sshOverlayOpen, setSshOverlayOpen] = useState(false);
|
||||||
const { getScrollElementScrollableHeight } = useWrapperContext();
|
const { getScrollElementScrollableHeight } = useWrapperContext();
|
||||||
const {
|
const {
|
||||||
|
|||||||
Reference in New Issue
Block a user