mirror of
https://github.com/vatesfr/xen-orchestra.git
synced 2026-11-10 01:15:35 -06:00
feat(rest-api): add POST /vbds endpoint to create VBDs (#9391)
This commit is contained in:
@@ -5,10 +5,12 @@ import {
|
||||
XenApiRecord,
|
||||
XenApiSr,
|
||||
XenApiTask,
|
||||
XenApiVbd,
|
||||
XenApiVdi,
|
||||
XenApiVm,
|
||||
XenApiVmWrapped,
|
||||
} from '../xen-api.mjs'
|
||||
import type { OPAQUE_REF_NULL, VBD_MODE, VBD_TYPE } from '../common.mjs'
|
||||
import type { PassThrough, Readable } from 'node:stream'
|
||||
import type {
|
||||
XoGpuGroup,
|
||||
@@ -177,6 +179,19 @@ export interface Xapi {
|
||||
creatorId?: XoUser['id'],
|
||||
opts?: { destroyAllVifs: boolean }
|
||||
): Promise<XenApiVmWrapped>
|
||||
VBD_create(params: {
|
||||
bootable?: boolean
|
||||
empty?: boolean
|
||||
mode?: VBD_MODE
|
||||
other_config?: Record<string, string>
|
||||
qos_algorithm_params?: Record<string, string>
|
||||
qos_algorithm_type?: string
|
||||
type?: VBD_TYPE
|
||||
unpluggable?: boolean
|
||||
userdevice?: string
|
||||
VDI: XenApiVdi['$ref'] | OPAQUE_REF_NULL
|
||||
VM: XenApiVm['$ref']
|
||||
}): Promise<XenApiVbd['$ref']>
|
||||
VDI_destroy(vdiRef: XenApiVdi['$ref']): Promise<void>
|
||||
VDI_destroyCloudInitConfig(vdiRef: XenApiVdi['$ref'], opts?: { timeLimit?: number }): Promise<void>
|
||||
VDI_exportContent(
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
export const vbdId = {
|
||||
id: '5f9a4c0b-3548-6171-4396-699a0e56cc60',
|
||||
}
|
||||
|
||||
export const vbdIds = [
|
||||
'/rest/v0/vbds/5f9a4c0b-3548-6171-4396-699a0e56cc60',
|
||||
'/rest/v0/vbds/60c7c9b6-35ba-1791-67b5-6aaf90eea11d',
|
||||
|
||||
@@ -1,14 +1,38 @@
|
||||
import { Example, Get, Path, Query, Request, Response, Route, Security, Tags } from 'tsoa'
|
||||
import {
|
||||
Body,
|
||||
Example,
|
||||
Get,
|
||||
Middlewares,
|
||||
Path,
|
||||
Post,
|
||||
Query,
|
||||
Request,
|
||||
Response,
|
||||
Route,
|
||||
Security,
|
||||
SuccessResponse,
|
||||
Tags,
|
||||
} from 'tsoa'
|
||||
import { json } from 'express'
|
||||
import { inject } from 'inversify'
|
||||
import { invalidParameters as invalidParametersError } from 'xo-common/api-errors.js'
|
||||
import { provide } from 'inversify-binding-decorators'
|
||||
import type { Request as ExRequest } from 'express'
|
||||
import type { XoAlarm, XoMessage, XoTask, XoVbd } from '@vates/types'
|
||||
import type { Xapi, XoAlarm, XoMessage, XoTask, XoVbd, XoVdi, XoVm } from '@vates/types'
|
||||
|
||||
import { AlarmService } from '../alarms/alarm.service.mjs'
|
||||
import { escapeUnsafeComplexMatcher } from '../helpers/utils.helper.mjs'
|
||||
import { genericAlarmsExample } from '../open-api/oa-examples/alarm.oa-example.mjs'
|
||||
import { badRequestResp, notFoundResp, unauthorizedResp, type Unbrand } from '../open-api/common/response.common.mjs'
|
||||
import { partialVbds, vbd, vbdIds } from '../open-api/oa-examples/vbd.oa-example.mjs'
|
||||
import {
|
||||
badRequestResp,
|
||||
createdResp,
|
||||
invalidParameters,
|
||||
notFoundResp,
|
||||
unauthorizedResp,
|
||||
type Unbrand,
|
||||
} from '../open-api/common/response.common.mjs'
|
||||
import { BASE_URL } from '../index.mjs'
|
||||
import { partialVbds, vbd, vbdId, vbdIds } from '../open-api/oa-examples/vbd.oa-example.mjs'
|
||||
import { RestApi } from '../rest-api/rest-api.mjs'
|
||||
import type { SendObjects } from '../helpers/helper.type.mjs'
|
||||
import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs'
|
||||
@@ -28,6 +52,45 @@ export class VbdController extends XapiXoController<XoVbd> {
|
||||
this.#alarmService = alarmService
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a VBD to attach a VDI to a VM
|
||||
*
|
||||
* @example body { "VM": "4fe90510-8da4-1530-38e2-a7876ef374c7", "VDI": "656052a2-2e3e-467b-88ba-63a9ea5e4a54", "bootable": false, "mode": "RW" }
|
||||
*/
|
||||
@Example(vbdId)
|
||||
@Post('')
|
||||
@Middlewares(json())
|
||||
@SuccessResponse(createdResp.status, createdResp.description)
|
||||
@Response(notFoundResp.status, notFoundResp.description)
|
||||
@Response(invalidParameters.status, invalidParameters.description)
|
||||
async createVbd(
|
||||
@Body() body: Omit<Unbrand<Parameters<Xapi['VBD_create']>[0]>, 'VM' | 'VDI'> & { VM: string; VDI: string }
|
||||
): Promise<{ id: string }> {
|
||||
const xoVm = this.restApi.getObject<XoVm>(body.VM as XoVm['id'], 'VM')
|
||||
const xoVdi = this.restApi.getObject<XoVdi>(body.VDI as XoVdi['id'], 'VDI')
|
||||
|
||||
if (xoVm.$pool !== xoVdi.$pool) {
|
||||
throw invalidParametersError('VM and VDI must be in the same pool')
|
||||
}
|
||||
|
||||
const xapiVm = this.restApi.getXapiObject<XoVm>(xoVm.id, 'VM')
|
||||
const xapiVdi = this.restApi.getXapiObject<XoVdi>(xoVdi.id, 'VDI')
|
||||
|
||||
const xapi = xapiVm.$xapi
|
||||
|
||||
const vbdRef = await xapi.VBD_create({
|
||||
...body,
|
||||
VDI: xapiVdi.$ref,
|
||||
VM: xapiVm.$ref,
|
||||
})
|
||||
|
||||
const vbdUuid = await xapi.call<string>('VBD.get_uuid', vbdRef)
|
||||
|
||||
this.setHeader('Location', `${BASE_URL}/vbds/${vbdUuid}`)
|
||||
|
||||
return { id: vbdUuid }
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @example fields "device,bootable,uuid"
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
- [vhd-cli] Prevent using invalid options (PR [#9386](https://github.com/vatesfr/xen-orchestra/pull/9386))
|
||||
- [REST API] Add endpoints to reconfigure management interface for hosts and pools (PR [#9369](https://github.com/vatesfr/xen-orchestra/pull/9369))
|
||||
- [VM] Add "Change state" button on VM view (PR [#9317](https://github.com/vatesfr/xen-orchestra/pull/9317))
|
||||
- [REST API] Add `POST /vbds` endpoint to create a VBD (attach a VDI to a VM) (PR [#9391](https://github.com/vatesfr/xen-orchestra/pull/9391))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user