Skip to content

HCP Packer Registry Support + CD-ROM Bus Portability - #49

Merged
anurag5sh merged 7 commits into
hashicorp:mainfrom
dejo-oyelese:hcp-ready
Aug 3, 2026
Merged

HCP Packer Registry Support + CD-ROM Bus Portability#49
anurag5sh merged 7 commits into
hashicorp:mainfrom
dejo-oyelese:hcp-ready

Conversation

@dejo-oyelese

@dejo-oyelese dejo-oyelese commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR adds native HCP Packer registry integration to the kubevirt-iso
builder and fixes a pre-existing bug where Linux CD-ROM disk devices had no
bus type set, causing builds to fail on arm64 clusters.


Changes

1. HCP Packer registry support (10f464d)

The kubevirt-iso builder now registers build artifacts with the HCP Packer
registry after each successful build. When a hcp_packer_registry block is
present in the template, Packer core will track the resulting DataSource
as a versioned artifact in the registry.

artifact.go

  • Added Namespace and StateData fields to Artifact
  • Id() now returns namespace/name (e.g. images/fedora-42) so HCP can
    track artifacts unambiguously across clusters
  • State() handles the registryimage.ArtifactStateURI key
    ("par.artifact.metadata") and returns a populated *registryimage.Image
    with provider=kubevirt, region=<namespace>, and labels including
    namespace and any values from generated_data

builder.go

  • Prepare() returns []string{"BootableVolumeName"} so provisioners can
    reference the artifact name at runtime via build.BootableVolumeName
  • Run() wires packerbuilderdata.GeneratedData so generated values are
    accessible in provisioner interpolation
  • Added post-runner state.GetOk("error") and state.GetOk(StateCancelled)
    checks before artifact construction — previously a halted build would return
    a misleading "bootable volume name not found in state" error instead of
    the real underlying error
  • StepCreateBootableVolume is gated on !SkipCreateImage so the step is
    skipped when the flag is set

config.go

  • Added skip_create_image bool — when true, skips the final
    StepCreateBootableVolume step and returns no artifact, which also
    suppresses HCP registration. Useful for iterative debugging without
    producing a final image.

step_create_bootablevolume.go

  • Added GeneratedData *packerbuilderdata.GeneratedData field
  • Calls GeneratedData.Put("BootableVolumeName", ds.Name) so the value is
    available to provisioners
  • Stores bootable_volume_namespace in the state bag alongside the existing
    bootable_volume_name so Builder.Run() can construct a fully-qualified
    artifact ID

artifact_test.go (new)

  • Table-driven unit tests covering BuilderId, Id, String, Files,
    Destroy, State(ArtifactStateURI) with and without generated_data,
    and StateData fallthrough including nil map safety

step_create_bootablevolume_test.go

  • Wired GeneratedData into BeforeEach to prevent nil pointer panic

2. CD-ROM bus type — intermediate fix (cde2306)

During testing, KubeVirt's admission webhook rejected the VM because Linux
CD-ROM devices had no Bus set. KubeVirt was defaulting to virtio, which
is an invalid bus type for CD-ROM devices. This commit hardcoded sata as
a stepping stone; it was immediately superseded by commit ef8f80d.


3. Configurable CD-ROM bus type (ef8f80d)

The intermediate sata fix broke arm64 clusters (including OpenShift on
ARM), where the admission webhook only accepts virtio or scsi for disk
buses. Rather than hardcode either value, this commit exposes disk_bus as
a user-configurable field.

config.go

  • Added disk_bus string field with mapstructure:"disk_bus"
  • Prepare() defaults to "scsi" when unset — valid on both x86 and arm64

resources.go

  • getLinuxVirtualMachineDisks() now accepts diskBus string and applies
    v1.DiskBus(diskBus) to both the cdrom and oemdrv CD-ROM devices
  • Windows VM disks are unaffected (already explicitly set to sata)

step_create_virtualmachine.go

  • Reads s.Config.DiskBus and passes it through to virtualMachine()

Example usage in template:

source "kubevirt-iso" "example" {
  disk_bus = "scsi"   # arm64 clusters
  # disk_bus = "sata" # x86 clusters if needed
}

What was tested

All existing unit tests pass. New unit tests for the HCP artifact wiring pass.

ok  github.com/hashicorp/packer-plugin-kubevirt/builder/kubevirt/iso  5.3s

End-to-end testing was carried out on a local minikube cluster (qemu2 driver,
Apple Silicon). The following was verified locally:

  • packer validate accepts hcp_packer_registry {} and skip_create_image
  • HCP credentials authenticate correctly (Tracking build on HCP Packer with fingerprint ... appears in build output)
  • StepValidateIsoDataVolume reaches the cluster and validates the ISO
    DataVolume successfully
  • StepCopyMediaFiles creates the ConfigMap successfully
  • StepCreateVirtualMachine creates the VM with disk_bus = "scsi" without
    rejection from the admission webhook

End-to-end VM boot and full HCP artifact registration could not be completed
locally due to a minikube + Docker networking constraint (nf_nat table
operations are not permitted inside a Docker container, which prevents
KubeVirt's masquerade networking from initialising the VM's network stack).
This is an environment limitation, not a plugin issue.

Remaining tests required before merge

The following must be run on a Linux-based KubeVirt cluster (bare metal,
OpenShift Local/CRC, or a cloud-hosted cluster):

1. Full build completes and registers with HCP

packer build hcp-test.pkr.hcl

Expected:

  • Build runs to completion
  • Terminal output contains:
    kubevirt-iso.test: Bootable volume: images/hcp-test-image
    
  • HCP portal → Packer → Buckets → kubevirt-test → latest version shows:
Field Expected
Artifact ID images/hcp-test-image
Provider kubevirt
Region images
Label: namespace images
Label: BootableVolumeName hcp-test-image

2. build.BootableVolumeName is accessible in provisioners

Add to the build block:

provisioner "shell" {
  inline = ["echo BootableVolumeName=${build.BootableVolumeName}"]
}

Expected: Provisioner output contains BootableVolumeName=hcp-test-image
and not the ERR_* placeholder.

3. Second build creates a new version

Change name to hcp-test-image-2 and re-run.

Expected: HCP bucket shows 2 distinct versions.

4. Failed build is not registered

Set iso_volume_name to a DataVolume that does not exist and run.

Expected: Build exits non-zero, no new version in HCP bucket.

5. skip_create_image = true suppresses HCP registration

Add skip_create_image = true to the source block and run.

Expected: No Creating a new bootable volume log line, no artifact
output, no new version in HCP bucket.

Implements native HCP Packer integration so the kubevirt-iso builder
registers its artifacts with the HCP Packer registry after each
successful build.

Changes:
- artifact.go: add Namespace and StateData fields; implement
  State(registryimage.ArtifactStateURI) returning a *registryimage.Image
  with provider=kubevirt, region=namespace, and generated_data labels;
  Id() now returns namespace/name for an unambiguous artifact identifier

- builder.go: declare BootableVolumeName as a generated variable in
  Prepare() so provisioners can reference it via build.BootableVolumeName;
  wire packerbuilderdata.GeneratedData in Run(); add post-runner
  error/cancel state checks before artifact construction; gate
  StepCreateBootableVolume on !SkipCreateImage; return nil artifact
  when SkipCreateImage is set

- config.go: add skip_create_image bool field to allow skipping final
  image creation and HCP registration during iterative debugging

- config.hcl2spec.go: regenerated via go generate

- step_create_bootablevolume.go: add GeneratedData field; call
  GeneratedData.Put("BootableVolumeName", ...) and store
  bootable_volume_namespace in state bag alongside the existing
  bootable_volume_name entry

- step_create_bootablevolume_test.go: wire GeneratedData into BeforeEach
  to prevent nil pointer panic with new field

- artifact_test.go: new table-driven tests covering BuilderId, Id,
  String, Files, Destroy, State(ArtifactStateURI) with and without
  generated_data, and StateData fallthrough including nil map safety
KubeVirt rejects CD-ROM devices with no bus set because it defaults to
virtio, which is invalid for CD-ROMs. Explicitly set bus to sata on
both the cdrom and oemdrv disk devices for linux VMs, matching the
existing behaviour of the windows VM disks.
Exposes the CD-ROM disk bus type as a user-configurable field so
builds work across architectures without code changes.

arm64 clusters (e.g. minikube on Apple Silicon) only support virtio
and scsi for disk buses. sata is rejected by the admission webhook.
x86 clusters accept sata. Previously the bus was hardcoded, breaking
arm64 users.

- Default is 'scsi', which is valid on both x86 and arm64
- User can override to 'sata' or 'virtio' via disk_bus in the template
- Applied to both cdrom and oemdrv CD-ROM devices for linux VMs
- Windows VM disks are unaffected (already explicitly set to sata)
@dejo-oyelese
dejo-oyelese requested a review from a team as a code owner July 28, 2026 18:59
@hashicorp-cla-app

hashicorp-cla-app Bot commented Jul 28, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@dejo-oyelese

Copy link
Copy Markdown
Collaborator Author

Hi @anurag5sh - sorry I duplicated PRs but I closed the other one. I fixed the tests and this should be good to go now.

@dejo-oyelese dejo-oyelese changed the title Hcp ready HCP Packer Registry Support + CD-ROM Bus Portability Jul 28, 2026
@anurag5sh
anurag5sh merged commit 851dd38 into hashicorp:main Aug 3, 2026
12 checks passed
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.

2 participants