feat(xo-server): add MBR to cloud-init drive (#6889)

This commit is contained in:
Florent BEAUCHAMP 2023-06-28 10:42:01 +02:00 committed by GitHub
parent 603696dad1
commit 161c20b534
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 11 deletions

View File

@ -12,6 +12,7 @@
- [Plugin/auth-iodc] OpenID Connect scopes are now configurable and `profile` is included by default
- [Dashboard/Health] Button to copy UUID of an orphan VDI to the clipboard (PR [#6893](https://github.com/vatesfr/xen-orchestra/pull/6893))
- [Kubernetes recipe] Add the possibility to choose the version for the cluster [#6842](https://github.com/vatesfr/xen-orchestra/issues/6842) (PR [#6880](https://github.com/vatesfr/xen-orchestra/pull/6880))
- [New VM] cloud-init drives are now bootable in a Windows VM (PR [#6889](https://github.com/vatesfr/xen-orchestra/pull/6889))
### Bug fixes
@ -49,7 +50,7 @@
- @xen-orchestra/vmware-explorer patch
- xen-api patch
- xo-cli minor
- xo-server patch
- xo-server minor
- xo-server-auth-oidc minor
- xo-server-perf-alert patch
- xo-web minor

View File

@ -23,6 +23,29 @@ const SECTOR_SIZE = 512
const TEN_MIB = 10 * 1024 * 1024
// https://en.wikipedia.org/wiki/Master_boot_record
// we'll add a classical generic mbr
// with one FAT16 partition addressed by LBA
export function addMbr(buf) {
const mbr = Buffer.alloc(SECTOR_SIZE, 0)
// 0 - 446 is bootstrap code , keep it empty
// entry
mbr[446] = 0x80 // entry is bootable
mbr[450] = 0x0e // FAT16 LBA
mbr.writeInt32LE(1, 454) // LBA address of first sector
assert.strictEqual(buf.length % SECTOR_SIZE, 0, 'buffer length must be aligned to sector size')
mbr.writeInt32LE(buf.length / SECTOR_SIZE + 1, 458) // LBA address of last sector
// 3 more 16 bytes entry we don't need
// boot signature
mbr[510] = 0x55
mbr[511] = 0xaa
return Buffer.concat([mbr, buf])
}
// Creates a 10MB buffer and initializes it as a FAT 16 volume.
export function init({ label = 'NO LABEL ' } = {}) {
assert.strictEqual(typeof label, 'string')

View File

@ -28,7 +28,7 @@ import { extractOpaqueRef, parseDateTime, Xapi as XapiBase } from '@xen-orchestr
import { Ref } from 'xen-api'
import { synchronized } from 'decorator-synchronized'
import fatfsBuffer, { init as fatfsBufferInit } from '../fatfs-buffer.mjs'
import fatfsBuffer, { addMbr, init as fatfsBufferInit } from '../fatfs-buffer.mjs'
import { camelToSnakeCase, forEach, map, pDelay, promisifyAll } from '../utils.mjs'
import { debounceWithKey } from '../_pDebounceWithKey.mjs'
@ -1301,15 +1301,7 @@ export default class Xapi extends XapiBase {
const sr = this.getObject(srId)
// First, create a small VDI (10MB) which will become the ConfigDrive
const buffer = fatfsBufferInit({ label: 'cidata ' })
const vdi = await this._getOrWaitObject(
await this.VDI_create({
name_label: 'XO CloudConfigDrive',
SR: sr.$ref,
virtual_size: buffer.length,
})
)
$defer.onFailure(() => vdi.$destroy())
let buffer = fatfsBufferInit({ label: 'cidata ' })
// Then, generate a FAT fs
const { mkdir, writeFile } = promisifyAll(fatfs.createFileSystem(fatfsBuffer(buffer)))
@ -1334,6 +1326,15 @@ export default class Xapi extends XapiBase {
)
),
])
buffer = addMbr(buffer)
const vdi = await this._getOrWaitObject(
await this.VDI_create({
name_label: 'XO CloudConfigDrive',
SR: sr.$ref,
virtual_size: buffer.length,
})
)
$defer.onFailure(() => vdi.$destroy())
// ignore errors, I (JFT) don't understand why they are emitted
// because it works