feat(xo-server): add MBR to cloud-init drive (#6889)
This commit is contained in:
parent
603696dad1
commit
161c20b534
@ -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
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user