diff --git a/pkg/manifest/raw_bootc.go b/pkg/manifest/raw_bootc.go new file mode 100644 index 0000000000..fe49bb6260 --- /dev/null +++ b/pkg/manifest/raw_bootc.go @@ -0,0 +1,105 @@ +package manifest + +import ( + "github.com/osbuild/images/pkg/container" + "github.com/osbuild/images/pkg/disk" + "github.com/osbuild/images/pkg/osbuild" + "github.com/osbuild/images/pkg/ostree" + "github.com/osbuild/images/pkg/platform" + "github.com/osbuild/images/pkg/rpmmd" +) + +// A RawBootcImage represents a raw bootc image file which can be booted in a +// hypervisor. +type RawBootcImage struct { + Base + + filename string + platform platform.Platform + + containers []container.SourceSpec + containerSpecs []container.Spec + + // customizations go here because there is no intermediate + // tree, with `bootc install to-filesystem` we can only work + // with the image itself + PartitionTable *disk.PartitionTable +} + +func (p RawBootcImage) Filename() string { + return p.filename +} + +func (p *RawBootcImage) SetFilename(filename string) { + p.filename = filename +} + +func NewRawBootcImage(buildPipeline Build, containers []container.SourceSpec, platform platform.Platform) *RawBootcImage { + p := &RawBootcImage{ + Base: NewBase("image", buildPipeline), + filename: "disk.img", + platform: platform, + + containers: containers, + } + buildPipeline.addDependent(p) + return p +} + +func (p *RawBootcImage) getContainerSources() []container.SourceSpec { + return p.containers +} + +func (p *RawBootcImage) getContainerSpecs() []container.Spec { + return p.containerSpecs +} + +func (p *RawBootcImage) serializeStart(_ []rpmmd.PackageSpec, containerSpecs []container.Spec, _ []ostree.CommitSpec) { + if len(p.containerSpecs) > 0 { + panic("double call to serializeStart()") + } + p.containerSpecs = containerSpecs +} + +func (p *RawBootcImage) serializeEnd() { + if len(p.containerSpecs) == 0 { + panic("serializeEnd() call when serialization not in progress") + } + p.containerSpecs = nil +} + +func (p *RawBootcImage) serialize() osbuild.Pipeline { + pipeline := p.Base.serialize() + + pt := p.PartitionTable + if pt == nil { + panic("no partition table in live image") + } + + for _, stage := range osbuild.GenImagePrepareStages(pt, p.filename, osbuild.PTSfdisk) { + pipeline.AddStage(stage) + } + + inputs := osbuild.ContainerDeployInputs{ + Images: osbuild.NewContainersInputForSources(p.containerSpecs), + } + devices, mounts, err := osbuild.GenBootupdDevicesMounts(p.filename, p.PartitionTable) + if err != nil { + panic(err) + } + st, err := osbuild.NewBootcInstallToFilesystemStage(inputs, devices, mounts) + if err != nil { + panic(err) + } + pipeline.AddStage(st) + + for _, stage := range osbuild.GenImageFinishStages(pt, p.filename) { + pipeline.AddStage(stage) + } + + // XXX: we need to write a valid /etc/fstab here (or somehow + // pass the right data to bootc above), see + // https://github.com/containers/bootc/issues/357 + + return pipeline +}