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",