Compare commits

...

2 Commits

Author SHA1 Message Date
b-Nollet
de4efdaf7a feat(xo-server): implement VUSB API 2024-02-21 17:19:41 +01:00
Mathieu
039d5687c0 fix(xo-server/host): fix false positives when restarting host after updates (#7366)
The previous implementation only considered version upgrades and did not take into account the installation of missing patches.

See zammad#21487
Introduced by 85ec261
2024-02-21 15:05:05 +01:00
6 changed files with 121 additions and 7 deletions

View File

@@ -7,3 +7,4 @@ export { default as VDI } from './vdi.mjs'
export { default as VIF } from './vif.mjs'
export { default as VM } from './vm.mjs'
export { default as VTPM } from './vtpm.mjs'
export { default as VUSB } from './vusb.mjs'

View File

@@ -0,0 +1,16 @@
import ignoreErrors from 'promise-toolbox/ignoreErrors'
export default class Vusb {
async create(VM, USB_group) {
return this.call('VUSB.create', VM, USB_group)
}
async unplug(ref) {
await this.call('VUSB.unplug', ref)
}
async destroy(ref) {
await ignoreErrors.call(this.VUSB_unplug(ref))
await this.call('VUSB.destroy', ref)
}
}

View File

@@ -22,6 +22,7 @@
- [Plugins/audit] Don't log `tag.getAllConfigured` calls
- [Remotes] Correctly clear error when the remote is tested with success
- [Import/VMWare] Fix importing last snapshot (PR [#7370](https://github.com/vatesfr/xen-orchestra/pull/7370))
- [Host/Reboot] Fix false positive warning when restarting an host after updates (PR [#7366](https://github.com/vatesfr/xen-orchestra/pull/7366))
### Packages to release

View File

@@ -1,3 +1,4 @@
import semver from 'semver'
import { createLogger } from '@xen-orchestra/log'
import assert from 'assert'
import { format } from 'json-rpc-peer'
@@ -136,13 +137,38 @@ export async function restart({
const pool = this.getObject(host.$poolId, 'pool')
const master = this.getObject(pool.master, 'host')
const hostRebootRequired = host.rebootRequired
if (hostRebootRequired && host.id !== master.id && host.version === master.version) {
throw incorrectState({
actual: hostRebootRequired,
expected: false,
object: master.id,
property: 'rebootRequired',
})
// we are currently in an host upgrade process
if (hostRebootRequired && host.id !== master.id) {
// this error is not ideal but it means that the pool master must be fully upgraded/rebooted before the current host can be rebooted.
//
// there is a single error for the 3 cases because the client must handle them the same way
const throwError = () =>
incorrectState({
actual: hostRebootRequired,
expected: false,
object: master.id,
property: 'rebootRequired',
})
if (semver.lt(master.version, host.version)) {
log.error(`master version (${master.version}) is older than the host version (${host.version})`, {
masterId: master.id,
hostId: host.id,
})
throwError()
}
if (semver.eq(master.version, host.version)) {
if ((await this.getXapi(host).listMissingPatches(master._xapiId)).length > 0) {
log.error('master has missing patches', { masterId: master.id })
throwError()
}
if (master.rebootRequired) {
log.error('master needs to reboot')
throwError()
}
}
}
}

View File

@@ -0,0 +1,42 @@
// Creates a VUSB which will be plugged to the VM at its next restart
// Only one VUSB can be attached to a given USB_group, and up to six VUSB can be attached to a VM.
export async function create({ vm, usbGroup }) {
const xapi = this.getXapi(vm)
const vusbRef = await xapi.VUSB_create(vm._xapiRef, usbGroup._xapiRef)
return xapi.getField('VUSB', vusbRef, 'uuid')
}
create.params = {
vmId: { type: 'string' },
usbGroupId: { type: 'string' },
}
create.resolve = {
vm: ['vmId', 'VM', 'administrate'],
usbGroup: ['usbGroupId', 'USB_group', 'administrate'],
}
// Unplug VUSB until next VM restart
export async function unplug({ vusb }) {
await this.getXapi(vusb).VUSB_unplug(vusb._xapiRef)
}
unplug.params = {
id: { type: 'string' },
}
unplug.resolve = {
vusb: ['id', 'VUSB', 'administrate'],
}
export async function destroy({ vusb }) {
await this.getXapi(vusb).VUSB_destroy(vusb._xapiRef)
}
destroy.params = {
id: { type: 'string' },
}
destroy.resolve = {
vusb: ['id', 'VUSB', 'administrate'],
}

View File

@@ -882,6 +882,8 @@ const TRANSFORMS = {
}
},
// -----------------------------------------------------------------
vtpm(obj) {
return {
type: 'VTPM',
@@ -889,6 +891,32 @@ const TRANSFORMS = {
vm: link(obj, 'VM'),
}
},
// -----------------------------------------------------------------
vusb(obj) {
return {
type: 'VUSB',
vm: link(obj, 'VM'),
currentlyAttached: obj.currently_attached,
usbGroup: link(obj, 'USB_group'),
}
},
// -----------------------------------------------------------------
usb_group(obj) {
return {
type: 'USB_group',
PUSB: link(obj, 'PUSBs'),
VUSB: link(obj, 'VUSBs'),
nameDescription: obj.name_description,
nameLabel: obj.name_label,
otherConfig: obj.other_config,
}
},
}
// ===================================================================