mirror of
https://github.com/vatesfr/xen-orchestra.git
synced 2026-09-10 22:14:48 -05:00
feat(@xen-orchestra/rest-api): ability to start a vm on a specific host
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { WrappedXenApiRecord, XenApiNetworkWrapped, XenApiRecord, XenApiSr, XenApiVm } from '../xen-api.mjs'
|
||||
import type { XoHost, XoNetwork, XoPif } from '../xo.mjs'
|
||||
import type { Readable } from 'node:stream'
|
||||
import type { XoHost, XoNetwork, XoPif, XoVm } from '../xo.mjs'
|
||||
|
||||
type XcpPatches = {
|
||||
changelog?: {
|
||||
@@ -59,6 +59,21 @@ export interface Xapi {
|
||||
deleteNetwork(id: XoNetwork['id']): Promise<void>
|
||||
listMissingPatches(host: XoHost['id']): Promise<XcpPatches[] | XsPatches[]>
|
||||
pool_emergencyShutdown(): Promise<void>
|
||||
startVm(
|
||||
id: XoVm['id'],
|
||||
opts?: {
|
||||
bypassMacAddressesCheck?: boolean
|
||||
force?: boolean
|
||||
hostId?: XoHost['id']
|
||||
/**
|
||||
* if startOnly is true and the VM is not halted, throw VM_BAD_POWER_STATE
|
||||
* otherwise, unpause/resume the VM
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
startOnly?: boolean
|
||||
}
|
||||
): Promise<void>
|
||||
VM_import(
|
||||
stream: Readable,
|
||||
srRef?: XenApiSr['$ref'],
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Request as ExRequest } from 'express'
|
||||
import { inject } from 'inversify'
|
||||
import { incorrectState, invalidParameters } from 'xo-common/api-errors.js'
|
||||
import { provide } from 'inversify-binding-decorators'
|
||||
import type { XapiStatsGranularity, XapiVmStats, XenApiVm, XoVm, XoVmSnapshot } from '@vates/types'
|
||||
import type { XapiStatsGranularity, XapiVmStats, XenApiVm, XoHost, XoVm, XoVmSnapshot } from '@vates/types'
|
||||
|
||||
import {
|
||||
asynchronousActionResp,
|
||||
@@ -162,7 +162,10 @@ export class VmController extends XapiXoController<XoVm> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The VM must be halted
|
||||
*
|
||||
* @example id "f07ab729-c0e8-721c-45ec-f11276377030"
|
||||
* @example body { "hostId": "b61a5c92-700e-4966-a13b-00633f03eea8" }
|
||||
*/
|
||||
@Example(taskLocation)
|
||||
@Post('{id}/actions/start')
|
||||
@@ -170,14 +173,17 @@ export class VmController extends XapiXoController<XoVm> {
|
||||
@Response(noContentResp.status, noContentResp.description)
|
||||
@Response(notFoundResp.status, notFoundResp.description)
|
||||
@Response(internalServerErrorResp.status, internalServerErrorResp.description)
|
||||
async startVm(@Path() id: string, @Query() sync?: boolean) {
|
||||
async startVm(@Path() id: string, @Body() body?: { hostId?: string }, @Query() sync?: boolean) {
|
||||
const vmId = id as XoVm['id']
|
||||
const action = () => this.getXapiObject(vmId).$callAsync('start', false, false)
|
||||
const action = async () => {
|
||||
await this.getXapi(vmId).startVm(vmId, { startOnly: true, hostId: body?.hostId as XoHost['id'] })
|
||||
}
|
||||
|
||||
return this.createAction(action, {
|
||||
sync,
|
||||
statusCode: noContentResp.status,
|
||||
taskProperties: {
|
||||
args: body,
|
||||
name: 'start VM',
|
||||
objectId: vmId,
|
||||
},
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
- [XO5/Tasks] hide pending/successful xo tasks (PR [#8676](https://github.com/vatesfr/xen-orchestra/pull/8676))
|
||||
- [REST API] Expose `POST /rest/v0/vms/<vm-id>/actions/pause` (PR [#8744](https://github.com/vatesfr/xen-orchestra/pull/8744))
|
||||
- [REST API] Expose `POST /rest/v0/vms/<vm-id>/actions/suspend` (PR [#8744](https://github.com/vatesfr/xen-orchestra/pull/8744))
|
||||
- [REST API] Add `hostId` in body of `POST /rest/v0/vms/<vm-id>/actions/start` to start a VM on a specific host (PR [#8744](https://github.com/vatesfr/xen-orchestra/pull/8744))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
||||
@@ -959,15 +959,27 @@ export default class Xapi extends XapiBase {
|
||||
}
|
||||
}
|
||||
|
||||
async startVm(vmId, options) {
|
||||
/**
|
||||
*
|
||||
* @param {string} vmId
|
||||
* @param {object} options
|
||||
* @param {boolean} [options.startOnly] - If true, don't try to unpause/resume the VM if VM_BAD_POWER_STATE is thrown
|
||||
*
|
||||
*/
|
||||
async startVm(vmId, { startOnly = false, ...options } = {}) {
|
||||
try {
|
||||
await this._startVm(this.getObject(vmId), options)
|
||||
} catch (e) {
|
||||
if (e.code === 'OPERATION_BLOCKED') {
|
||||
throw forbiddenOperation('Start', e.params[1])
|
||||
}
|
||||
if (e.code === 'VM_BAD_POWER_STATE') {
|
||||
return e.params[2] === 'paused' ? this.unpauseVm(vmId) : this.resumeVm(vmId)
|
||||
if (e.code === 'VM_BAD_POWER_STATE' && !startOnly) {
|
||||
const status = e.params[2]
|
||||
if (status === 'running') {
|
||||
throw e
|
||||
}
|
||||
|
||||
return status === 'paused' ? this.unpauseVm(vmId) : this.resumeVm(vmId)
|
||||
}
|
||||
throw e
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user