diff --git a/@xen-orchestra/backups/_deltaVm.js b/@xen-orchestra/backups/_deltaVm.js index a126918d7..b7ae850d0 100644 --- a/@xen-orchestra/backups/_deltaVm.js +++ b/@xen-orchestra/backups/_deltaVm.js @@ -201,6 +201,7 @@ exports.importDeltaVm = defer(async function importDeltaVm( blocked_operations: { ...vmRecord.blocked_operations, start: 'Importing…', + start_on: 'Importing…', }, ha_always_run: false, is_a_template: false, diff --git a/@xen-orchestra/backups/writers/DeltaReplicationWriter.js b/@xen-orchestra/backups/writers/DeltaReplicationWriter.js index 58aa0b7bd..1c696a9a9 100644 --- a/@xen-orchestra/backups/writers/DeltaReplicationWriter.js +++ b/@xen-orchestra/backups/writers/DeltaReplicationWriter.js @@ -111,9 +111,11 @@ exports.DeltaReplicationWriter = class DeltaReplicationWriter extends MixinRepli targetVm.ha_restart_priority !== '' && Promise.all([targetVm.set_ha_restart_priority(''), targetVm.add_tags('HA disabled')]), targetVm.set_name_label(`${vm.name_label} - ${job.name} - (${formatFilenameDate(timestamp)})`), - targetVm.update_blocked_operations( - 'start', - 'Start operation for this vm is blocked, clone it if you want to use it.' + asyncMap(['start', 'start_on'], op => + targetVm.update_blocked_operations( + op, + 'Start operation for this vm is blocked, clone it if you want to use it.' + ) ), targetVm.update_other_config({ 'xo:backup:sr': srUuid, diff --git a/@xen-orchestra/backups/writers/FullReplicationWriter.js b/@xen-orchestra/backups/writers/FullReplicationWriter.js index aed080f14..39386552c 100644 --- a/@xen-orchestra/backups/writers/FullReplicationWriter.js +++ b/@xen-orchestra/backups/writers/FullReplicationWriter.js @@ -1,5 +1,5 @@ const ignoreErrors = require('promise-toolbox/ignoreErrors.js') -const { asyncMapSettled } = require('@xen-orchestra/async-map') +const { asyncMap, asyncMapSettled } = require('@xen-orchestra/async-map') const { formatDateTime } = require('@xen-orchestra/xapi') const { formatFilenameDate } = require('../_filenameDate.js') @@ -64,9 +64,11 @@ exports.FullReplicationWriter = class FullReplicationWriter extends MixinReplica const targetVm = await xapi.getRecord('VM', targetVmRef) await Promise.all([ - targetVm.update_blocked_operations( - 'start', - 'Start operation for this vm is blocked, clone it if you want to use it.' + asyncMap(['start', 'start_on'], op => + targetVm.update_blocked_operations( + op, + 'Start operation for this vm is blocked, clone it if you want to use it.' + ) ), targetVm.update_other_config({ 'xo:backup:sr': srUuid, diff --git a/@xen-orchestra/cr-seed-cli/index.js b/@xen-orchestra/cr-seed-cli/index.js index d28f1d307..5a672c319 100755 --- a/@xen-orchestra/cr-seed-cli/index.js +++ b/@xen-orchestra/cr-seed-cli/index.js @@ -77,7 +77,11 @@ ${cliName} v${pkg.version} 'xo:backup:sr': tgtSr.uuid, 'xo:copy_of': srcSnapshotUuid, }), - tgtVm.update_blocked_operations('start', 'Start operation for this vm is blocked, clone it if you want to use it.'), + Promise.all( + ['start', 'start_on'].map(op => + tgtVm.update_blocked_operations(op, 'Start operation for this vm is blocked, clone it if you want to use it.') + ) + ), Promise.all( userDevices.map(userDevice => { const srcDisk = srcDisks[userDevice] diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 0e71c063a..4a03ae7a0 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -17,6 +17,7 @@ > Users must be able to say: “I had this issue, happy to know it's fixed” - [VM/disks] Fix `an error has occured` when self service user was on VM disk view (PR [#5841](https://github.com/vatesfr/xen-orchestra/pull/5841)) +- [Backup] Protect replicated VMs from being started on specific hosts (PR [#5852](https://github.com/vatesfr/xen-orchestra/pull/5852)) ### Packages to release @@ -35,5 +36,8 @@ > > In case of conflict, the highest (lowest in previous list) `$version` wins. +- @xen-orchestra/backups patch +- @xen-orchestra/proxy patch - xo-server-netbox minor +- xo-server patch - xo-web minor diff --git a/packages/xo-server/src/xapi/index.mjs b/packages/xo-server/src/xapi/index.mjs index 84e043b77..4912ab4e5 100644 --- a/packages/xo-server/src/xapi/index.mjs +++ b/packages/xo-server/src/xapi/index.mjs @@ -727,6 +727,7 @@ export default class Xapi extends XapiBase { blocked_operations: { ...delta.vm.blocked_operations, start: 'Importing…', + start_on: 'Importing…', }, ha_always_run: false, is_a_template: false, @@ -851,9 +852,11 @@ export default class Xapi extends XapiBase { delta.vm.ha_always_run && vm.set_ha_always_run(true), vm.set_name_label(name_label), // FIXME: move - vm.update_blocked_operations( - 'start', - disableStartAfterImport ? 'Do not start this VM, clone it if you want to use it.' : null + asyncMap(['start', 'start_on'], op => + vm.update_blocked_operations( + op, + disableStartAfterImport ? 'Do not start this VM, clone it if you want to use it.' : null + ) ), ]) @@ -1097,7 +1100,7 @@ export default class Xapi extends XapiBase { $defer.onFailure(() => this.VM_destroy(vm.$ref)) // Disable start and change the VM name label during import. await Promise.all([ - vm.update_blocked_operations('start', 'OVA import in progress...'), + asyncMapSettled(['start', 'start_on'], op => vm.update_blocked_operations(op, 'OVA import in progress...')), vm.set_name_label(`[Importing...] ${nameLabel}`), ]) @@ -1169,7 +1172,7 @@ export default class Xapi extends XapiBase { }) // Enable start and restore the VM name label after import. - await Promise.all([vm.update_blocked_operations('start', null), vm.set_name_label(nameLabel)]) + await Promise.all([vm.update_blocked_operations({ start: null, start_on: null }), vm.set_name_label(nameLabel)]) return vm } @@ -1303,7 +1306,7 @@ export default class Xapi extends XapiBase { log.debug(`Starting VM ${vm.name_label}`) if (force) { - await vm.update_blocked_operations('start', null) + await vm.update_blocked_operations({ start: null, start_on: null }) } return hostId === undefined