Skip to content

Commit 5def1d7

Browse files
committed
Allow different types of boot configurations for WCOW UVM
Currently WCOW UVM only support booting with VmbFS and legacy layers. However, we are adding support for booting the UVM with BlockCIM layers. This commit updates the WCOWBootFiles struct to support different boot configurations. Signed-off-by: Amit Barve <[email protected]>
1 parent b4e0744 commit 5def1d7

File tree

4 files changed

+66
-7
lines changed

4 files changed

+66
-7
lines changed

internal/layers/wcow_parse.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,11 @@ func GetWCOWUVMBootFilesFromLayers(ctx context.Context, rootfs []*types.Mount, l
263263
}
264264
}
265265
return &uvm.WCOWBootFiles{
266-
OSFilesPath: filepath.Join(uvmFolder, `UtilityVM\Files`),
267-
OSRelativeBootDirPath: `\EFI\Microsoft\Boot`,
268-
ScratchVHDPath: scratchVHDPath,
266+
BootType: uvm.VmbFSBoot,
267+
VmbFSFiles: &uvm.VmbFSBootFiles{
268+
OSFilesPath: filepath.Join(uvmFolder, `UtilityVM\Files`),
269+
OSRelativeBootDirPath: `\EFI\Microsoft\Boot`,
270+
ScratchVHDPath: scratchVHDPath,
271+
},
269272
}, nil
270273
}

internal/uvm/create.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,25 @@ type Options struct {
124124
NumaMemoryBlocksCounts []uint64
125125
}
126126

127+
func verifyWCOWBootFiles(bootFiles *WCOWBootFiles) error {
128+
if bootFiles.BootType == VmbFSBoot {
129+
if bootFiles.VmbFSFiles == nil {
130+
return fmt.Errorf("VmbFS boot files is empty")
131+
} else if bootFiles.BlockCIMFiles != nil {
132+
return fmt.Errorf("confidential boot files should be empty")
133+
}
134+
} else if bootFiles.BootType == BlockCIMBoot {
135+
if bootFiles.BlockCIMFiles == nil {
136+
return fmt.Errorf("Confidential boot files is empty")
137+
} else if bootFiles.VmbFSFiles != nil {
138+
return fmt.Errorf("VmbFS boot files should be empty")
139+
}
140+
} else {
141+
return fmt.Errorf("invalid boot type specified")
142+
}
143+
return nil
144+
}
145+
127146
// Verifies that the final UVM options are correct and supported.
128147
func verifyOptions(_ context.Context, options interface{}) error {
129148
switch opts := options.(type) {
@@ -156,6 +175,9 @@ func verifyOptions(_ context.Context, options interface{}) error {
156175
if opts.SCSIControllerCount != 1 {
157176
return errors.New("exactly 1 SCSI controller is required for WCOW")
158177
}
178+
if err := verifyWCOWBootFiles(opts.BootFiles); err != nil {
179+
return err
180+
}
159181
}
160182
return nil
161183
}

internal/uvm/create_wcow.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,17 @@ func prepareConfigDoc(ctx context.Context, uvm *UtilityVM, opts *OptionsWCOW) (*
8686
memorySizeInMB := uvm.normalizeMemorySize(ctx, opts.MemorySizeInMB)
8787

8888
// UVM rootfs share is readonly.
89+
if opts.BootFiles.BootType != VmbFSBoot {
90+
return nil, fmt.Errorf("expected VmbFS boot type, found: %d", opts.BootFiles.BootType)
91+
}
8992
vsmbOpts := uvm.DefaultVSMBOptions(true)
9093
vsmbOpts.TakeBackupPrivilege = true
9194
virtualSMB := &hcsschema.VirtualSmb{
9295
DirectFileMappingInMB: 1024, // Sensible default, but could be a tuning parameter somewhere
9396
Shares: []hcsschema.VirtualSmbShare{
9497
{
9598
Name: "os",
96-
Path: opts.BootFiles.OSFilesPath,
99+
Path: opts.BootFiles.VmbFSFiles.OSFilesPath,
97100
Options: vsmbOpts,
98101
},
99102
},
@@ -192,7 +195,7 @@ func prepareConfigDoc(ctx context.Context, uvm *UtilityVM, opts *OptionsWCOW) (*
192195
Chipset: &hcsschema.Chipset{
193196
Uefi: &hcsschema.Uefi{
194197
BootThis: &hcsschema.UefiBootEntry{
195-
DevicePath: filepath.Join(opts.BootFiles.OSRelativeBootDirPath, "bootmgfw.efi"),
198+
DevicePath: filepath.Join(opts.BootFiles.VmbFSFiles.OSRelativeBootDirPath, "bootmgfw.efi"),
196199
DeviceType: "VmbFs",
197200
},
198201
},
@@ -313,7 +316,7 @@ func CreateWCOW(ctx context.Context, opts *OptionsWCOW) (_ *UtilityVM, err error
313316
return nil, fmt.Errorf("error in preparing config doc: %w", err)
314317
}
315318

316-
if err := wclayer.GrantVmAccess(ctx, uvm.id, opts.BootFiles.ScratchVHDPath); err != nil {
319+
if err := wclayer.GrantVmAccess(ctx, uvm.id, opts.BootFiles.VmbFSFiles.ScratchVHDPath); err != nil {
317320
return nil, errors.Wrap(err, "failed to grant vm access to scratch")
318321
}
319322

@@ -326,7 +329,7 @@ func CreateWCOW(ctx context.Context, opts *OptionsWCOW) (_ *UtilityVM, err error
326329

327330
doc.VirtualMachine.Devices.Scsi[guestrequest.ScsiControllerGuids[0]].Attachments["0"] = hcsschema.Attachment{
328331

329-
Path: opts.BootFiles.ScratchVHDPath,
332+
Path: opts.BootFiles.VmbFSFiles.ScratchVHDPath,
330333
Type_: "VirtualDisk",
331334
}
332335

internal/uvm/types.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,28 @@ type OutputHandler func(io.Reader)
153153

154154
type OutputHandlerCreator func(*Options) OutputHandler
155155

156+
type WCOWBootFilesType uint8
157+
158+
const (
159+
VmbFSBoot WCOWBootFilesType = iota
160+
BlockCIMBoot
161+
)
162+
163+
// WCOWBootFiles provides the files paths (and other data) required to configure boot of
164+
// an UVM. This struct (more like a union) maintains a type variable to specify what kind
165+
// of boot we are doing and then the struct applicable to that boot type will have the
166+
// necessary data. All other fields should be null. (Maybe we can make this into an
167+
// interface with a method that configures boot given the UVM HCS doc, but configuring
168+
// boot requires access to the uvm struct itself to update the used SCSI mounts etc. and
169+
// then the interface gets ugly...)
156170
type WCOWBootFiles struct {
171+
BootType WCOWBootFilesType
172+
VmbFSFiles *VmbFSBootFiles
173+
BlockCIMFiles *BlockCIMBootFiles
174+
}
175+
176+
// files required to boot an UVM with layer files stored on NTFS in legacy (WCIFS) format.
177+
type VmbFSBootFiles struct {
157178
// Path to the directory that contains the OS files.
158179
OSFilesPath string
159180
// Path of the boot directory relative to the `OSFilesPath`. This boot directory MUST
@@ -162,3 +183,13 @@ type WCOWBootFiles struct {
162183
// Path for the scratch VHD of thef UVM
163184
ScratchVHDPath string
164185
}
186+
187+
// files required to boot an UVM with the layer files stored in a block CIM.
188+
type BlockCIMBootFiles struct {
189+
// Path to the VHD that has a block CIM (which contains the OS files) on it.
190+
BootCIMVHDPath string
191+
// VHD that contains the EFI partition
192+
EFIVHDPath string
193+
// A non formatted scratch VHD
194+
ScratchVHDPath string
195+
}

0 commit comments

Comments
 (0)