Skip to content

Add OCI Windows machine images - #429

Draft
sjmiller609 wants to merge 4 commits into
hypeship/windows-configfrom
hypeship/windows-images
Draft

Add OCI Windows machine images#429
sjmiller609 wants to merge 4 commits into
hypeship/windows-configfrom
hypeship/windows-images

Conversation

@sjmiller609

@sjmiller609 sjmiller609 commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

summary

  • add OCI metadata and materialization for Windows base/persona machine images
  • normalize raw, qcow2, VHD, and VHDX bases into immutable sparse raw disks
  • canonicalize persona backing paths and reflink-clone writable per-instance qcow2 disks
  • create per-instance OVMF/NVRAM and TPM state for Windows QEMU instances
  • reject external disk references and pre-snapshot Windows lifecycle operations
  • preserve existing Linux image and instance behavior

tests

  • go test -run 'TestMaterializeRejectsExternalDiskReferences|TestMaterializeWindowsBaseFormats|TestMaterializeWindowsPersona|TestValidateWindows|TestRejectWindowsSnapshotLifecycle' -v ./lib/images ./lib/instances on deft
  • CI=true HYPEMAN_WINDOWS_TEST_BASE=/ci/windows/base.raw HYPEMAN_WINDOWS_TEST_PERSONA=/ci/windows/persona.qcow2 go test -run TestMachineArtifactsPullFromOCI -v -timeout 20m ./lib/images on deft
  • CI=true HYPEMAN_WINDOWS_TEST_PERSONA=/ci/windows/persona.qcow2 go test -run 'TestWindowsImagesIntegration|TestQEMUStandbyAndRestore' -v -timeout 20m ./lib/instances on deft

notes

  • Windows instances remain Initializing until guest-agent readiness lands in the next phase.
  • Image tag deletion now aborts if digest tag counting fails rather than deleting a tag with uncertain digest ownership.
  • The manually prepared Windows fixtures are private and digest-pinned; no Windows media, generated disks, credentials, or licensing material is committed.

@sjmiller609
sjmiller609 force-pushed the hypeship/windows-images branch 2 times, most recently from 65c40f2 to dd4f0b7 Compare August 20, 2026 15:32
Comment on lines +116 to +119
test -r /ci/windows/base.raw
test -r /ci/windows/persona.qcow2
qemu-img info --output=json /ci/windows/persona.qcow2 \
| jq -e '.format == "qcow2" and .["backing-filename-format"] == "raw"' >/dev/null

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double check for potential concurrency in test running issues

Comment thread docs/windows-images.md
@@ -0,0 +1,21 @@
# Windows machine images

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

user facing style docs can go where this is, and internal "how it works but not the structure of the code" goes in lib/**/README.md, that's more like the context for why things work as they do

Comment thread lib/images/machine.go

const (
MachineImageWindowsBase MachineImageKind = "windows-base"
MachineImageWindowsPersona MachineImageKind = "windows-persona"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure about codifying the "persona" word. is there naming here that might make more sense...? let's discuss

Comment thread lib/images/machine.go
return format
}

func (m *manager) materializeMachineImage(ref *ResolvedRef, root string, machine *MachineImage) (int64, error) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need the right lib/**/README.md to explain the processing and when it happens and why etc

return image
}

func TestMachineArtifactsPullFromOCI(t *testing.T) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double check for non-conflicting between concurrent test runs on the same server

Comment thread lib/instances/create.go
Comment on lines +197 to +200
if windows {
size = 8 * 1024 * 1024 * 1024
} else {
size = 1 * 1024 * 1024 * 1024 // 1GB default

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

explain why defaults are different

Comment thread lib/instances/create.go
Comment on lines +216 to +220
if windows {
vcpus = 4
} else {
vcpus = 2
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

explain why

Comment thread lib/instances/create.go
Cmd: req.Cmd,
SkipKernelHeaders: req.SkipKernelHeaders,
SkipGuestAgent: req.SkipGuestAgent,
SkipGuestAgent: req.SkipGuestAgent || windows,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is temporary right? because guest agent in subsequent pr

@sjmiller609
sjmiller609 force-pushed the hypeship/windows-images branch from dd4f0b7 to a6c00b9 Compare August 20, 2026 16:27
Comment thread lib/instances/windows.go
Comment on lines +28 to +30
if req.HotplugSize != 0 {
return fmt.Errorf("%w: Windows instances do not yet support hotplug memory", ErrInvalidRequest)
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we use Capabilities pattern for some of these situations?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant