diff --git a/@xen-orchestra/xapi/package.json b/@xen-orchestra/xapi/package.json index 51977a93879..3c7c7e3ff9a 100644 --- a/@xen-orchestra/xapi/package.json +++ b/@xen-orchestra/xapi/package.json @@ -26,6 +26,7 @@ "@vates/async-each": "^1.0.0", "@vates/decorate-with": "^2.1.0", "@vates/nbd-client": "^3.1.0", + "@vates/read-chunk": "^1.2.0", "@vates/task": "^0.4.0", "@xen-orchestra/async-map": "^0.1.2", "@xen-orchestra/log": "^0.6.0", diff --git a/@xen-orchestra/xapi/vdi.mjs b/@xen-orchestra/xapi/vdi.mjs index 04692a47c28..5ea6a7ff1ee 100644 --- a/@xen-orchestra/xapi/vdi.mjs +++ b/@xen-orchestra/xapi/vdi.mjs @@ -5,6 +5,7 @@ import { createLogger } from '@xen-orchestra/log' import { createVhdStreamWithLength } from 'vhd-lib' import { decorateClass } from '@vates/decorate-with' import { defer } from 'golike-defer' +import { readChunk } from '@vates/read-chunk' import { strict as assert } from 'node:assert' import MultiNbdClient from '@vates/nbd-client/multi.mjs' @@ -14,6 +15,34 @@ import { finished } from 'node:stream' const { warn, info } = createLogger('xo:xapi:vdi') +// 2024-09-26 - Work-around a XAPI bug: sometimes the response status is +// `200 OK` but the body contains a full HTTP response +// +// Example: +// +// ```http +// HTTP/1.1 500 Internal Error +// content-length: 357 +// content-type:text/html +// connection:close +// cache-control:no-cache, no-store +// +//

HTTP 500 internal server error

An unexpected error occurred; please wait a while and try again. If the problem persists, please contact your support representative.

Additional information

SR_BACKEND_FAILURE_46: [ ; The VDI is not available [opterr=VDI d63513c8-b662-41cd-a355-a63efb5f073f not detached cleanly]; ] +// ``` +// +// Related GitHub issue: https://github.com/xapi-project/xen-api/issues/4603 +// +// This function detects this and throw an error +async function checkVdiExport(stream) { + const chunk = await readChunk(stream, 5) + stream.unshift(chunk) + if (String(chunk) === 'HTTP/') { + const error = new Error('invalid HTTP header in response body') + Object.defineProperty(error, 'response', { body: await readChunk(stream, 1024) }) + throw error + } +} + const noop = Function.prototype class Vdi { async clone(vdiRef) { @@ -157,6 +186,9 @@ class Vdi { query, task: await this.task_create(`Exporting content of VDI ${vdiName}`), }) + + await checkVdiExport(body) + return body } @@ -215,6 +247,8 @@ class Vdi { }) ).body + await checkVdiExport(stream) + $defer.onFailure(() => { exportStream.on('error', noop).destroy() }) diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 8f0c50b2639..ae93cb47eb6 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -31,4 +31,7 @@ +- @xen-orchestra/xapi patch +- xen-api patch + diff --git a/packages/xen-api/index.mjs b/packages/xen-api/index.mjs index f789d397476..7527b91cd47 100644 --- a/packages/xen-api/index.mjs +++ b/packages/xen-api/index.mjs @@ -26,7 +26,6 @@ import makeCallSetting from './_makeCallSetting.mjs' import parseUrl from './_parseUrl.mjs' import Ref from './_Ref.mjs' import transports from './transports/index.mjs' -import { readChunk } from '@vates/read-chunk' const { debug } = createLogger('xen-api') @@ -478,33 +477,6 @@ export class Xapi extends EventEmitter { ) ) - // 2024-09-26 - Work-around a XAPI bug: sometimes the response status is - // `200 OK` but the body contains a full HTTP response - // - // Example: - // - // ```http - // HTTP/1.1 500 Internal Error - // content-length: 357 - // content-type:text/html - // connection:close - // cache-control:no-cache, no-store - // - //

HTTP 500 internal server error

An unexpected error occurred; please wait a while and try again. If the problem persists, please contact your support representative.

Additional information

SR_BACKEND_FAILURE_46: [ ; The VDI is not available [opterr=VDI d63513c8-b662-41cd-a355-a63efb5f073f not detached cleanly]; ] - // ``` - // - // Related GitHub issue: https://github.com/xapi-project/xen-api/issues/4603 - // - // This code detects this and throw an error - const { body } = response - const chunk = await readChunk(body, 5) - body.unshift(chunk) - if (String(chunk) === 'HTTP/') { - const error = new Error('invalid HTTP header in response body') - Object.defineProperty(error, 'response', { value: response }) - throw error - } - if (pTaskResult !== undefined) { response.task = pTaskResult } diff --git a/packages/xen-api/package.json b/packages/xen-api/package.json index 8f1f2ba4e44..1af261d557f 100644 --- a/packages/xen-api/package.json +++ b/packages/xen-api/package.json @@ -36,7 +36,6 @@ "@vates/decorate-with": "^2.1.0", "@vates/json-hash": "^0.2.0", "@vates/obfuscate": "^0.1.0", - "@vates/read-chunk": "^1.2.0", "@vates/xml": "^2.0.0", "@vates/xml-rpc": "^1.0.0", "@xen-orchestra/log": "^0.6.0",