Skip to content

Commit

Permalink
refactor and support edge qcow2
Browse files Browse the repository at this point in the history
Signed-off-by: Antonio Murdaca <runcom@linux.com>
  • Loading branch information
runcom authored and 7flying committed May 4, 2023
1 parent ab120dd commit c413206
Show file tree
Hide file tree
Showing 18 changed files with 330 additions and 128 deletions.
2 changes: 2 additions & 0 deletions internal/cloudapi/v2/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,8 @@ func imageTypeFromApiImageType(it ImageTypes, arch distro.Arch) string {
return "iot-installer"
case ImageTypesIotRawImage:
return "iot-raw-image"
case ImageTypesIotQcow2Image:
return "iot-qcow2-image"
}
return ""
}
Expand Down
2 changes: 2 additions & 0 deletions internal/cloudapi/v2/openapi.v2.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions internal/cloudapi/v2/openapi.v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ components:
- iot-container
- iot-installer
- iot-raw-image
- iot-qcow2-image
- vsphere
Repository:
type: object
Expand Down
1 change: 1 addition & 0 deletions internal/distro/distro_test_common/distro_test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ func TestDistro_KernelOption(t *testing.T, d distro.Distro) {
"edge-installer": true,
"edge-simplified-installer": true,
"iot-raw-image": true,
"iot-qcow2-image": true,
"edge-raw-image": true,

// the tar image type is a minimal image type which is not expected to
Expand Down
30 changes: 30 additions & 0 deletions internal/distro/fedora/distro.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,25 @@ var (
requiredPartitionSizes: map[string]uint64{},
}

iotQcow2ImgType = imageType{
name: "iot-qcow2-image",
nameAliases: []string{"fedora-iot-qcow2-image"},
filename: "image.qcow2",
mimeType: "application/x-qemu-disk",
packageSets: map[string]packageSetFunc{},
defaultImageConfig: &distro.ImageConfig{
Locale: common.ToPtr("en_US.UTF-8"),
},
defaultSize: 10 * common.GibiByte,
rpmOstree: true,
bootable: true,
image: iotQcow2Image,
buildPipelines: []string{"build"},
payloadPipelines: []string{"image-tree", "image", "qcow2"},
exports: []string{"qcow2"},
basePartitionTables: iotBasePartitionTables,
}

qcow2ImgType = imageType{
name: "qcow2",
filename: "disk.qcow2",
Expand Down Expand Up @@ -1041,6 +1060,16 @@ func newDistro(version int) distro.Distro {
},
iotRawImgType,
)
x86_64.addImageTypes(
&platform.X86{
BasePlatform: platform.BasePlatform{
ImageFormat: platform.FORMAT_QCOW2,
},
BIOS: false,
UEFIVendor: "fedora",
},
iotQcow2ImgType,
)
x86_64.addImageTypes(
&platform.X86{
BasePlatform: platform.BasePlatform{
Expand Down Expand Up @@ -1069,6 +1098,7 @@ func newDistro(version int) distro.Distro {
},
},
qcow2ImgType,
iotQcow2ImgType,
ociImgType,
)
aarch64.addImageTypes(
Expand Down
40 changes: 35 additions & 5 deletions internal/distro/fedora/distro_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,22 @@ func TestFilenameFromType(t *testing.T) {
mimeType: "application/x-iso9660-image",
},
},
{
name: "iot-qcow2-image",
args: args{"iot-qcow2-image"},
want: wantResult{
filename: "image.qcow2",
mimeType: "application/x-qemu-disk",
},
},
{ // Alias
name: "fedora-iot-qcow2-image",
args: args{"fedora-iot-qcow2-image"},
want: wantResult{
filename: "image.qcow2",
mimeType: "application/x-qemu-disk",
},
},
{
name: "image-installer",
args: args{"image-installer"},
Expand Down Expand Up @@ -290,6 +306,7 @@ func TestImageType_Name(t *testing.T) {
"iot-installer",
"iot-simplified-installer",
"iot-raw-image",
"iot-qcow2-image",
"oci",
"image-installer",
"minimal-raw",
Expand All @@ -307,6 +324,7 @@ func TestImageType_Name(t *testing.T) {
"iot-installer",
"iot-simplified-installer",
"iot-raw-image",
"iot-qcow2-image",
"image-installer",
"minimal-raw",
},
Expand Down Expand Up @@ -387,6 +405,16 @@ func TestImageTypeAliases(t *testing.T) {
imageTypeName: "iot-simplified-installer",
},
},

{
name: "iot-qcow2-image aliases",
args: args{
imageTypeAliases: []string{"fedora-iot-qcow2-image"},
},
want: wantResult{
imageTypeName: "iot-qcow2-image",
},
},
}
for _, dist := range fedoraFamilyDistros {
t.Run(dist.name, func(t *testing.T) {
Expand Down Expand Up @@ -446,7 +474,7 @@ func TestDistro_ManifestError(t *testing.T) {
}
testPackageSpecSets := distro_test_common.GetTestingImagePackageSpecSets("kernel", imgType)
_, _, err := imgType.Manifest(bp.Customizations, imgOpts, nil, testPackageSpecSets, nil, 0)
if imgTypeName == "iot-commit" || imgTypeName == "iot-container" || imgTypeName == "iot-raw-image" {
if imgTypeName == "iot-commit" || imgTypeName == "iot-container" || imgTypeName == "iot-raw-image" || imgTypeName == "iot-qcow2-image" {
assert.EqualError(t, err, "kernel boot parameter customizations are not supported for ostree types")
} else if imgTypeName == "iot-installer" || imgTypeName == "iot-simplified-installer" {
assert.EqualError(t, err, fmt.Sprintf("boot ISO image type \"%s\" requires specifying a URL from which to retrieve the OSTree commit", imgTypeName))
Expand Down Expand Up @@ -477,6 +505,7 @@ func TestArchitecture_ListImageTypes(t *testing.T) {
"iot-container",
"iot-installer",
"iot-raw-image",
"iot-qcow2-image",
"iot-simplified-installer",
"oci",
"container",
Expand All @@ -494,6 +523,7 @@ func TestArchitecture_ListImageTypes(t *testing.T) {
"iot-container",
"iot-installer",
"iot-raw-image",
"iot-qcow2-image",
"iot-simplified-installer",
"oci",
"container",
Expand Down Expand Up @@ -590,7 +620,7 @@ func TestDistro_CustomFileSystemManifestError(t *testing.T) {
for _, imgTypeName := range arch.ListImageTypes() {
imgType, _ := arch.GetImageType(imgTypeName)
_, _, err := imgType.Manifest(bp.Customizations, distro.ImageOptions{}, nil, nil, nil, 0)
if imgTypeName == "iot-commit" || imgTypeName == "iot-container" || imgTypeName == "iot-raw-image" {
if imgTypeName == "iot-commit" || imgTypeName == "iot-container" || imgTypeName == "iot-raw-image" || imgTypeName == "iot-qcow2-image" {
assert.EqualError(t, err, "Custom mountpoints are not supported for ostree types")
} else if imgTypeName == "iot-installer" || imgTypeName == "iot-simplified-installer" || imgTypeName == "image-installer" {
continue
Expand Down Expand Up @@ -619,7 +649,7 @@ func TestDistro_TestRootMountPoint(t *testing.T) {
imgType, _ := arch.GetImageType(imgTypeName)
testPackageSpecSets := distro_test_common.GetTestingImagePackageSpecSets("kernel", imgType)
_, _, err := imgType.Manifest(bp.Customizations, distro.ImageOptions{}, nil, testPackageSpecSets, nil, 0)
if imgTypeName == "iot-commit" || imgTypeName == "iot-container" || imgTypeName == "iot-raw-image" {
if imgTypeName == "iot-commit" || imgTypeName == "iot-container" || imgTypeName == "iot-raw-image" || imgTypeName == "iot-qcow2-image" {
assert.EqualError(t, err, "Custom mountpoints are not supported for ostree types")
} else if imgTypeName == "iot-installer" || imgTypeName == "iot-simplified-installer" || imgTypeName == "image-installer" {
continue
Expand Down Expand Up @@ -755,7 +785,7 @@ func TestDistro_CustomFileSystemPatternMatching(t *testing.T) {
for _, imgTypeName := range arch.ListImageTypes() {
imgType, _ := arch.GetImageType(imgTypeName)
_, _, err := imgType.Manifest(bp.Customizations, distro.ImageOptions{}, nil, nil, nil, 0)
if imgTypeName == "iot-commit" || imgTypeName == "iot-container" || imgTypeName == "iot-raw-image" {
if imgTypeName == "iot-commit" || imgTypeName == "iot-container" || imgTypeName == "iot-raw-image" || imgTypeName == "iot-qcow2-image" {
assert.EqualError(t, err, "Custom mountpoints are not supported for ostree types")
} else if imgTypeName == "iot-installer" || imgTypeName == "iot-simplified-installer" || imgTypeName == "image-installer" {
continue
Expand Down Expand Up @@ -784,7 +814,7 @@ func TestDistro_CustomUsrPartitionNotLargeEnough(t *testing.T) {
imgType, _ := arch.GetImageType(imgTypeName)
testPackageSpecSets := distro_test_common.GetTestingImagePackageSpecSets("kernel", imgType)
_, _, err := imgType.Manifest(bp.Customizations, distro.ImageOptions{}, nil, testPackageSpecSets, nil, 0)
if imgTypeName == "iot-commit" || imgTypeName == "iot-container" || imgTypeName == "iot-raw-image" {
if imgTypeName == "iot-commit" || imgTypeName == "iot-container" || imgTypeName == "iot-raw-image" || imgTypeName == "iot-qcow2-image" {
assert.EqualError(t, err, "Custom mountpoints are not supported for ostree types")
} else if imgTypeName == "iot-installer" || imgTypeName == "iot-simplified-installer" || imgTypeName == "image-installer" {
continue
Expand Down
101 changes: 89 additions & 12 deletions internal/distro/fedora/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,13 @@ func iotCommitImage(workload workload.Workload,

img := image.NewOSTreeArchive(options.OSTree.ImageRef)

distro := t.Arch().Distro()

img.Platform = t.platform
img.OSCustomizations = osCustomizations(t, packageSets[osPkgsKey], containers, customizations)
if strings.HasPrefix(distro.Name(), "fedora") && !common.VersionLessThan(distro.Releasever(), "38") {
img.OSCustomizations.EnabledServices = append(img.OSCustomizations.EnabledServices, "ignition-firstboot-complete.service", "coreos-ignition-write-issues.service")
}
img.Environment = t.environment
img.Workload = workload

Expand Down Expand Up @@ -324,8 +329,13 @@ func iotContainerImage(workload workload.Workload,

img := image.NewOSTreeContainer(options.OSTree.ImageRef)

distro := t.Arch().Distro()

img.Platform = t.platform
img.OSCustomizations = osCustomizations(t, packageSets[osPkgsKey], containers, customizations)
if strings.HasPrefix(distro.Name(), "fedora") && !common.VersionLessThan(distro.Releasever(), "38") {
img.OSCustomizations.EnabledServices = append(img.OSCustomizations.EnabledServices, "ignition-firstboot-complete.service", "coreos-ignition-write-issues.service")
}
img.ContainerLanguage = img.OSCustomizations.Language
img.Environment = t.environment
img.Workload = workload
Expand Down Expand Up @@ -389,7 +399,7 @@ func iotInstallerImage(workload workload.Workload,
return img, nil
}

func iotRawImage(workload workload.Workload,
func iotQcow2Image(workload workload.Workload,
t *imageType,
customizations *blueprint.Customizations,
options distro.ImageOptions,
Expand All @@ -403,12 +413,73 @@ func iotRawImage(workload workload.Workload,
ContentURL: options.OSTree.ContentURL,
Checksum: options.OSTree.FetchChecksum,
}
img := image.NewOSTreeRawImage(commit)
img := image.NewOSTreeImage(commit)

distro := t.Arch().Distro()

img.Users = users.UsersFromBP(customizations.GetUsers())
img.Groups = users.GroupsFromBP(customizations.GetGroups())

img.KernelOptionsAppend = []string{"modprobe.blacklist=vc4"}
img.Keyboard = "us"
img.Locale = "C.UTF-8"

// Set sysroot read-only only for Fedora 37+
if strings.HasPrefix(distro.Name(), "fedora") && !common.VersionLessThan(distro.Releasever(), "37") {
img.SysrootReadOnly = true
img.KernelOptionsAppend = append(img.KernelOptionsAppend, "rw")
}

img.Platform = t.platform
img.Workload = workload

img.Remote = ostree.Remote{
Name: "fedora-iot",
URL: "https://ostree.fedoraproject.org/iot",
ContentURL: "mirrorlist=https://ostree.fedoraproject.org/iot/mirrorlist",
GPGKeyPaths: []string{"/etc/pki/rpm-gpg/"},
}
img.OSName = "fedora-iot"

if strings.HasPrefix(distro.Name(), "fedora") && !common.VersionLessThan(distro.Releasever(), "38") {
img.Ignition = true
img.IgnitionPlatform = "qemu"
}

if kopts := customizations.GetKernel(); kopts != nil && kopts.Append != "" {
img.KernelOptionsAppend = append(img.KernelOptionsAppend, kopts.Append)
}

// TODO: move generation into LiveImage
pt, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
if err != nil {
return nil, err
}
img.PartitionTable = pt

img.Filename = t.Filename()

return img, nil
}

func iotRawImage(workload workload.Workload,
t *imageType,
customizations *blueprint.Customizations,
options distro.ImageOptions,
packageSets map[string]rpmmd.PackageSet,
containers []container.Spec,
rng *rand.Rand) (image.ImageKind, error) {

commit := ostree.CommitSpec{
Ref: options.OSTree.ImageRef,
URL: options.OSTree.URL,
ContentURL: options.OSTree.ContentURL,
Checksum: options.OSTree.FetchChecksum,
}
img := image.NewOSTreeImage(commit)
img.Compression = "xz"

distro := t.Arch().Distro()

img.Users = users.UsersFromBP(customizations.GetUsers())
img.Groups = users.GroupsFromBP(customizations.GetGroups())
Expand All @@ -434,8 +505,12 @@ func iotRawImage(workload workload.Workload,
}
img.OSName = "fedora-iot"

if bpIgnition := customizations.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" {
img.KernelOptionsAppend = append(img.KernelOptionsAppend, "ignition.config.url="+bpIgnition.FirstBoot.ProvisioningURL)
if strings.HasPrefix(distro.Name(), "fedora") && !common.VersionLessThan(distro.Releasever(), "38") {
img.Ignition = true
img.IgnitionPlatform = "metal"
if bpIgnition := customizations.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" {
img.KernelOptionsAppend = append(img.KernelOptionsAppend, "ignition.config.url="+bpIgnition.FirstBoot.ProvisioningURL)
}
}

if kopts := customizations.GetKernel(); kopts != nil && kopts.Append != "" {
Expand Down Expand Up @@ -468,10 +543,8 @@ func iotSimplifiedInstallerImage(workload workload.Workload,
ContentURL: options.OSTree.ContentURL,
Checksum: options.OSTree.FetchChecksum,
}
rawImg := image.NewOSTreeRawImage(commit)
if !common.VersionLessThan(t.arch.distro.osVersion, "38") {
rawImg.Ignition = true
}
rawImg := image.NewOSTreeImage(commit)
rawImg.Compression = "xz"

rawImg.Users = users.UsersFromBP(customizations.GetUsers())
rawImg.Groups = users.GroupsFromBP(customizations.GetGroups())
Expand All @@ -493,6 +566,14 @@ func iotSimplifiedInstallerImage(workload workload.Workload,
}
rawImg.OSName = "fedora"

if !common.VersionLessThan(t.arch.distro.osVersion, "38") {
rawImg.Ignition = true
rawImg.IgnitionPlatform = "metal"
if bpIgnition := customizations.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" {
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, "ignition.config.url="+bpIgnition.FirstBoot.ProvisioningURL)
}
}

// TODO: move generation into LiveImage
pt, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
if err != nil {
Expand All @@ -502,10 +583,6 @@ func iotSimplifiedInstallerImage(workload workload.Workload,

rawImg.Filename = t.Filename()

if bpIgnition := customizations.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" {
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, "ignition.config.url="+bpIgnition.FirstBoot.ProvisioningURL)
}

if kopts := customizations.GetKernel(); kopts != nil && kopts.Append != "" {
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, kopts.Append)
}
Expand Down
1 change: 0 additions & 1 deletion internal/distro/fedora/package_sets.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,6 @@ func iotCommitPackageSet(t *imageType) rpmmd.PackageSet {
Include: []string{
"fdo-client",
"fdo-owner-cli",
"ignition",
"ignition-edge",
"ssh-key-dir",
},
Expand Down
1 change: 1 addition & 0 deletions internal/distro/rhel8/distro.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ func newDistro(name string, minor int) *distribution {

bareMetalX86Platform := &platform.X86{
BasePlatform: platform.BasePlatform{
ImageFormat: platform.FORMAT_RAW,
FirmwarePackages: []string{
"microcode_ctl", // ??
"iwl1000-firmware",
Expand Down
Loading

0 comments on commit c413206

Please sign in to comment.