fix(qa-test): don't try to export disk > 2TB in vhd (#10607)

* fix(qa-test): don't try to export disk > 2TB in vhd
This commit is contained in:
Florent BEAUCHAMP
2026-10-20 14:17:45 +02:00
committed by GitHub
parent b630456835
commit 2233bad7a7
3 changed files with 35 additions and 24 deletions

View File

@@ -20,6 +20,7 @@ import {
validateVhdIntegrity,
validateXvaIntegrity,
formatBytes,
findVhdExportableVdi,
} from '../utils/exportUtils.js'
import { assertBackupSuccess, assertRepositoryEmpty } from '../utils/backupUtils.js'
import { setup, teardown } from './setup.js'
@@ -261,9 +262,7 @@ describe('Backup + Replication Combined Tests', () => {
// Step 2: Export VDI as VHD
const vdis = await dispatchClient.vdi.getVdisForVm(vm.uuid)
assert.ok(vdis.length > 0, 'VM should have at least one VDI')
const vdi = vdis[0]
const vdi = findVhdExportableVdi(vdis)
const fileName = generateExportFileName(`${vm.name_label}-combined-vhd`, 'vhd')
const outputPath = path.join(exportPath, fileName)
@@ -353,9 +352,7 @@ describe('Backup + Replication Combined Tests', () => {
// Step 2: Export VDI as VHD
const vdis = await dispatchClient.vdi.getVdisForVm(vm.uuid)
assert.ok(vdis.length > 0, 'VM should have at least one VDI')
const vdi = vdis[0]
const vdi = findVhdExportableVdi(vdis)
const fileName = generateExportFileName(`${vm.name_label}-restore-vhd`, 'vhd')
const outputPath = path.join(exportPath, fileName)

View File

@@ -12,6 +12,7 @@ import {
assertExportSizeReasonable,
assertCompressionEfficiency,
formatBytes,
findVhdExportableVdi,
} from '../utils/exportUtils.js'
import { setup, teardown } from './setup.js'
import { getRequiredEnv } from '../utils/index.js'
@@ -101,9 +102,7 @@ describe('VHD/XVA Export Replication Tests', () => {
it('should export VDI as VHD file', async () => {
// Get VM's VDIs
const vdis = await dispatchClient.vdi.getVdisForVm(vm.uuid)
assert(vdis.length > 0, 'VM should have at least one VDI')
const vdi = vdis[0]
const vdi = findVhdExportableVdi(vdis)
log.debug('Exporting VDI', { name: vdi.name_label, uuid: vdi.uuid, size: formatBytes(vdi.virtual_size) })
// Generate unique filename
@@ -127,9 +126,7 @@ describe('VHD/XVA Export Replication Tests', () => {
it('should export VDI with NBD protocol', async () => {
// Get VM's VDIs
const vdis = await dispatchClient.vdi.getVdisForVm(vm.uuid)
assert(vdis.length > 0, 'VM should have at least one VDI')
const vdi = vdis[0]
const vdi = findVhdExportableVdi(vdis)
const fileName = generateExportFileName(`${vm.name_label}-nbd`, 'vhd')
const outputPath = path.join(exportPath, fileName)
@@ -150,9 +147,7 @@ describe('VHD/XVA Export Replication Tests', () => {
it('should validate VHD file structure', async () => {
// Get VM's VDIs
const vdis = await dispatchClient.vdi.getVdisForVm(vm.uuid)
assert(vdis.length > 0, 'VM should have at least one VDI')
const vdi = vdis[0]
const vdi = findVhdExportableVdi(vdis)
const fileName = generateExportFileName(`${vm.name_label}-validate`, 'vhd')
const outputPath = path.join(exportPath, fileName)
@@ -170,9 +165,7 @@ describe('VHD/XVA Export Replication Tests', () => {
it('should have reasonable export size', async () => {
// Get VM's VDIs
const vdis = await dispatchClient.vdi.getVdisForVm(vm.uuid)
assert(vdis.length > 0, 'VM should have at least one VDI')
const vdi = vdis[0]
const vdi = findVhdExportableVdi(vdis)
const fileName = generateExportFileName(`${vm.name_label}-size`, 'vhd')
const outputPath = path.join(exportPath, fileName)
@@ -296,9 +289,7 @@ describe('VHD/XVA Export Replication Tests', () => {
it('should restore VHD to new VDI', async () => {
// First, export a VDI
const vdis = await dispatchClient.vdi.getVdisForVm(vm.uuid)
assert(vdis.length > 0, 'VM should have at least one VDI')
const vdi = vdis[0]
const vdi = findVhdExportableVdi(vdis)
const fileName = generateExportFileName(`${vm.name_label}-restore`, 'vhd')
const outputPath = path.join(exportPath, fileName)
@@ -368,9 +359,7 @@ describe('VHD/XVA Export Replication Tests', () => {
it('should compare source VDI size vs exported VHD', async () => {
// Get VM's VDIs
const vdis = await dispatchClient.vdi.getVdisForVm(vm.uuid)
assert(vdis.length > 0, 'VM should have at least one VDI')
const vdi = vdis[0]
const vdi = findVhdExportableVdi(vdis)
const fileName = generateExportFileName(`${vm.name_label}-compare`, 'vhd')
const outputPath = path.join(exportPath, fileName)

View File

@@ -1,4 +1,5 @@
import { createLogger } from '@xen-orchestra/log'
import assert from 'node:assert'
import fs from 'node:fs/promises'
import path from 'node:path'
import { waitUntil, assertNonEmptyString } from './index.js'
@@ -19,6 +20,30 @@ export const VHD_MAGIC = Buffer.from('conectix')
*/
export const VHD_FOOTER_SIZE = 512
/**
* Largest VDI that can be exported as VHD, bigger ones are rejected with a 422.
* Same value as VHD_MAX_SIZE in @xen-orchestra/xapi.
* @constant {number}
*/
export const VHD_MAX_SIZE = 2 * 1024 * 1024 * 1024 * 1024 /* 2TB */ - 8 * 1024 /* metadata */
/**
* Returns the first VDI that can be exported as VHD.
* The VM can also have disks over 2TB (qcow2), which can't be exported as VHD.
*
* @param {Array<{uuid: string, name_label: string, virtual_size: number}>} vdis - VDIs from getVdisForVm
* @returns {{uuid: string, name_label: string, virtual_size: number}} The VDI to export
* @throws {assert.AssertionError} If no VDI is small enough
*/
export function findVhdExportableVdi(vdis) {
const vdi = vdis.find(vdi => vdi.virtual_size <= VHD_MAX_SIZE)
assert.ok(
vdi !== undefined,
`VM should have at least one VDI of at most ${formatBytes(VHD_MAX_SIZE)} to be exported as VHD, got ${vdis.length} VDIs`
)
return vdi
}
/**
* Generates a unique export file name with timestamp.
*