From 7be702ef0dd345a0962bccc1ffe280ee8a892dda Mon Sep 17 00:00:00 2001 From: Mathieu <70369997+MathieuRA@users.noreply.github.com> Date: Fri, 13 Jun 2025 14:54:29 +0200 Subject: [PATCH] feat(@xen-orchestra/rest-api): expose pgpus (#8684) --- @vates/types/src/xen-api.mts | 7 +++ @vates/types/src/xo.mts | 32 +++++++++++- .../open-api/oa-examples/pgpu.oa-example.mts | 38 ++++++++++++++ .../rest-api/src/pgpus/pgpu.controller.mts | 50 +++++++++++++++++++ .../rest-api/src/rest-api/rest-api.type.mts | 8 ++- CHANGELOG.unreleased.md | 1 + 6 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 @xen-orchestra/rest-api/src/open-api/oa-examples/pgpu.oa-example.mts create mode 100644 @xen-orchestra/rest-api/src/pgpus/pgpu.controller.mts diff --git a/@vates/types/src/xen-api.mts b/@vates/types/src/xen-api.mts index 391b12fb27..d597b72f31 100644 --- a/@vates/types/src/xen-api.mts +++ b/@vates/types/src/xen-api.mts @@ -1047,6 +1047,8 @@ export interface XenApiPgpu { supported_VGPU_types: XenApiVgpuType['$ref'][] uuid: string } +export type XenApiPgpuWrapped = WrapperXenApi + export interface XenApiGpuGroup { $ref: Branded<'GPU_group'> @@ -1061,6 +1063,7 @@ export interface XenApiGpuGroup { uuid: string VGPUs: XenApiVgpu['$ref'][] } +export type XenApiGpuGroupWrapped = WrapperXenApi export interface XenApiVgpu { $ref: Branded<'VGPU'> @@ -1098,6 +1101,7 @@ export interface XenApiVgpuType { vendor_name: string VGPUs: XenApiVgpu['$ref'][] } +export type XenApiVgpuTypeWrapped = WrapperXenApi export interface XenApiPvsSite { $ref: Branded<'PVS_site'> @@ -1358,3 +1362,6 @@ export type WrappedXenApiRecord = | XenApiVmWrapped | XenApiVtpmWrapped | XenApiPciWrapped + | XenApiGpuGroupWrapped + | XenApiPgpuWrapped + | XenApiVgpuTypeWrapped diff --git a/@vates/types/src/xo.mts b/@vates/types/src/xo.mts index 712143fabb..b39b54d0b5 100644 --- a/@vates/types/src/xo.mts +++ b/@vates/types/src/xo.mts @@ -9,6 +9,7 @@ import type { IP_CONFIGURATION_MODE, IPV6_CONFIGURATION_MODE, NETWORK_OPERATIONS, + PGPU_DOM0_ACCESS, POOL_ALLOWED_OPERATIONS, PRIMARY_ADDRESS_TYPE, STORAGE_OPERATIONS, @@ -143,6 +144,11 @@ export type XoBackupRepository = { url: string } +export type XoGpuGroup = BaseXapiXo & { + id: Branded<'gpu-group'> + type: 'gpuGroup' +} + export type XoGroup = { id: Branded<'group'> name: string @@ -286,8 +292,24 @@ export type XoPci = BaseXapiXo & { } export type XoPgpu = BaseXapiXo & { + $host: XoHost['id'] + $vgpus: XoVgpu['id'][] + + dom0Access: PGPU_DOM0_ACCESS + enabledVgpuTypes: XoVgpuType['id'][] + gpuGroup?: XoGpuGroup['id'] + host: XoHost['id'] id: Branded<'PGPU'> + isSystemDisplayDevice: boolean + pci?: XoPci['id'] + // it seems that supportedVgpuMaxCapcities always return undefined (See: xapi-objet-to-xo) + /** + * @deprecated + */ + supportedVgpuMaxCapcities?: never + supportedVgpuTypes: XoVgpuType['id'][] type: 'PGPU' + vgpus: XoVgpu['id'][] } export type XoPif = BaseXapiXo & { @@ -514,7 +536,12 @@ export type XoVdiUnmanaged = BaseXoVdi & { export type XoVgpu = BaseXapiXo & { id: Branded<'VGPU'> - type: 'VGPU' + type: 'vgpu' +} + +export type XoVgpuType = BaseXapiXo & { + id: Branded<'vgpu-type'> + type: 'vgpuType' } export type XoVif = BaseXapiXo & { @@ -583,10 +610,12 @@ export type XoVtpm = BaseXapiXo & { export type XapiXoRecord = | XoAlarm + | XoGpuGroup | XoHost | XoMessage | XoNetwork | XoPci + | XoPgpu | XoPif | XoPool | XoSr @@ -595,6 +624,7 @@ export type XapiXoRecord = | XoVdiSnapshot | XoVdiUnmanaged | XoVgpu + | XoVgpuType | XoVif | XoVm | XoVmController diff --git a/@xen-orchestra/rest-api/src/open-api/oa-examples/pgpu.oa-example.mts b/@xen-orchestra/rest-api/src/open-api/oa-examples/pgpu.oa-example.mts new file mode 100644 index 0000000000..a981352f2a --- /dev/null +++ b/@xen-orchestra/rest-api/src/open-api/oa-examples/pgpu.oa-example.mts @@ -0,0 +1,38 @@ +export const pgpuIds = [ + '/rest/v0/pgpus/838335fa-ee21-15e1-760a-a37a3a4ef1db', + '/rest/v0/pgpus/4062d698-50aa-c53a-9974-9806bb38bf8d', +] + +export const partialPgpus = [ + { + id: '838335fa-ee21-15e1-760a-a37a3a4ef1db', + dom0Access: 'enabled', + gpuGroup: '8f77aa2b-db69-a6b7-b36e-597aafe40f05', + href: '/rest/v0/pgpus/838335fa-ee21-15e1-760a-a37a3a4ef1db', + }, + { + id: '4062d698-50aa-c53a-9974-9806bb38bf8d', + dom0Access: 'enabled', + gpuGroup: '8f77aa2b-db69-a6b7-b36e-597aafe40f05', + href: '/rest/v0/pgpus/4062d698-50aa-c53a-9974-9806bb38bf8d', + }, +] + +export const pgpu = { + type: 'PGPU', + dom0Access: 'enabled', + enabledVgpuTypes: [], + gpuGroup: '8f77aa2b-db69-a6b7-b36e-597aafe40f05', + isSystemDisplayDevice: true, + pci: '8b515224-0c6c-c498-5ece-39f64d9b7b20', + supportedVgpuTypes: [], + host: '84e555d8-267a-4720-aa5f-fd19035aadae', + $host: '84e555d8-267a-4720-aa5f-fd19035aadae', + vgpus: [], + $vgpus: [], + id: '838335fa-ee21-15e1-760a-a37a3a4ef1db', + uuid: '838335fa-ee21-15e1-760a-a37a3a4ef1db', + $pool: 'b7569d99-30f8-178a-7d94-801de3e29b5b', + $poolId: 'b7569d99-30f8-178a-7d94-801de3e29b5b', + _xapiRef: 'OpaqueRef:c842190a-381d-1616-f363-c031a54c3526', +} diff --git a/@xen-orchestra/rest-api/src/pgpus/pgpu.controller.mts b/@xen-orchestra/rest-api/src/pgpus/pgpu.controller.mts new file mode 100644 index 0000000000..629a40b698 --- /dev/null +++ b/@xen-orchestra/rest-api/src/pgpus/pgpu.controller.mts @@ -0,0 +1,50 @@ +import { inject } from 'inversify' +import type { XoPgpu } from '@vates/types' +import type { Request as ExRequest } from 'express' + +import { RestApi } from '../rest-api/rest-api.mjs' +import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs' +import { Example, Get, Path, Query, Request, Response, Route, Security, Tags } from 'tsoa' +import { notFoundResp, unauthorizedResp, Unbrand } from '../open-api/common/response.common.mjs' +import { provide } from 'inversify-binding-decorators' +import type { SendObjects } from '../helpers/helper.type.mjs' +import { partialPgpus, pgpu, pgpuIds } from '../open-api/oa-examples/pgpu.oa-example.mjs' + +@Route('pgpus') +@Security('*') +@Response(unauthorizedResp.status, unauthorizedResp.description) +@Tags('pgpus') +@provide(PgpuController) +export class PgpuController extends XapiXoController { + constructor(@inject(RestApi) restApi: RestApi) { + super('PGPU', restApi) + } + + /** + * @example fields "id,dom0Access,gpuGroup" + * @example filter "dom0Access:enabled" + * @example limit 42 + */ + @Example(pgpuIds) + @Example(partialPgpus) + @Get('') + getPgpus( + @Request() req: ExRequest, + @Query() fields?: string, + @Query() ndjson?: boolean, + @Query() filter?: string, + @Query() limit?: number + ): SendObjects>> { + return this.sendObjects(Object.values(this.getObjects({ filter, limit })), req) + } + + /** + * @example id "838335fa-ee21-15e1-760a-a37a3a4ef1db" + */ + @Example(pgpu) + @Get('{id}') + @Response(notFoundResp.status, notFoundResp.description) + getPgpu(@Path() id: string): Unbrand { + return this.getObject(id as XoPgpu['id']) + } +} diff --git a/@xen-orchestra/rest-api/src/rest-api/rest-api.type.mts b/@xen-orchestra/rest-api/src/rest-api/rest-api.type.mts index a9ec4bc80a..e19ee68195 100644 --- a/@xen-orchestra/rest-api/src/rest-api/rest-api.type.mts +++ b/@xen-orchestra/rest-api/src/rest-api/rest-api.type.mts @@ -3,15 +3,18 @@ import type { Task } from '@vates/types/lib/vates/task' import type { Xapi } from '@vates/types/lib/xen-orchestra/xapi' import type { XapiHostStats, XapiVmStats, XapiStatsGranularity, BACKUP_TYPE } from '@vates/types/common' import type { + XenApiGpuGroupWrapped, XenApiHostWrapped, XenApiMessage, XenApiNetworkWrapped, XenApiPciWrapped, + XenApiPgpuWrapped, XenApiPifWrapped, XenApiPoolWrapped, XenApiSrWrapped, XenApiVbdWrapped, XenApiVdiWrapped, + XenApiVgpuTypeWrapped, XenApiVgpuWrapped, XenApiVifWrapped, XenApiVmWrapped, @@ -34,10 +37,12 @@ import type { import type { InsertableXoServer } from '../servers/server.type.mjs' type XapiRecordByXapiXoRecord = { + gpuGroup: XenApiGpuGroupWrapped host: XenApiHostWrapped message: XenApiMessage network: XenApiNetworkWrapped PCI: XenApiPciWrapped + PGPU: XenApiPgpuWrapped PIF: XenApiPifWrapped pool: XenApiPoolWrapped SR: XenApiSrWrapped @@ -45,7 +50,8 @@ type XapiRecordByXapiXoRecord = { VDI: XenApiVdiWrapped 'VDI-snapshot': XenApiVdiWrapped 'VDI-unmanaged': XenApiVdiWrapped - VGPU: XenApiVgpuWrapped + vgpu: XenApiVgpuWrapped + vgpuType: XenApiVgpuTypeWrapped VIF: XenApiVifWrapped VM: XenApiVmWrapped 'VM-controller': XenApiVmWrapped diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 3b01959640..29daa715a6 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -30,6 +30,7 @@ - [REST API] Ability to create a network `POST /rest/v0/pools/` (PR [#8671](https://github.com/vatesfr/xen-orchestra/pull/8671)) - [REST API] Expose `GET /rest/v0/pcis` and `GET /rest/v0/pcis/` (PR [#8686](https://github.com/vatesfr/xen-orchestra/pull/8686)) +- [REST API] expose `GET /rest/v0/pgpus` and `GET /rest/v0/pgpus/` (PR [#8684](https://github.com/vatesfr/xen-orchestra/pull/8684)) - **Azure Blob Storage**: - [Backups]: Implemented Azure Blob Storage for backups, Integrating with both the Azurite emulator and Azure (PR [#8415](https://github.com/vatesfr/xen-orchestra/pull/8415))