diff --git a/@xen-orchestra/xapi/vdi.mjs b/@xen-orchestra/xapi/vdi.mjs index 912a6155282..da9be6ac70c 100644 --- a/@xen-orchestra/xapi/vdi.mjs +++ b/@xen-orchestra/xapi/vdi.mjs @@ -158,6 +158,39 @@ class Vdi { return Buffer.from(encoded, 'base64') } + /** + * will disable CBT on the VDI, all its ancestor and will purge + * snapshots of type cbt_metadata of this chain + * + * @param {OpaqueRef} vdiRef + */ + async disableCbtOnChain(vdiRef) { + const smConfig = await this.getField('VDI', vdiRef, 'sm_config') + if (smConfig['vhd-parent']) { + const parentRef = await this.call('VDI.get_by_uuid', smConfig['vhd-parent']) + await this.VDI_disableCbtOnChain(parentRef) + } + const snapshotRefs = await this.getField('VDI', vdiRef, 'snapshots') + for (const snapshotRef of snapshotRefs) { + const type = await this.getField('VDI', snapshotRef, 'type') + if (type === 'cbt_metadata') { + try { + await this.VDI_destroy(snapshotRef) + } catch (err) { + warn('couldn t destroy snapshot', { err, vdiRef, snapshotRef }) + } + } + /** + * xapi can't disable CBT on a snapshot OPERATION_NOT_ALLOWED(VDI is a snapshot) + */ + } + try { + await this.callAsync('VDI.disable_cbt', vdiRef) + } catch (err) { + warn('couldn t disable cbt on disk', { err, vdiRef }) + } + } + async disconnectFromControlDomain(vdiRef) { let vbdRefs try { @@ -206,11 +239,12 @@ class Vdi { vdi: ref, } - const [cbt_enabled, size, uuid, vdiName] = await Promise.all([ + const [cbt_enabled, size, snapshotOf, uuid, vdiName] = await Promise.all([ this.getField('VDI', ref, 'cbt_enabled').catch(() => { /* on XS < 7.3 cbt is not supported */ }), this.getField('VDI', ref, 'virtual_size'), + this.getField('VDI', ref, 'snapshot_of'), this.getField('VDI', ref, 'uuid'), this.getField('VDI', ref, 'name_label'), ]) @@ -275,8 +309,10 @@ class Vdi { // a CBT export can only work if we have a NBD client and changed blocks if (changedBlocks === undefined || nbdClient === undefined) { if (baseParentType === 'cbt_metadata') { + await this.VDI_disableCbtOnChain(snapshotOf) const e = new Error(`can't create a stream from a metadata VDI, fall back to a base `) e.code = 'VDI_CANT_DO_DELTA' + // CBT is not usable: reset it throw e } diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index d0411688fb6..6f1f1cada21 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -11,7 +11,7 @@ - **XO6**: - [Pool/Network]: Display networks and host internal networks information in side panel (PR [#8286](https://github.com/vatesfr/xen-orchestra/pull/8286)) - +- [Changed Block Tracking] Disabling CBT now cleanup the full disk and snapshot chains (PR [#8313](https://github.com/vatesfr/xen-orchestra/pull/8313)) > Users must be able to say: “Nice enhancement, I'm eager to test it” ### Bug fixes diff --git a/packages/xo-server/src/api/vdi.mjs b/packages/xo-server/src/api/vdi.mjs index 30666c306ba..af84546336b 100644 --- a/packages/xo-server/src/api/vdi.mjs +++ b/packages/xo-server/src/api/vdi.mjs @@ -67,8 +67,11 @@ export const set = defer(async function ($defer, params) { await xapi.resizeVdi(ref, size) } if ('cbt' in params) { - const method = params.cbt ? 'VDI.enable_cbt' : 'VDI.disable_cbt' - await xapi.callAsync(method, ref) + if (params.cbt) { + await xapi.callAsync('VDI.enable_cbt', ref) + } else { + await xapi.VDI_disableCbtOnChain(ref) + } } // Other fields.